diff --git a/config/scripts/capture-live-input-lag.mjs b/config/scripts/capture-live-input-lag.mjs new file mode 100644 index 00000000000..d2282d961d0 --- /dev/null +++ b/config/scripts/capture-live-input-lag.mjs @@ -0,0 +1,184 @@ +import { mkdtemp, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { + startRendererTimingProbe, + stopRendererTimingProbe +} from './idle-cpu-renderer-timing-probe.mjs' + +// Called with an already-attached main Orca page; never launches, focuses, or reloads it. +export async function captureLiveInputLag(page, durationMs = 30_000) { + if (!Number.isFinite(durationMs) || durationMs < 1_000 || durationMs > 60_000) { + throw new Error('Capture duration must be 1–60 seconds') + } + const identity = await page.evaluate(async () => { + if (!window.api?.app?.getIdentity) { + throw new Error('Target is not the main Orca renderer') + } + if (window.__orcaLiveInputLag || window.__orcaIdleCpuTimingProbe) { + throw new Error('A renderer timing probe already exists; stop it before capturing') + } + return window.api.app.getIdentity() + }) + const directory = await mkdtemp(join(tmpdir(), 'orca-input-lag-')) + const cdp = await page.context().newCDPSession(page) + let timingStarted = false + let inputStarted = false + let profilingStarted = false + try { + await startRendererTimingProbe(page) + timingStarted = true + await page.evaluate(() => { + const events = [] + const frames = [] + const observers = [] + const maxEntries = 3_000 + let dropped = 0 + const retain = (list, value) => { + if (list.length < maxEntries) { + list.push(value) + } else { + dropped++ + } + } + const surface = (target) => { + if (!(target instanceof Element)) { + return 'other' + } + if (target.closest('.xterm')) { + return 'terminal' + } + if (target.closest('.monaco-editor')) { + return 'editor' + } + if (target.closest('[contenteditable="true"]')) { + return 'contenteditable' + } + return target.matches('input, textarea') ? 'text-input' : 'other' + } + const onInput = (event) => { + retain(events, { + kind: 'listener', + type: event.type, + surface: surface(event.target), + eventAt: event.timeStamp, + handlerAt: performance.now(), + trusted: event.isTrusted + }) + } + const types = ['keydown', 'beforeinput', 'input', 'compositionstart', 'compositionend'] + for (const type of types) { + document.addEventListener(type, onInput, true) + } + const supported = PerformanceObserver.supportedEntryTypes ?? [] + if (supported.includes('event')) { + const observer = new PerformanceObserver((list) => { + for (const event of list.getEntries()) { + if (!types.includes(event.name)) { + continue + } + retain(events, { + kind: 'event-timing', + type: event.name, + surface: surface(event.target), + eventAt: event.startTime, + processingStart: event.processingStart, + processingEnd: event.processingEnd, + duration: event.duration, + interactionId: event.interactionId + }) + } + }) + observer.observe({ type: 'event', durationThreshold: 16 }) + observers.push(observer) + } + let last = performance.now() + let frameId + const frame = (now) => { + if (now - last > 32) { + retain(frames, { at: now, gapMs: now - last }) + } + last = now + frameId = requestAnimationFrame(frame) + } + frameId = requestAnimationFrame(frame) + const startedAt = performance.now() + const startedAtIso = new Date().toISOString() + window.__orcaLiveInputLag = { + stop: () => { + cancelAnimationFrame(frameId) + for (const type of types) { + document.removeEventListener(type, onInput, true) + } + for (const observer of observers) { + observer.disconnect() + } + delete window.__orcaLiveInputLag + return { + startedAt, + startedAtIso, + endedAt: performance.now(), + visibility: document.visibilityState, + events, + frames, + dropped, + eventTimingSupported: supported.includes('event') + } + } + } + }) + inputStarted = true + await cdp.send('Profiler.enable') + const profileStartWindow = [await page.evaluate(() => performance.now())] + await cdp.send('Profiler.start') + profilingStarted = true + profileStartWindow.push(await page.evaluate(() => performance.now())) + await new Promise((resolve) => setTimeout(resolve, durationMs)) + const { profile } = await cdp.send('Profiler.stop') + profilingStarted = false + const input = await page.evaluate(() => window.__orcaLiveInputLag.stop()) + inputStarted = false + const timing = await stopRendererTimingProbe(page) + await page.evaluate(() => { + delete window.__orcaIdleCpuTimingProbe + }) + timingStarted = false + await writeFile(join(directory, 'renderer.cpuprofile'), JSON.stringify(profile), { + mode: 0o600 + }) + await writeFile( + join(directory, 'input-timing.json'), + JSON.stringify( + { + identity, + input, + timing, + profileStartWindow, + limitation: + 'Keyboard dispatch, handlers and frames only; not PTY echo latency. Event Timing omits short events and rounds durations.' + }, + null, + 2 + ), + { mode: 0o600 } + ) + return { directory, eventRecords: input.events.length, slowFrames: input.frames.length, timing } + } finally { + if (profilingStarted) { + await cdp.send('Profiler.stop').catch(() => {}) + } + if (inputStarted) { + await page.evaluate(() => window.__orcaLiveInputLag?.stop()).catch(() => {}) + } + if (timingStarted) { + await stopRendererTimingProbe(page).catch(() => {}) + await page + .evaluate(() => { + delete window.__orcaIdleCpuTimingProbe + }) + .catch(() => {}) + } + await cdp.send('Profiler.disable').catch(() => {}) + await cdp.detach().catch(() => {}) + } +} diff --git a/config/scripts/capture-running-orca-lag.mjs b/config/scripts/capture-running-orca-lag.mjs new file mode 100644 index 00000000000..718f1cd19a7 --- /dev/null +++ b/config/scripts/capture-running-orca-lag.mjs @@ -0,0 +1,72 @@ +import { writeFile } from 'node:fs/promises' +import { join } from 'node:path' +import { captureLiveInputLag } from './capture-live-input-lag.mjs' +import { connectOrcaMainInspector } from './orca-main-inspector-connection.mjs' + +// Diagnostic-only adapter: Electron CDP on the verified existing renderer; no window actions. +const expectedPid = Number(process.argv[2]) +const rendererId = Number(process.argv[3]) +if (!expectedPid || !rendererId) { + throw new Error('Usage: node capture-running-orca-lag.mjs MAIN_PID WEB_CONTENTS_ID') +} +const connection = await connectOrcaMainInspector(expectedPid, rendererId) +const { send, evaluateMain, evaluateRenderer, contents } = connection +let attached = false +let echoStarted = false +let mainProfiling = false +try { + const identity = await evaluateMain( + `({pid:process.pid,type:${contents}.getType(),rendererPid:${contents}.getOSProcessId(),attached:${contents}.debugger.isAttached()})` + ) + if (identity.pid !== expectedPid || identity.type !== 'window' || identity.attached) { + throw new Error(`Unexpected or already-debugged target: ${JSON.stringify(identity)}`) + } + const before = await evaluateRenderer('window.__orcaTypingDiagnostic.report()') + if (before.sampling.running) { + throw new Error('An existing typing diagnostic is running') + } + await evaluateMain(`${contents}.debugger.attach('1.3')`) + attached = true + const page = { + evaluate: (fn, arg) => evaluateRenderer(`(${fn.toString()})(${JSON.stringify(arg) ?? ''})`), + context: () => ({ + newCDPSession: async () => ({ + send: connection.cdp, + detach: async () => {} + }) + }) + } + await evaluateRenderer('window.__orcaTypingDiagnostic.start()') + echoStarted = true + await send('Profiler.enable') + await send('Profiler.start') + mainProfiling = true + console.log( + JSON.stringify({ captureStarted: new Date().toISOString(), identity, census: before.census }) + ) + const result = await captureLiveInputLag(page, 30_000) + const { profile } = await send('Profiler.stop') + mainProfiling = false + await evaluateRenderer('window.__orcaTypingDiagnostic.stop()') + echoStarted = false + const echo = await evaluateRenderer('window.__orcaTypingDiagnostic.report()') + await writeFile(join(result.directory, 'main.cpuprofile'), JSON.stringify(profile), { + mode: 0o600 + }) + await writeFile(join(result.directory, 'terminal-echo.json'), JSON.stringify(echo, null, 2), { + mode: 0o600 + }) + console.log(JSON.stringify({ ...result, echo }, null, 2)) +} finally { + if (echoStarted) { + await evaluateRenderer('window.__orcaTypingDiagnostic.stop()').catch(() => {}) + } + if (mainProfiling) { + await send('Profiler.stop').catch(() => {}) + } + await send('Profiler.disable').catch(() => {}) + if (attached) { + await evaluateMain(`${contents}.debugger.detach()`).catch(() => {}) + } + connection.close() +} diff --git a/config/scripts/lag-probe-failures.test.mjs b/config/scripts/lag-probe-failures.test.mjs new file mode 100644 index 00000000000..7402bbf6f94 --- /dev/null +++ b/config/scripts/lag-probe-failures.test.mjs @@ -0,0 +1,82 @@ +import assert from 'node:assert/strict' +import { test } from 'vitest' +import { runInNewContext } from 'node:vm' +import { installRendererIpcProbe } from './main-blocking-probe.mjs' +import { connectOrcaMainInspector } from './orca-main-inspector-connection.mjs' + +test('IPC polling records a rejection and permits the next poll', async () => { + let poll + let calls = 0 + const window = { + api: { + app: { + getIdentity: async () => { + if (++calls === 1) { + throw new Error('IPC disconnected') + } + } + } + } + } + runInNewContext(`(${String(installRendererIpcProbe)})()`, { + window, + performance, + Date, + document: { addEventListener() {}, removeEventListener() {} }, + setInterval(callback) { + poll = callback + return 1 + }, + clearInterval() {} + }) + await poll() + await poll() + const { requests } = window.__orcaIpcTimingProbe.stop() + assert.equal(requests.length, 2) + assert.match(requests[0].failed, /IPC disconnected/) + assert.equal(requests[1].failed, undefined) +}) + +test('socket closure rejects outstanding and subsequent requests without timeout timers', async () => { + let socket + const timers = new Set() + class FakeSocket { + static OPEN = 1 + readyState = 1 + constructor() { + socket = this + queueMicrotask(() => this.onopen()) + } + send(payload) { + const { id, params } = JSON.parse(payload) + if (params.expression === 'process.pid') { + queueMicrotask(() => + this.onmessage({ data: JSON.stringify({ id, result: { result: { value: 42 } } }) }) + ) + } + } + close() { + this.readyState = 3 + this.onclose() + } + } + const connect = runInNewContext(`(${String(connectOrcaMainInspector)})`, { + fetch: async () => ({ json: async () => [{ webSocketDebuggerUrl: 'ws://fixture' }] }), + WebSocket: FakeSocket, + setTimeout(callback) { + timers.add(callback) + return callback + }, + clearTimeout(timer) { + timers.delete(timer) + } + }) + const connection = await connect(42) + const first = connection.send('Profiler.start') + const second = connection.send('Profiler.stop') + socket.close() + await assert.rejects(first, /Inspector socket closed/) + await assert.rejects(second, /Inspector socket closed/) + await assert.rejects(connection.send('Profiler.enable'), /not open/) + assert.equal(timers.size, 0) +}) diff --git a/config/scripts/main-blocking-probe.mjs b/config/scripts/main-blocking-probe.mjs new file mode 100644 index 00000000000..93a5372a765 --- /dev/null +++ b/config/scripts/main-blocking-probe.mjs @@ -0,0 +1,120 @@ +export function installMainBlockingProbe() { + if (globalThis.__orcaMainBlockingProbe) { + throw new Error('Main blocking probe already exists') + } + const events = [] + const cleanup = [] + const startedAt = Date.now() + function wrap(object, name, label, sizeOf) { + const original = object[name] + const wrapped = function (...args) { + const start = performance.now() + const epoch = Date.now() + let result + try { + result = Reflect.apply(original, this, args) + return result + } finally { + const durationMs = performance.now() - start + if (durationMs >= 8 && events.length < 2000) { + events.push({ + epoch, + durationMs, + label, + size: sizeOf?.(args, result) ?? null, + stack: new Error('Main blocking call').stack?.split('\n').slice(2, 10) + }) + } + } + } + object[name] = wrapped + cleanup.push(() => { + if (object[name] === wrapped) { + object[name] = original + } + }) + } + wrap(JSON, 'stringify', 'JSON.stringify', (_args, result) => result?.length) + wrap(globalThis, 'structuredClone', 'structuredClone') + wrap(Buffer, 'from', 'Buffer.from', (args) => args[0]?.length) + const hashPrototype = Object.getPrototypeOf( + process.getBuiltinModule('crypto').createHash('sha256') + ) + wrap(hashPrototype, 'update', 'hash.update', (args) => args[0]?.length) + const fs = process.getBuiltinModule('fs') + for (const name of ['existsSync', 'accessSync', 'writeFileSync', 'fsyncSync', 'renameSync']) { + wrap(fs, name, name) + } + const timerGaps = [] + let previous = performance.now() + const timer = setInterval(() => { + const now = performance.now() + const gap = now - previous - 25 + previous = now + if (gap > 20 && timerGaps.length < 2000) { + timerGaps.push({ epoch: Date.now(), gapMs: gap }) + } + }, 25) + timer.unref() + globalThis.__orcaMainBlockingProbe = { + stop() { + clearInterval(timer) + for (const restore of cleanup.toReversed()) { + restore() + } + delete globalThis.__orcaMainBlockingProbe + return { startedAt, endedAt: Date.now(), events, timerGaps } + } + } + return { startedAt } +} + +export function installRendererIpcProbe() { + if (window.__orcaIpcTimingProbe) { + throw new Error('Renderer IPC probe already exists') + } + const requests = [] + const keys = [] + let pending = false + let stopped = false + const timer = setInterval(async () => { + if (pending || stopped) { + return + } + pending = true + const start = performance.now() + const epoch = Date.now() + try { + await window.api.app.getIdentity() + if (requests.length < 2000) { + requests.push({ epoch, durationMs: performance.now() - start }) + } + } catch (error) { + if (requests.length < 2000) { + requests.push({ epoch, durationMs: performance.now() - start, failed: String(error) }) + } + } finally { + pending = false + } + }, 100) + const keydown = (event) => { + if (keys.length < 1000) { + keys.push({ + epoch: Date.now(), + queueMs: performance.now() - event.timeStamp, + terminal: !!event.target?.closest?.('.xterm'), + trusted: event.isTrusted + }) + } + } + document.addEventListener('keydown', keydown, true) + window.__orcaIpcTimingProbe = { + stop() { + stopped = true + clearInterval(timer) + document.removeEventListener('keydown', keydown, true) + delete window.__orcaIpcTimingProbe + return { requests, keys } + } + } +} diff --git a/config/scripts/orca-main-inspector-connection.mjs b/config/scripts/orca-main-inspector-connection.mjs new file mode 100644 index 00000000000..1d77e728f89 --- /dev/null +++ b/config/scripts/orca-main-inspector-connection.mjs @@ -0,0 +1,84 @@ +export async function connectOrcaMainInspector(expectedPid, rendererId = 1) { + const [target] = await (await fetch('http://127.0.0.1:9229/json/list')).json() + const socket = new WebSocket(target.webSocketDebuggerUrl) + await new Promise((resolve, reject) => { + socket.onopen = resolve + socket.onerror = reject + }) + const pending = new Map() + let nextId = 0 + socket.onclose = () => { + for (const [id, callback] of pending) { + pending.delete(id) + clearTimeout(callback.timer) + callback.reject(new Error('Inspector socket closed')) + } + } + socket.onmessage = (event) => { + const message = JSON.parse(event.data) + const callback = pending.get(message.id) + if (!callback) { + return + } + pending.delete(message.id) + clearTimeout(callback.timer) + if (message.error) { + callback.reject(new Error(JSON.stringify(message.error))) + } else { + callback.resolve(message.result) + } + } + function send(method, params = {}) { + return new Promise((resolve, reject) => { + if (socket.readyState !== WebSocket.OPEN) { + reject(new Error('Inspector socket is not open')) + return + } + const id = ++nextId + const timer = setTimeout(() => { + pending.delete(id) + reject(new Error(`Timed out: ${method}`)) + }, 15_000) + pending.set(id, { resolve, reject, timer }) + try { + socket.send(JSON.stringify({ id, method, params })) + } catch (error) { + pending.delete(id) + clearTimeout(timer) + reject(error) + } + }) + } + async function evaluateMain(expression) { + const result = await send('Runtime.evaluate', { + expression, + returnByValue: true, + awaitPromise: true + }) + if (result.exceptionDetails) { + throw new Error(result.result.description ?? JSON.stringify(result.exceptionDetails)) + } + return result.result.value + } + try { + if ((await evaluateMain('process.pid')) !== expectedPid) { + throw new Error('Inspector belongs to a different main process') + } + } catch (error) { + socket.close() + throw error + } + const contents = `process.getBuiltinModule('module').createRequire(process.execPath)('electron').webContents.fromId(${rendererId})` + return { + send, + evaluateMain, + contents, + evaluateRenderer: (expression) => + evaluateMain(`${contents}.executeJavaScript(${JSON.stringify(expression)})`), + cdp: (method, params = {}) => + evaluateMain( + `${contents}.debugger.sendCommand(${JSON.stringify(method)},${JSON.stringify(params)})` + ), + close: () => socket.close() + } +} diff --git a/config/scripts/persistence-call-probe.mjs b/config/scripts/persistence-call-probe.mjs new file mode 100644 index 00000000000..d62df17cc0b --- /dev/null +++ b/config/scripts/persistence-call-probe.mjs @@ -0,0 +1,85 @@ +export function installPersistenceCallProbe() { + const store = globalThis.__orcaLiveStoreProbeTarget + if (!store || globalThis.__orcaPersistenceCallProbe) { + throw new Error('Missing verified live store, or probe already active') + } + const contextSymbol = Object.getOwnPropertySymbols(store).find( + (symbol) => symbol.description === 'PrimaryStateWriteOperations' + ) + const serialization = store[contextSymbol]?.serialization + if (!serialization?.buildStateToSave) { + throw new Error('Live serialization context was not found') + } + const events = [] + const cleanup = [] + function wrap(object, name, describe) { + const descriptor = Object.getOwnPropertyDescriptor(object, name) + const original = object[name] + const wrapped = function (...args) { + const details = describe?.(args) ?? {} + const start = performance.now() + const epoch = Date.now() + let result + try { + result = Reflect.apply(original, this, args) + return result + } finally { + const durationMs = performance.now() - start + if (events.length < 1000) { + events.push({ + name, + epoch, + durationMs, + ...details, + payloadBytes: name === 'buildStateToSave' ? result?.payload?.length : undefined, + stack: + durationMs > 20 + ? new Error('Persistence timing').stack?.split('\n').slice(2, 9) + : undefined + }) + } + } + } + Object.defineProperty(object, name, { value: wrapped, configurable: true, writable: true }) + cleanup.push(() => { + if (object[name] !== wrapped) { + return + } + if (descriptor) { + Object.defineProperty(object, name, descriptor) + } else { + delete object[name] + } + }) + } + wrap(serialization, 'buildStateToSave') + wrap(store, 'flushOrThrow') + wrap(store, 'persistPtyBinding', ([args, hostId]) => { + if (hostId && hostId !== 'local') { + return { local: false } + } + const session = store.getWorkspaceSession() + const key = `${args.tabId}:${args.leafId}` + const worktreeId = args.expectedSourceBinding?.worktreeId ?? args.worktreeId + const tab = session.tabsByWorktree?.[worktreeId]?.find((t) => t.id === args.tabId) + return { + local: true, + tabAlreadyBound: tab?.ptyId === args.ptyId, + leafAlreadyBound: + session.terminalLayoutsByTabId?.[args.tabId]?.ptyIdsByLeafId?.[args.leafId] === args.ptyId, + incarnationAlreadyMatches: + session.terminalPtyIncarnationsByPaneKey?.[key] === args.incarnationId, + layoutExists: !!session.terminalLayoutsByTabId?.[args.tabId]?.root + } + }) + globalThis.__orcaPersistenceCallProbe = { + stop() { + for (const restore of cleanup.toReversed()) { + restore() + } + delete globalThis.__orcaPersistenceCallProbe + delete globalThis.__orcaLiveStoreProbeTarget + return { events } + } + } +} diff --git a/config/scripts/session-search-file-id-e2e/README.md b/config/scripts/session-search-file-id-e2e/README.md new file mode 100644 index 00000000000..ae1de7fd994 --- /dev/null +++ b/config/scripts/session-search-file-id-e2e/README.md @@ -0,0 +1,80 @@ +# Windows session-search file-ID integration reproduction + +Opt-in Windows/NTFS harness for #20551. Run from the fix workspace root with +dependencies, the Electron binary, and Git object `9845bef63a6` available. +Everything generated stays under ignored `notes/search-ipc/`; each run gets fresh +roots and a profile. No real transcripts, WSL discovery, desktop windows, or user +profile are used. The synthetic file is recreated until NTFS assigns a real inode +above `Number.MAX_SAFE_INTEGER`; failure to obtain one fails the test. + +```powershell +$env:ORCA_BACKGROUND_LAUNCH='1' +pnpm exec esbuild config/scripts/session-search-file-id-e2e/run.ts --bundle --platform=node --format=esm --packages=external --outfile=notes/search-ipc/run.mjs +node notes/search-ipc/run.mjs red +# Expected exit 1: initial indexing/query succeeds, subsequent reconciliation fails. +node notes/search-ipc/run.mjs green +# Expected exit 0 for both the lifecycle and fresh-host restart phases. +node config/scripts/session-search-file-id-e2e/verify.cjs +``` + +Run red and green sequentially: their build step reuses the exported source tree. +The verifier checks the expected red failure, green reports, identical oracle +expressions after formatting normalization, and that exactly the two file-ID +SELECT source files differ. It does not turn an arbitrary red failure into success. + +## Exact topology + +The runner exports **LOCAL integration overlay** #20516 head +`9845bef63a6d0b80ec37af82b5b275287b8e17df` with `git archive`, then bundles the real +scanner entry and parent modules with esbuild. It does not check out, stage, or +push overlay sources. Green changes only the two SELECT projections to the CAST +expressions in #20551; red retains the original projections. CLI #20514 is unused. + +An isolated, windowless Electron host installs the production child search +enablement using fixture settings. The production shared scanner client invokes +`spawnAiVaultServiceProcess`, which forks Electron with `ELECTRON_RUN_AS_NODE=1` +and the real `session-scanner-service-entry`. That child owns the production +instance, indexer, SQLite search engine, and IPC request handling. + +Marker queries come from **separate Node client processes over a real Windows +named pipe**, through production `UnixSocketTransport`, production `RpcDispatcher` +and `AI_VAULT_METHODS`, then the search registry/service and scanner IPC. Status +polls and default-off/disabled responses also exercise registered handlers directly. +An independent read-only SQLite connection verifies active FTS rows and committed +file metadata against filesystem size/mtime. The transcript-consumer observation +logs actual replace/append modes without supplying messages or search results. + +Labelled fixture seams, identical in both variants: + +- Parent root resolution returns the existing `isolatedScanRoots` fixture. +- `getSettings` supplies the isolated JSON policy; real enablement/settings-change functions apply it. +- The child's allowlisted environment includes `ORCA_BACKGROUND_LAUNCH=1`. +- Passive child PID, IPC, stderr, and transcript-read observations are added. +- The unused default RPC method catalog is excluded; the dispatcher receives the production `AI_VAULT_METHODS` explicitly. Its runtime context supplies only a fixture runtime ID. + +## Oracle and evidence + +Default-off creates no DB and returns disabled. Enablement indexes the marker; +two **real default 20-second recent timer cycles** and two explicit full passes +preserve it. An append becomes searchable; a rename replacement with equal byte +length and exactly restored mtime removes the old marker and adds the new one. +The scanner restarts, then a second Electron host opens the same profile/DB and +queries again. Disablement followed by an append, explicit reconcile, and 21-second +wait leaves the DB unchanged and the new marker absent. + +`red-latest.json` / `green-latest.json` locate each run. Reports contain parent and +scanner PIDs, executable/Node/Electron versions, IPC events, raw unsafe inode, +queries, DB metadata, read modes, and scanner exit codes. `*-stages.jsonl` gives +live progress; `process-*.log` preserves complete output. `comparison.json` records +the two-source-only comparison. The production scanner shutdown protocol closes +only recorded children; the runner waits for its own Electron hosts and external +clients. Profiles/DBs remain as evidence, not running services. + +## Boundaries not exercised + +This is not a packaged/full Orca desktop launch. The host and scanner are bundled +from production sources by this harness, not electron-vite's complete app build. +The actual runtime authentication/metadata server, CLI routing, remote SSH/relay +transport, and UI are not exercised. Named-pipe framing and dispatcher are real, +but the harness connects them directly with a fixture token; it makes no claim +about production authentication. No session-search UI exists in this topology. diff --git a/config/scripts/session-search-file-id-e2e/client.cjs b/config/scripts/session-search-file-id-e2e/client.cjs new file mode 100644 index 00000000000..1922547f6ac --- /dev/null +++ b/config/scripts/session-search-file-id-e2e/client.cjs @@ -0,0 +1,30 @@ +const { connect } = require('node:net') +const assert = require('node:assert/strict') +assert.equal(process.env.ORCA_BACKGROUND_LAUNCH, '1') +const socket = connect(process.argv[2]) +let buffer = '' +socket.setEncoding('utf8') +socket.setTimeout(10_000, () => socket.destroy(new Error('RPC client timeout'))) +socket.on('connect', () => + socket.write( + `${JSON.stringify({ + id: 'file-id-query', + authToken: 'isolated-fixture', + method: 'aiVault.searchSessions', + params: JSON.parse(process.argv[3]) + })}\n` + ) +) +socket.on('data', (chunk) => { + buffer += String(chunk) + const newline = buffer.indexOf('\n') + if (newline === -1) { + return + } + console.log(JSON.stringify({ pid: process.pid, response: JSON.parse(buffer.slice(0, newline)) })) + socket.end() +}) +socket.on('error', (error) => { + console.error(error) + process.exitCode = 1 +}) diff --git a/config/scripts/session-search-file-id-e2e/host.cjs b/config/scripts/session-search-file-id-e2e/host.cjs new file mode 100644 index 00000000000..17ddbb21ff8 --- /dev/null +++ b/config/scripts/session-search-file-id-e2e/host.cjs @@ -0,0 +1,325 @@ +const { app } = require('electron') +const assert = require('node:assert/strict') +const fs = require('node:fs/promises') +const { existsSync, appendFileSync } = require('node:fs') +const { join } = require('node:path') +const { DatabaseSync } = require('node:sqlite') +const output = process.argv[2] +const phase = process.argv[3] +const profile = join(output, 'profile') +app.setPath('userData', profile) +app.setPath('sessionData', join(profile, 'chromium')) +app.disableHardwareAcceleration() +globalThis.__fileIdChildren = [] +const report = { + phase, + pid: process.pid, + execPath: process.execPath, + versions: process.versions, + stages: [], + children: [], + stderr: [], + ipc: [] +} +globalThis.__fileIdObserveChild = (child) => { + globalThis.__fileIdChildren.push(child) + child.stderr.on('data', (chunk) => report.stderr.push(String(chunk))) + child.on('message', (message) => + report.ipc.push({ pid: child.pid, type: message.type, operation: message.operation }) + ) +} +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) +const sessionId = 'aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee' +const markers = { + initial: 'quartzinitialmarker', + append: 'cobaltappendedmarker', + replacement: 'velvetreplacedmarker', + disabled: 'tungstendisabledmarker' +} +let api +let registration +let transport +const endpoint = `\\\\.\\pipe\\orca-file-id-${process.pid}` +let settings = {} +let transcript +const database = join(profile, 'ai-vault', 'session-search.sqlite') +function record(stage, data = {}) { + const entry = { stage, at: Date.now(), ...data } + report.stages.push(entry) + appendFileSync(join(output, `${phase}-stages.jsonl`), `${JSON.stringify(entry)}\n`) + console.log(stage, JSON.stringify(data)) +} +function inspect(marker) { + const db = new DatabaseSync(database, { readOnly: true }) + try { + const query = db.prepare( + 'SELECT CAST(ino AS TEXT) AS ino, byte_offset, size_bytes, mtime_ms FROM files WHERE path = ?' + ) + const rows = db + .prepare(`SELECT s.session_id FROM messages_fts f JOIN messages m ON m.id=f.rowid + JOIN sessions s ON s.id=m.session_row_id WHERE messages_fts MATCH ?`) + .all(marker) + return { file: query.get(transcript), sessions: rows.map((row) => row.session_id) } + } finally { + db.close() + } +} +async function query(marker, present) { + const result = await api.runProcess({ + program: process.env.ORCA_FILE_ID_NODE, + args: [ + join(output, 'client.cjs'), + endpoint, + JSON.stringify({ query: `"${marker}"`, scope: 'conversation', freshness: 'indexed' }) + ], + env: process.env, + timeoutMs: 15_000 + }) + assert.equal(result.code, 0, result.stderr) + const external = JSON.parse(result.stdout) + assert.equal(external.response.ok, true, JSON.stringify(external)) + const response = external.response.result + assert.equal(response.kind, 'results', JSON.stringify(response)) + assert.equal( + response.hits.some((hit) => hit.sessionId === sessionId), + present, + `RPC ${marker}` + ) + const disk = inspect(marker) + assert.equal(disk.sessions.includes(sessionId), present, `DB ${marker}`) + const actual = await fs.stat(transcript) + assert.equal( + disk.file.byte_offset, + actual.size, + 'Committed cursor covers actual transcript bytes' + ) + assert.equal(disk.file.size_bytes, actual.size) + assert.equal(disk.file.mtime_ms, actual.mtimeMs) + record('query', { marker, present, clientPid: external.pid, endpoint, response, disk }) +} +async function status() { + return api.rpc('aiVault.searchStatus', {}) +} +async function waitFor(predicate, label, timeout = 30_000) { + const until = Date.now() + timeout + while (Date.now() < until) { + const current = await status() + if (predicate(current)) { + return current + } + await sleep(200) + } + throw new Error(`Timed out: ${label}`) +} +async function policy(next) { + const before = settings + settings = next + await fs.writeFile(join(profile, 'fixture-settings.json'), JSON.stringify(settings)) + api.applySessionSearchSettingsChange(before, settings) +} +async function stopChild() { + const children = [...globalThis.__fileIdChildren] + api.resetAiVaultScannerServiceForTests() + for (const child of children) { + const until = Date.now() + 5000 + while (child.exitCode === null && child.signalCode === null && Date.now() < until) { + await sleep(50) + } + assert.ok( + child.exitCode !== null || child.signalCode !== null, + `Child ${child.pid} did not exit` + ) + if (!report.children.some((row) => row.pid === child.pid)) { + report.children.push({ + pid: child.pid, + spawnfile: child.spawnfile, + spawnargs: child.spawnargs, + exitCode: child.exitCode, + signalCode: child.signalCode + }) + } + } +} +async function run() { + assert.equal(process.env.ORCA_BACKGROUND_LAUNCH, '1') + await fs.mkdir(profile, { recursive: true }) + api = require('./production.js') + api.setAppEnvironment({ + getPath: (name) => (name === 'userData' ? profile : app.getPath(name)), + getAppPath: () => output, + getVersion: () => app.getVersion(), + isPackaged: () => false, + onWillQuit: (handler) => app.on('will-quit', handler), + exit: (code) => app.exit(code), + getAppMetrics: () => app.getAppMetrics() + }) + const dispatcher = new api.RpcDispatcher({ + methods: api.AI_VAULT_METHODS, + runtime: { getRuntimeId: () => `file-id-${process.pid}` } + }) + transport = new api.UnixSocketTransport({ endpoint, kind: 'named-pipe' }) + transport.onMessage((message, reply) => { + void dispatcher + .dispatch(JSON.parse(message)) + .then((response) => reply(JSON.stringify(response))) + }) + await transport.start() + record('rpc-transport', { + endpoint, + auth: 'fixture; production auth/metadata server not booted', + methods: 'production AI_VAULT_METHODS', + dispatcher: 'production RpcDispatcher' + }) + const roots = { + ...api.isolatedScanRoots(join(output, 'roots')), + wslHomeDirs: [], + additionalCodexSessionsDirs: [], + executionHostId: 'local' + } + process.env.ORCA_FILE_ID_ROOTS = JSON.stringify(roots) + await fs.mkdir(roots.claudeProjectsDir, { recursive: true }) + transcript = join(roots.claudeProjectsDir, `${sessionId}.jsonl`) + if (phase === 'restart') { + settings = JSON.parse(await fs.readFile(join(profile, 'fixture-settings.json'), 'utf8')) + assert.equal(settings.aiVaultSearch.enabled, true) + const beforeRestart = inspect(markers.replacement) + registration = api.installChildSessionSearchService({ + dataRoot: profile, + getSettings: () => settings + }) + await waitFor((s) => s.filesIndexed === 1 && s.phase === 'current', 'Electron host restart') + await query(markers.append, false) + await query(markers.replacement, true) + assert.deepEqual(inspect(markers.replacement), beforeRestart) + record('app-host-restart-same-db') + await disableAndCheck() + return + } + const body = `${api.claudeLines([markers.initial], sessionId, 0).join('\n')}\n` + await fs.writeFile(transcript, body) + let raw = await fs.stat(transcript, { bigint: true }) + for (let n = 0; raw.ino <= BigInt(Number.MAX_SAFE_INTEGER) && n < 512; n++) { + await fs.unlink(transcript) + await fs.writeFile(transcript, body) + raw = await fs.stat(transcript, { bigint: true }) + } + assert.ok(raw.ino > BigInt(Number.MAX_SAFE_INTEGER), 'NTFS must supply an actual unsafe inode') + record('fixture', { + transcript, + rawIno: raw.ino.toString(), + numericIno: BigInt(Number(raw.ino)).toString() + }) + registration = api.installChildSessionSearchService({ + dataRoot: profile, + getSettings: () => settings + }) + assert.ok(registration) + assert.equal((await status()).enabled, false) + assert.deepEqual(await api.rpc('aiVault.searchSessions', { query: markers.initial }), { + kind: 'unavailable', + reason: 'disabled' + }) + assert.equal(existsSync(database), false) + record('default-off') + await policy({ aiVaultSearch: { enabled: true, historyDays: null } }) + const initial = await waitFor( + (s) => s.filesIndexed === 1 && s.phase === 'current', + 'initial indexing' + ) + assert.equal(inspect(markers.initial).file.ino, BigInt(Number(raw.ino)).toString()) + await query(markers.initial, true) + record('initial-indexing', { status: initial }) + let recent = initial + for (let n = 0; n < 2; n++) { + const previous = recent + recent = await waitFor( + (s) => s.lastReconcileAt > previous.lastReconcileAt, + 'recent timer reconciliation' + ) + assert.equal( + recent.lastSweepCompletedAt, + initial.lastSweepCompletedAt, + 'Expected a recent pass' + ) + await query(markers.initial, true) + record('recent-pass', { status: recent }) + } + for (let n = 0; n < 2; n++) { + await api.reconcileSessionSearchInService() + await query(markers.initial, true) + record('full-pass', { status: await status() }) + } + await fs.appendFile( + transcript, + `${api.claudeLines([markers.append], sessionId, 10).join('\n')}\n` + ) + const frozen = new Date(Math.floor((await fs.stat(transcript)).mtimeMs)) + await fs.utimes(transcript, frozen, frozen) + await api.reconcileSessionSearchInService() + await query(markers.append, true) + const before = await fs.stat(transcript) + const replacement = `${transcript}.replacement` + const replacementBody = (await fs.readFile(transcript, 'utf8')).replaceAll( + markers.append, + markers.replacement + ) + assert.equal(Buffer.byteLength(replacementBody), before.size) + await fs.writeFile(replacement, replacementBody) + await fs.rename(replacement, transcript) + await fs.utimes(transcript, before.atime, before.mtime) + const after = await fs.stat(transcript) + assert.equal(after.size, before.size) + assert.equal(after.mtimeMs, before.mtimeMs) + assert.notEqual(after.ino, before.ino) + await api.reconcileSessionSearchInService() + await query(markers.append, false) + await query(markers.replacement, true) + record('replacement', { beforeIno: before.ino, afterIno: after.ino }) + await stopChild() + await waitFor((s) => s.filesIndexed === 1 && s.phase === 'current', 'scanner restart') + await query(markers.append, false) + await query(markers.replacement, true) + record('service-restart') +} +async function disableAndCheck() { + await policy({ aiVaultSearch: { enabled: false, historyDays: null } }) + await waitFor((s) => !s.enabled, 'disable') + const snapshot = inspect(markers.replacement) + await fs.appendFile( + transcript, + `${api.claudeLines([markers.disabled], sessionId, 20).join('\n')}\n` + ) + await api.reconcileSessionSearchInService() + await sleep(21_000) + assert.deepEqual(await api.rpc('aiVault.searchSessions', { query: markers.disabled }), { + kind: 'unavailable', + reason: 'disabled' + }) + assert.deepEqual(inspect(markers.replacement), snapshot) + assert.deepEqual(inspect(markers.disabled).sessions, []) + record('disabled-no-indexing') +} +app.whenReady().then(async () => { + try { + await run() + report.ok = true + } catch (error) { + report.ok = false + report.error = error.stack + console.error(error) + } finally { + registration?.dispose() + await transport?.stop() + if (api) { + await stopChild().catch((error) => { + report.cleanupError = String(error) + report.ok = false + }) + } + if (report.stderr.some((text) => text.includes('[ai-vault-search]'))) { + report.ok = false + } + await fs.writeFile(join(output, `report-${phase}.json`), JSON.stringify(report, null, 2)) + app.exit(report.ok ? 0 : 1) + } +}) diff --git a/config/scripts/session-search-file-id-e2e/run.ts b/config/scripts/session-search-file-id-e2e/run.ts new file mode 100644 index 00000000000..9df3efc5e3e --- /dev/null +++ b/config/scripts/session-search-file-id-e2e/run.ts @@ -0,0 +1,194 @@ +import assert from 'node:assert/strict' +import { mkdir, readFile, writeFile, copyFile } from 'node:fs/promises' +import { resolve, join, relative } from 'node:path' +import { createHash } from 'node:crypto' +import { build } from 'esbuild' +import { runProcess } from '../../../src/shared/child-process/run-process' + +const root = process.cwd() +const evidence = resolve('notes/search-ipc') +const overlay = join(evidence, 'overlay') +const wiring = '9845bef63a6' +const mode = process.argv[2] +assert.equal(process.platform, 'win32', 'This harness requires native Windows and NTFS') +assert.ok(mode === 'red' || mode === 'green', 'Pass red or green') +assert.equal(process.env.ORCA_BACKGROUND_LAUNCH, '1') +const output = join(evidence, mode, String(Date.now())) +await mkdir(output, { recursive: true }) + +async function command(program: string, args: string[]) { + const result = await runProcess({ program, args, cwd: root, timeoutMs: 120_000 }) + assert.equal(result.code, 0, result.stderr) + return result.stdout.trim() +} + +// The overlay is exported, never checked out or staged on the fix branch. +await mkdir(overlay, { recursive: true }) +await command('git', [ + 'archive', + '--format=tar', + `--output=${join(evidence, 'overlay.tar')}`, + wiring, + 'src' +]) +await command('tar', [ + '-xf', + relative(root, join(evidence, 'overlay.tar')), + '-C', + relative(root, overlay) +]) +const edits: { path: string; sha256: string }[] = [] +function replaceOnce(source: string, before: string, after: string) { + assert.equal(source.split(before).length, 2, `Expected exactly one injection: ${before}`) + return source.replace(before, after) +} + +const adapter = join(output, 'adapter.mjs') +const source = (path: string) => JSON.stringify(join(overlay, 'src', path)) +await writeFile( + adapter, + ` +export { installChildSessionSearchService, applySessionSearchSettingsChange } from ${source('main/ai-vault-search/session-search-enablement.ts')}; +export { resetAiVaultScannerServiceForTests, reconcileSessionSearchInService } from ${source('main/ai-vault/session-scanner-service-spawn.ts')}; +export { setAppEnvironment } from ${source('shared/app-environment.ts')}; +export { isolatedScanRoots } from ${source('main/ai-vault/session-scanner-test-fixtures.ts')}; +export { claudeLines } from ${source('main/ai-vault-search/session-search-indexer-test-fixture.ts')}; +export { runProcess } from ${source('shared/child-process/run-process.ts')}; +export { UnixSocketTransport } from ${source('main/runtime/rpc/unix-socket-transport.ts')}; +export { RpcDispatcher } from ${source('main/runtime/rpc/dispatcher.ts')}; +export { AI_VAULT_METHODS } from ${source('main/runtime/rpc/methods/ai-vault.ts')}; +import { buildRegistry } from ${source('main/runtime/rpc/core.ts')}; +import { AI_VAULT_METHODS } from ${source('main/runtime/rpc/methods/ai-vault.ts')}; +const registry = buildRegistry(AI_VAULT_METHODS); +export async function rpc(name, params) { + const method = registry.get(name); + if (!method || !name.startsWith('aiVault.search')) throw new Error('Unexpected method'); + return method.handler(method.params.parse(params), {}); +} +` +) + +await build({ + entryPoints: { + production: adapter, + 'session-scanner-service-entry': join( + overlay, + 'src/main/ai-vault/session-scanner-service-entry.ts' + ) + }, + outdir: output, + platform: 'node', + format: 'cjs', + bundle: true, + packages: 'external', + define: { ORCA_FEATURE_WALL_ENABLED: 'true' }, + plugins: [ + { + name: 'labelled-local-fixtures', + setup(api) { + api.onLoad({ filter: /\.ts$/ }, async (args) => { + let contents = await readFile(args.path, 'utf8') + const path = args.path.replaceAll('\\', '/') + if (path.endsWith('/runtime/rpc/methods/index.ts')) { + // DispatcherOptions explicitly supplies AI_VAULT_METHODS; don't load unrelated default methods. + contents = 'export const ALL_RPC_METHODS = []' + } + if (path.endsWith('/cached-session-list.ts')) { + contents = replaceOnce( + contents, + ' const [additionalCodexHomes, wslHomeDirs] = await Promise.all([', + ' return JSON.parse(process.env.ORCA_FILE_ID_ROOTS!);\n const [additionalCodexHomes, wslHomeDirs] = await Promise.all([' + ) + } + if (path.endsWith('/session-scanner-service-env.ts')) { + contents = replaceOnce( + contents, + " env.ELECTRON_RUN_AS_NODE = '1'", + " env.ORCA_BACKGROUND_LAUNCH = '1'\n env.ELECTRON_RUN_AS_NODE = '1'" + ) + } + if (path.endsWith('/session-scanner-service-spawn.ts')) { + contents = replaceOnce( + contents, + ' lowerAiVaultServicePriority(child.pid)', + ' globalThis.__fileIdObserveChild?.(child)\n lowerAiVaultServicePriority(child.pid)' + ) + } + if (path.endsWith('/session-scanner-service-entry.ts')) { + contents = `import { registerTranscriptConsumer } from './session-transcript-consumers'; +registerTranscriptConsumer({beginRead: start => { console.error('[file-id-read]', JSON.stringify({mode:start.mode,path:start.candidate.file.path})); return null }}); +console.error('[file-id-child]', JSON.stringify({pid:process.pid,execPath:process.execPath,versions:process.versions,background:process.env.ORCA_BACKGROUND_LAUNCH}));\n${contents}` + } + if (mode === 'green' && path.endsWith('/session-search-store.ts')) { + contents = replaceOnce( + contents, + 'SELECT path, dev, ino, mtime_ms', + 'SELECT path, CAST(dev AS REAL) AS dev, CAST(ino AS REAL) AS ino, mtime_ms' + ) + } + if (mode === 'green' && path.endsWith('/session-search-index-writer.ts')) { + contents = replaceOnce( + contents, + 'SELECT dev, ino, byte_offset', + 'SELECT CAST(dev AS REAL) AS dev, CAST(ino AS REAL) AS ino, byte_offset' + ) + } + edits.push({ + path: path.replace(overlay.replaceAll('\\', '/'), ''), + sha256: createHash('sha256').update(contents).digest('hex') + }) + return { contents, loader: 'ts' } + }) + } + } + ] +}) +await copyFile( + join(root, 'config/scripts/session-search-file-id-e2e/host.cjs'), + join(output, 'host.cjs') +) +await copyFile( + join(root, 'config/scripts/session-search-file-id-e2e/client.cjs'), + join(output, 'client.cjs') +) +await writeFile( + join(output, 'topology.json'), + JSON.stringify( + { + wiring: await command('git', ['rev-parse', wiring]), + fix: await command('git', ['rev-parse', 'HEAD']), + mode, + injections: [ + 'isolated root resolver', + 'background child env', + 'child PID/error/read observation', + 'unused default RPC catalog excluded; explicit production AI_VAULT_METHODS' + ], + files: edits.sort((a, b) => a.path.localeCompare(b.path)) + }, + null, + 2 + ) +) +await writeFile(join(evidence, `${mode}-latest.json`), JSON.stringify({ output })) +for (const phase of ['lifecycle', 'restart']) { + console.log(JSON.stringify({ mode, phase, output })) + const result = await runProcess({ + program: join(root, 'node_modules/electron/dist/electron.exe'), + args: [join(output, 'host.cjs'), output, phase], + cwd: output, + env: { + ...process.env, + ORCA_BACKGROUND_LAUNCH: '1', + ELECTRON_RUN_AS_NODE: undefined, + ORCA_FILE_ID_NODE: process.execPath + }, + timeoutMs: 180_000 + }) + await writeFile(join(output, `process-${phase}.log`), result.stdout + result.stderr) + console.log(JSON.stringify({ mode, phase, code: result.code, timedOut: result.timedOut, output })) + process.exitCode = result.code ?? 1 + if (process.exitCode !== 0) { + break + } +} diff --git a/config/scripts/session-search-file-id-e2e/verify.cjs b/config/scripts/session-search-file-id-e2e/verify.cjs new file mode 100644 index 00000000000..180bf4cf154 --- /dev/null +++ b/config/scripts/session-search-file-id-e2e/verify.cjs @@ -0,0 +1,62 @@ +const assert = require('node:assert/strict') +const { readFileSync, writeFileSync } = require('node:fs') +const { join, resolve } = require('node:path') +const { createHash } = require('node:crypto') +const { transformSync } = require('esbuild') +const evidence = resolve('notes/search-ipc') +const json = (path) => JSON.parse(readFileSync(path, 'utf8')) +const red = json(join(evidence, 'red-latest.json')).output +const green = json(join(evidence, 'green-latest.json')).output +const before = json(join(red, 'topology.json')) +const after = json(join(green, 'topology.json')) +assert.equal(before.wiring, after.wiring) +assert.deepEqual(before.injections, after.injections) +const oldFiles = new Map(before.files.map((row) => [row.path, row.sha256])) +assert.equal(oldFiles.size, after.files.length) +const changed = after.files + .filter((row) => oldFiles.get(row.path) !== row.sha256) + .map((row) => row.path) + .sort() +assert.deepEqual(changed, [ + '/src/main/ai-vault-search/session-search-index-writer.ts', + '/src/main/ai-vault-search/session-search-store.ts' +]) +for (const name of ['host.cjs', 'client.cjs']) { + // Ignore formatter-only differences; preserve every expression and assertion. + const hash = (root) => + createHash('sha256') + .update( + transformSync(readFileSync(join(root, name), 'utf8'), { + loader: 'js', + minifyWhitespace: true + }).code + ) + .digest('hex') + assert.equal(hash(red), hash(green), `Identical oracle: ${name}`) +} +const failed = json(join(red, 'report-lifecycle.json')) +assert.equal(failed.ok, false) +assert.match(failed.stderr.join(''), /RangeError: Value is too large/) +assert.ok(failed.stages.some((row) => row.stage === 'initial-indexing')) +const reports = [ + json(join(green, 'report-lifecycle.json')), + json(join(green, 'report-restart.json')) +] +for (const report of reports) { + assert.equal(report.ok, true) + assert.ok(report.ipc.some((row) => row.operation === 'searchSessions')) + assert.ok(report.stages.some((row) => row.stage === 'query' && row.clientPid !== report.pid)) + assert.ok(report.children.every((child) => child.exitCode === 0)) +} +assert.notEqual(reports[0].pid, reports[1].pid) +const result = { + ok: true, + wiring: before.wiring, + changed, + red, + green, + parentPids: [failed.pid, ...reports.map((row) => row.pid)], + childPids: [failed, ...reports].flatMap((report) => report.children.map((child) => child.pid)) +} +writeFileSync(join(evidence, 'comparison.json'), JSON.stringify(result, null, 2)) +console.log(JSON.stringify(result)) diff --git a/config/scripts/terminal-render-phase-probe.mjs b/config/scripts/terminal-render-phase-probe.mjs new file mode 100644 index 00000000000..a5032712d25 --- /dev/null +++ b/config/scripts/terminal-render-phase-probe.mjs @@ -0,0 +1,129 @@ +/* eslint-disable no-control-regex -- Terminal control-sequence metadata, never input text. */ +export function installTerminalRenderPhaseProbe() { + if (window.__orcaRenderPhaseProbe || !window.__orcaLiveRenderPanes) { + throw new Error('Missing verified pane references, or another probe is active') + } + const events = [] + const cleanup = [] + let dropped = 0 + const startedAt = performance.now() + function record(pane, kind, extra = {}) { + if (!pane.terminal.element?.contains(document.activeElement)) { + return + } + const core = pane.terminal._core + if (events.length >= 5000) { + dropped++ + return + } + events.push({ + at: performance.now(), + leafId: pane.leafId, + kind, + paused: core?._renderService?._isPaused, + sync: core?.coreService?.decPrivateModes?.synchronizedOutput, + ...extra + }) + } + function wrap(object, key, makeWrapper) { + const original = object?.[key] + if (typeof original !== 'function') { + return + } + const wrapped = makeWrapper(original) + object[key] = wrapped + cleanup.push(() => { + if (object[key] === wrapped) { + object[key] = original + } + }) + } + function subscribe(object, key, listener) { + const disposable = object?.[key]?.(listener) + if (disposable) { + cleanup.push(() => disposable.dispose()) + } + } + for (const pane of window.__orcaLiveRenderPanes) { + const terminal = pane.terminal + const service = terminal?._core?._renderService + if (!service) { + continue + } + subscribe(terminal, 'onData', (data) => record(pane, 'dispatch', { bytes: data.length })) + subscribe(terminal, 'onWriteParsed', () => record(pane, 'parsed')) + subscribe(terminal, 'onRender', () => record(pane, 'public-render')) + subscribe(service, 'onRender', () => record(pane, 'service-render')) + wrap( + terminal, + 'write', + (original) => + function (data, ...args) { + if (terminal.element?.contains(document.activeElement)) { + const text = typeof data === 'string' ? data : new TextDecoder().decode(data) + const controls = [...text.matchAll(/\x1b\[([0-?]*)([ -/]*)([@-~])/g)] + const withoutControls = text + .replace(/\x1b\][\s\S]*?(?:\x07|\x1b\\)/g, '') + .replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, '') + .replace(/\x1b[()][0-~]/g, '') + .replace(/[\x00-\x1f\x7f]/g, '') + record(pane, 'write', { + bytes: data.length, + printableChars: withoutControls.length, + syncStarts: controls.filter((c) => c[1] === '?2026' && c[3] === 'h').length, + syncEnds: controls.filter((c) => c[1] === '?2026' && c[3] === 'l').length, + csiFinals: controls.map((c) => c[3]).join('') + }) + } + return original.call(this, data, ...args) + } + ) + wrap( + service, + 'refreshRows', + (original) => + function (start, end, sync, redrawOnly) { + record(pane, 'refresh-request', { + start, + end, + synchronous: !!sync, + redrawOnly: !!redrawOnly + }) + return original.call(this, start, end, sync, redrawOnly) + } + ) + const renderer = service._renderer?.value ?? service._renderer + wrap( + renderer, + 'renderRows', + (original) => + function (...args) { + const before = performance.now() + const result = original.apply(this, args) + record(pane, 'render-rows', { duration: performance.now() - before }) + return result + } + ) + } + const keydown = (event) => { + const pane = window.__orcaLiveRenderPanes.find((p) => + p.terminal.element?.contains(event.target) + ) + if (pane) { + record(pane, 'keydown', { eventAt: event.timeStamp, trusted: event.isTrusted }) + } + } + document.addEventListener('keydown', keydown, true) + cleanup.push(() => document.removeEventListener('keydown', keydown, true)) + window.__orcaRenderPhaseProbe = { + stop() { + for (const dispose of cleanup.toReversed()) { + dispose() + } + delete window.__orcaRenderPhaseProbe + delete window.__orcaLiveRenderPanes + return { startedAt, endedAt: performance.now(), events, dropped } + } + } + return { startedAt, panes: window.__orcaLiveRenderPanes.length } +} diff --git a/config/tsconfig.cli.json b/config/tsconfig.cli.json index 70d52e0802c..43eac7cb024 100644 --- a/config/tsconfig.cli.json +++ b/config/tsconfig.cli.json @@ -4,6 +4,9 @@ "../src/cli/**/*", "../src/shared/**/*", "../src/main/agent-state-file-reader.ts", + "../src/main/agent-hooks/grok-replay-guard.ts", + "../src/main/claude/hook-script.ts", + "../src/main/claude/claude-session-end-hook-capability.ts", "../src/main/agent-hooks/hook-stdin-contract.ts", "../src/main/agent-hooks/hook-post-command.ts", "../src/main/agent-hooks/hook-config-write-path.ts", diff --git a/docs/assets/readme-downloads.svg b/docs/assets/readme-downloads.svg index 2214ed564bc..08237c15016 100644 --- a/docs/assets/readme-downloads.svg +++ b/docs/assets/readme-downloads.svg @@ -1,5 +1,5 @@ - - downloads: 50m + + downloads: 51m @@ -15,7 +15,7 @@ downloads downloads - 50m - 50m + 51m + 51m diff --git a/docs/reference/runtime-file-base64-padding.md b/docs/reference/runtime-file-base64-padding.md new file mode 100644 index 00000000000..3715855eaa0 --- /dev/null +++ b/docs/reference/runtime-file-base64-padding.md @@ -0,0 +1,92 @@ +# Runtime file Base64 padding + +Padded runtime file writes must have a length divisible by four. Empty strings and +unpadded Base64 with length modulo four equal to zero, two, or three remain valid. +The change rejects exactly the previously accepted strings containing trailing +padding whose total length modulo four is two or three. It does not enforce +canonical unused pad bits or change the alphabet. + +## Boundary evidence + +| Input | Before | After | +| ------------------------- | ------ | ------ | +| `A=` | Accept | Reject | +| `AA==` | Accept | Accept | +| `AAA=` | Accept | Accept | +| `AAAA` | Accept | Accept | +| `''` | Accept | Accept | +| `A` | Reject | Reject | +| `==` | Accept | Reject | +| `AA=A` (interior padding) | Reject | Reject | +| `AA=` | Accept | Reject | +| `A==` | Accept | Reject | +| `AAAA==` | Accept | Reject | +| `AA`, `AAA` (unpadded) | Accept | Accept | + +`Buffer.from('A=', 'base64')` decodes to zero bytes. Rejecting malformed padding at +the RPC boundary prevents an accepted request from silently writing different bytes. + +## Caller census + +| Caller / surface | Reachability and compatibility verdict | +| ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Desktop `runtime-file-import-client.ts` → `uploadRuntimeFileWithoutClobber` → `writeRuntimeBase64File` | The only production producer of `files.writeBase64` and `files.writeBase64Chunk`. Staging in `filesystem-runtime-upload-staging.ts` encodes the complete file with `buffer.toString('base64')`; newly rejected values cannot be produced. | +| Desktop single-frame uploads | Sends the staged string unchanged when its length is at most 512 × 1024 characters. Standard Node Base64 always has length divisible by four. Empty files remain accepted. | +| Desktop chunked uploads | Slices the encoded stream at 512 × 1024 = 524,288 characters, divisible by four. Every offset and every complete chunk is quartet-aligned. The final chunk is the difference of two multiples of four, including when it ends in `=` or `==`. No separately assembled final chunk or per-chunk padding is added. | +| Web implementation of `stageExternalPathsForRuntimeUpload` | Returns an empty source list; no file-write payload is produced. | +| Mobile file editor | Uses `files.writeTerminalArtifact` with text content and its separate schema. Does not reach this predicate. | +| Mobile clipboard / image attachments | Uses `clipboard.startImageUpload`, `clipboard.appendImageUploadChunk`, `clipboard.commitImageUpload`, and the `clipboard.saveImageAsTempFile` fallback. Their validator is `isValidBase64` in `clipboard-params.ts`, not `isValidRuntimeFileBase64`. Unchanged, including the mobile normalizer's existing permissive padding behavior. | +| CLI | No producer of either Base64 file-write method. File commands in `src/cli/handlers/file.ts` call `files.open` / `files.openDiff`; other CLI RPC call sites do not construct Base64 file writes. | +| Generated params catalog | References both schemas; `RpcParams` consumers use inferred types. Mobile's entry point is `export type` only, so no new client-side parsing occurs. | +| RPC dispatch | `files-mutation-methods.ts` registers both schemas. The chunk schema extends the whole-file schema; these are the only runtime consumers of the predicate. Direct runtime/provider calls do not parse these schemas. | + +Repository-wide searches covered method names, schema names, the predicate and its +pattern, and all callers of the upload/staging functions. Targeted history search +on `HEAD` under `mobile/src` found no introduction/removal of the affected methods +or predicate. The local release refs `mobile-ios-v0.0.27` and `mobile-v0.0.13` also +contain no callers of either Base64 file-write method; the iOS ref uses the separate +clipboard and terminal-artifact methods above. No shipped mobile producer of a +newly rejected value was found in this source/history audit. + +## Remote and workspace compatibility + +Old desktop clients using the audited producer send valid quartets to a new host. +A new client still sends the same bytes to an old host. No method, field, opcode, +or host-published content changes. This follows the mixed-version requirements in +[remote-wire-compatibility.md](./remote-wire-compatibility.md). + +The RPC validation runs before workspace resolution and provider selection, so the +same rule applies to folder workspaces, git worktrees, local hosts, and SSH hosts. +SSH ownership fences and provider writes are unchanged. Arbitrary external RPC +callers sending malformed padding will now receive a validation error; valid +padded and unpadded payloads remain accepted. + +## Regression evidence + +`src/main/runtime/rpc/methods/files-base64-padding.test.ts` exercises both actual RPC +registrations, asserts rejected input never reaches the writer, and verifies +accepted content is forwarded unchanged. With the original predicate, the test +run produced **16 failed / 16 passed**; all 16 failures were newly rejected padding +shapes accepted by the old implementation. This was run before editing the predicate. + +The existing desktop external-import test now uses a final `AA==` chunk after a +524,288-character first chunk, pinning padded final-chunk forwarding in the real +upload path. No producer changes or clipboard validation changes were necessary. + +## Validation results + +All test/typecheck commands used `ORCA_BACKGROUND_LAUNCH=1`. + +- `pnpm tc`: exit 0; all root typecheck projects passed. +- `pnpm exec vitest run src/main/runtime/rpc`: 277 files passed, one failed; + 2,419 tests passed, two timed out, one skipped. Both timeouts were in the unchanged + `terminal-output-frame-chunks-equivalence.test.ts` (5s surrogate-range test and + 30s 800-payload fuzz test). +- `pnpm --dir mobile typecheck`: exit 0 (`tsc --noEmit`). +- `pnpm run check:code-quality:changed`: exit 0; code quality, type-aware code + quality, and React Doctor each reported zero new findings across three source files. +- Focused run with `--config config/vitest.config.ts --maxWorkers=2`: all three + files / 58 tests passed, covering padding, desktop external imports, and the + terminal-output equivalence file that timed out in the initial run. +- Full RPC rerun with `--maxWorkers=2`: exit 0; all 278 files passed, + 2,421 tests passed and one skipped (198.34s). No timeout overrides were needed. diff --git a/docs/reference/task-provider-identity-validation.md b/docs/reference/task-provider-identity-validation.md new file mode 100644 index 00000000000..4dba0760aab --- /dev/null +++ b/docs/reference/task-provider-identity-validation.md @@ -0,0 +1,81 @@ +# Task provider identity RPC validation + +The automation RPC identity schema follows `src/shared/task-provider-identity.ts`, +re-exported by `src/shared/task-source-context.ts`. Only GitHub requires fields beyond +`provider`: `owner` and `repo` are strings, and `host` is optional. GitLab, Linear, +and Jira fields are optional nullable strings. Requiring a GitLab project or a +Linear workspace/Jira site would contradict the domain type and account-wide scopes. + +The discriminated union validates these existing field types without trimming, +coercing, or stripping identity fields. Unknown fields pass through as they did under +`z.custom`, including fields from newer clients. Absent and explicit-null identities +remain distinct. The schema does not infer providers from owner/repo or require a +git worktree, repository slug, or local execution host for a source context. + +## Producer census + +Paths below are relative to the repository root. Searches covered production +`providerIdentity`, `TaskProviderIdentity`, `sourceContext`, and +`linkedTaskSourceContext` uses across desktop, shared code, mobile, and CLI. + +| Producer or forwarding path | Populated verdict | +| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `src/shared/project-host-setup-projection.ts`: `getProjectProviderIdentity` | GitHub owner/repo populated together, or no identity. Supplies project identities consumed by desktop and migration. | +| `src/renderer/src/components/task-page-source-context.tsx`: `getTaskPageRepoSourceContext` | GitHub fields populated through projection, or null. GitLab uses explicit provider and `buildGitLabProviderIdentity`; projectId/project/webUrl populated, namespace can be null. | +| Same file: `buildGitLabProviderIdentity` | GitLab fields come from project path/host; missing path components become null. No required GitLab field is invented. | +| `src/renderer/src/hooks/composer-state/source-context-state.ts` | Derived GitHub context carries a complete project identity or null. Jira folder/project-group context explicitly has null identity. Draft/linked contexts are forwarded. | +| `src/renderer/src/components/use-task-page-source-availability.ts` | Linear workspaceId/name and Jira siteId/URL can be null for account-wide selections; team/project fields are not populated. Valid under the existing optional-field contract. | +| `src/renderer/src/components/task-page-jira-item-source-context.ts` | Bound issue context populates siteId, siteUrl, projectKey. | +| `src/renderer/src/components/new-workspace/use-jira-url-source.ts` | Bound URL issue context populates siteId, siteUrl, projectKey. | +| `src/renderer/src/components/worktree-jump-palette-create-worktree.ts` | Linear teamId/key populated; workspaceId/name may be null. | +| `src/shared/task-source-context.ts`: normalize/build functions | GitHub missing owner/repo becomes null identity; other providers' missing fields become null. Provider mismatch becomes null, never an inferred provider. | +| `src/cli/handlers/automation-handler-flags.ts`, `src/cli/handlers/automations.ts` | Explicit JSON source-context input is normalized before create/update. GitHub fields populated or null identity; other fields nullable. Omitted/null context preserved by flag handling. | +| `src/main/persistence/scheduling-automations/automation-context-migration.ts` | Builds source context from projected complete GitHub identity, or null context. | +| Desktop automation save/scoped-list/host clients and web transport | Forward existing source contexts, not new identity constructors. `automation-orca-save.ts` forwards the current automation context or null. Legacy arbitrary malformed RPC input is deliberately rejected by the new schema. | +| Mobile | No task-provider identity/source-context constructor or sender found. `mobile/src/components/new-workspace-project-targets.ts` uses project identity solely for display. | + +## Compatibility evidence and limits + +Read `docs/reference/remote-wire-compatibility.md` before changing validation. +A source search against release tag `v1.4.199` also finds no mobile +`sourceContext`/`linkedTaskSourceContext` sender; its sole `providerIdentity` use +is the display-only project target above. The released CLI flag reader also calls +`normalizeTaskSourceContext`. This is source-level evidence for the checked release, +not a claim to have executed every historical mobile binary. + +No shipped mobile producer with a newly rejected payload was found. No new required +field was added to the domain contract. GitLab, Linear, and Jira discriminant-only +identities remain valid. Folder-workspace null/absent identities remain valid on +both local and SSH hosts. No execution/status logic or client-side parsing changed. + +## Regression evidence + +`src/main/runtime/rpc/methods/task-provider-identity.test.ts` checks unchanged valid +identities for all four providers, required GitHub fields, every declared field's +type, optional/null non-GitHub fields, unknown-field preservation, explicit GitLab +discrimination with owner/repo present, local/SSH folder contexts, and update patches. + +The focused run passed 81 tests. Temporarily replacing GitHub's field validators +with optional `z.unknown()` validators (discriminant-only acceptance) caused 17 +failures and 64 passes. The mutation was restored before running the gates. + +Counts re-measured at `cf4f77f` after the blank-field commit added seven tests; +the earlier 74/16/58 figures described the commit before it. + +## Gate results + +All commands ran with `ORCA_BACKGROUND_LAUNCH=1`. + +- `pnpm tc`: exit 0; completed the repository typecheck runner. +- `pnpm exec vitest run src/main/runtime/rpc`: exit 1; 277 files passed, + one failed; 2,462 tests passed, one failed, one skipped. The only failure was + the unrelated `structured-agent-session-adoption-replay.test.ts` hitting its + 5,000 ms timeout. All identity tests passed. +- `pnpm --dir mobile typecheck`: exit 0; `tsc --noEmit` passed. +- `pnpm run check:code-quality:changed`: exit 0; zero new code-quality, + type-aware, or React Doctor findings across the two changed code files. +- Isolated retry of `structured-agent-session-adoption-replay.test.ts`: exit 0; + one test passed, with the test body completing in 358 ms. +- Full RPC retry with `pnpm exec vitest run src/main/runtime/rpc --maxWorkers=4`: + exit 0; all 278 files passed, 2,470 tests passed, one skipped (97.24 seconds). + The bounded-concurrency rerun resolved the timeout without changing test code. diff --git a/electron.vite.config.ts b/electron.vite.config.ts index d900e6cba16..2ba0afaefc5 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -8,6 +8,7 @@ import { createPlainNodeEntryGuardPlugin } from './config/build-plugins/plain-no import packageJson from './package.json' with { type: 'json' } const BUNDLED_MAIN_DEPENDENCIES = new Set([ + '@streamparser/json', '@xterm/headless', '@xterm/addon-serialize', 'tldts', diff --git a/mobile/rpc-foundation/goldens/b1.json b/mobile/rpc-foundation/goldens/b1.json new file mode 100644 index 00000000000..1e0a26e1893 --- /dev/null +++ b/mobile/rpc-foundation/goldens/b1.json @@ -0,0 +1,328 @@ +{ + "operation": "workspace.file-inventory", + "family": "legacy-inventory", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0d903486cbe8": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 240 + } + }, + "1ba589a74085": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "2837f481a843": { + "name": "files.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "3b6419fbab75": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "$rpc": "undefined" + } + }, + "4c6301522bc0": { + "name": "files.list#2", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "602e35a92eec": { + "files": [] + }, + "603254c040fc": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "files": [ + { + "relativePath": "old.ts" + } + ] + } + } + } + }, + "6fcbcfd641a6": { + "name": "files.searchPaths#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"fresh\",\"limit\":16}}" + }, + "9dea95bddfe5": { + "name": "files.searchPaths#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"old\",\"limit\":16}}" + }, + "a129552fdc6e": { + "files": ["third.ts"] + }, + "b2434f1de9f6": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 120 + } + }, + "c0821dc354d7": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "d2ad71e601c4": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "$rpc": "undefined" + } + }, + "daf226a0261c": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "files": [ + { + "relativePath": "fresh.ts" + }, + { + "relativePath": "third.ts" + } + ] + } + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "b1", + "checkpoints": [ + { + "id": "old-pending", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/b2.json b/mobile/rpc-foundation/goldens/b2.json new file mode 100644 index 00000000000..b379fd05b0f --- /dev/null +++ b/mobile/rpc-foundation/goldens/b2.json @@ -0,0 +1,172 @@ +{ + "operation": "project.update-metadata", + "family": "project-explicit-false", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0c4dced3e005": { + "error": "", + "mutating": true, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "204a5c5728c2": { + "error": "Cannot read properties of null (reading 'ok')", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "2cd14f7121a5": { + "name": "projectMutating", + "value": false + }, + "52a7a7239fbb": { + "name": "github.project.updateIssueBySlug#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"github.project.updateIssueBySlug\",\"params\":{\"owner\":\"owner\",\"repo\":\"repo\",\"host\":\"github.enterprise.test\",\"number\":1,\"updates\":{\"addLabels\":[\"recorded\"]}}}" + }, + "6f0142de3930": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "c2a271fc5d97": { + "name": "projectMutating", + "value": true + }, + "d330309fabb3": { + "name": "projectRowDetailError", + "value": "Cannot read properties of null (reading 'ok')" + }, + "e5673036d45e": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "b2", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["e5673036d45e"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "0c4dced3e005", + "effects": ["c2a271fc5d97"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["6f0142de3930"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "204a5c5728c2", + "effects": ["c2a271fc5d97", "d330309fabb3", "2cd14f7121a5"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/b3.json b/mobile/rpc-foundation/goldens/b3.json new file mode 100644 index 00000000000..42be10f7e07 --- /dev/null +++ b/mobile/rpc-foundation/goldens/b3.json @@ -0,0 +1,233 @@ +{ + "operation": "linear.issue-detail", + "family": "linear-detail-barrier", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "034a83431f03": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "issue refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "1696f2f90218": { + "name": "detailError", + "value": "comments transport error" + }, + "3b01c25bcd45": { + "name": "detailError", + "value": "" + }, + "3cb9a384ce0e": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "42903545f0f8": { + "error": "comments transport error", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "4e7c4654b51d": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "comments transport error", + "isRpcDeliveryUnknown": true + } + } + }, + "780aaf1d97be": { + "error": "", + "loading": true, + "payload": { + "$rpc": "null" + } + }, + "7d21147e56c1": { + "name": "detailLoading", + "value": true + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "91a1c8142e23": { + "name": "detailLoading", + "value": false + }, + "bb215a1eb59b": { + "name": "linear.getIssue#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"linear.getIssue\",\"params\":{\"id\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "e7f73629d075": { + "name": "linear.issueComments#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.issueComments\",\"params\":{\"issueId\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "fc4ce176400a": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "b3", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["fc4ce176400a", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "issue-refused-comments-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/interruptions-inventory-lifecycle.json b/mobile/rpc-foundation/goldens/interruptions-inventory-lifecycle.json new file mode 100644 index 00000000000..f997f179ee1 --- /dev/null +++ b/mobile/rpc-foundation/goldens/interruptions-inventory-lifecycle.json @@ -0,0 +1,263 @@ +{ + "operation": "workspace.file-inventory", + "family": "legacy-inventory", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "2837f481a843": { + "name": "files.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "602e35a92eec": { + "files": [] + }, + "9dea95bddfe5": { + "name": "files.searchPaths#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"old\",\"limit\":16}}" + }, + "b5b30ad54c76": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 120, + "settledAt": 120, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "c0821dc354d7": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "ccb16672d904": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 120, + "settledAt": 120, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "d2ad71e601c4": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "$rpc": "undefined" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee88659ed950": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 120, + "settledAt": 30120, + "error": { + "category": "Error", + "message": "Request timed out: files.list", + "isRpcDeliveryUnknown": true + } + } + } + }, + "recording": { + "scenario": "interruptions-inventory-lifecycle", + "checkpoints": [ + { + "id": "inventory-lifecycle.timeout:interrupted", + "observation": { + "sender": ["c0821dc354d7", "ee88659ed950"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.timeout:settled", + "observation": { + "sender": ["c0821dc354d7", "ee88659ed950"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.disconnect:interrupted", + "observation": { + "sender": ["c0821dc354d7", "b5b30ad54c76"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "disconnect": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.disconnect:settled", + "observation": { + "sender": ["c0821dc354d7", "b5b30ad54c76"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "disconnect": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.cutover:interrupted", + "observation": { + "sender": ["c0821dc354d7", "ccb16672d904"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "cutover": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.cutover:settled", + "observation": { + "sender": ["c0821dc354d7", "ccb16672d904"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "cutover": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/interruptions-settings-bot-overrides-fulfilled.json b/mobile/rpc-foundation/goldens/interruptions-settings-bot-overrides-fulfilled.json new file mode 100644 index 00000000000..8588d3d73c3 --- /dev/null +++ b/mobile/rpc-foundation/goldens/interruptions-settings-bot-overrides-fulfilled.json @@ -0,0 +1,244 @@ +{ + "operation": "settings.bot-overrides", + "family": "settings.bot-overrides", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "06eff8247d02": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "4f53cda18c2b": [], + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "7fc945a92540": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: settings.get", + "isRpcDeliveryUnknown": true + } + } + }, + "af6903aed166": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "interruptions-settings-bot-overrides-fulfilled", + "checkpoints": [ + { + "id": "settings-bot-overrides-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.timeout:interrupted", + "observation": { + "sender": ["7fc945a92540"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.timeout:settled", + "observation": { + "sender": ["7fc945a92540"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.disconnect:interrupted", + "observation": { + "sender": ["af6903aed166"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "disconnect": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.disconnect:settled", + "observation": { + "sender": ["af6903aed166"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "disconnect": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.cutover:interrupted", + "observation": { + "sender": ["06eff8247d02"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "cutover": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.cutover:settled", + "observation": { + "sender": ["06eff8247d02"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "cutover": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/inventory-lifecycle.json b/mobile/rpc-foundation/goldens/inventory-lifecycle.json new file mode 100644 index 00000000000..cbfc520def2 --- /dev/null +++ b/mobile/rpc-foundation/goldens/inventory-lifecycle.json @@ -0,0 +1,125 @@ +{ + "operation": "workspace.file-inventory", + "family": "legacy-inventory", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "2837f481a843": { + "name": "files.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "64847315695c": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "files": [ + { + "relativePath": "old.ts" + } + ] + } + } + } + }, + "9dea95bddfe5": { + "name": "files.searchPaths#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"old\",\"limit\":16}}" + }, + "c0821dc354d7": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "fe1aebea954c": { + "files": ["old.ts"] + } + }, + "recording": { + "scenario": "inventory-lifecycle", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "fe1aebea954c", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/inventory-repeat-query.json b/mobile/rpc-foundation/goldens/inventory-repeat-query.json new file mode 100644 index 00000000000..3cd516d14c6 --- /dev/null +++ b/mobile/rpc-foundation/goldens/inventory-repeat-query.json @@ -0,0 +1,264 @@ +{ + "operation": "workspace.file-inventory", + "family": "legacy-inventory", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "003a57e2bf31": { + "files": ["alpha.ts"] + }, + "07ed03809186": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "alpha", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "files": [ + { + "relativePath": "alpha.ts" + } + ] + } + } + } + }, + "0a86b05a780d": { + "status": "fulfilled", + "startedAt": 360, + "settledAt": 360, + "value": { + "$rpc": "undefined" + } + }, + "1df364c141e7": { + "name": "files.searchPaths#2", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"beta\",\"limit\":16}}" + }, + "3642acfe438f": { + "files": ["beta.ts"] + }, + "3b6419fbab75": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "$rpc": "undefined" + } + }, + "6908b2a7adc8": { + "name": "files.searchPaths#3", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "gamma", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 360 + } + }, + "702153114450": { + "name": "files.searchPaths#3", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"gamma\",\"limit\":16}}" + }, + "7e0cf12e6220": { + "name": "files.searchPaths#3", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "gamma", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 360, + "settledAt": 360, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "files": [ + { + "relativePath": "gamma.ts" + } + ] + } + } + } + }, + "a1e1a76515f9": { + "name": "files.searchPaths#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"alpha\",\"limit\":16}}" + }, + "a7201fe6aca9": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "beta", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "files": [ + { + "relativePath": "beta.ts" + } + ] + } + } + } + }, + "d2ad71e601c4": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "$rpc": "undefined" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "inventory-repeat-query", + "checkpoints": [ + { + "id": "cached-alpha", + "observation": { + "sender": ["07ed03809186", "a7201fe6aca9", "6908b2a7adc8"], + "payloads": ["a1e1a76515f9", "1df364c141e7", "702153114450"], + "settlements": { + "mount": "eb79a9b3682a", + "alpha": "eb79a9b3682a", + "beta": "d2ad71e601c4", + "gamma": "3b6419fbab75", + "repeat-alpha": "0a86b05a780d" + }, + "state": "003a57e2bf31", + "effects": [] + } + }, + { + "id": "stale-search-ignored", + "observation": { + "sender": ["07ed03809186", "a7201fe6aca9", "7e0cf12e6220"], + "payloads": ["a1e1a76515f9", "1df364c141e7", "702153114450"], + "settlements": { + "mount": "eb79a9b3682a", + "alpha": "eb79a9b3682a", + "beta": "d2ad71e601c4", + "gamma": "3b6419fbab75", + "repeat-alpha": "0a86b05a780d" + }, + "state": "003a57e2bf31", + "effects": [] + } + }, + { + "id": "cached-beta-cancels-debounce", + "observation": { + "sender": ["07ed03809186", "a7201fe6aca9", "7e0cf12e6220"], + "payloads": ["a1e1a76515f9", "1df364c141e7", "702153114450"], + "settlements": { + "mount": "eb79a9b3682a", + "alpha": "eb79a9b3682a", + "beta": "d2ad71e601c4", + "gamma": "3b6419fbab75", + "repeat-alpha": "0a86b05a780d", + "delta": "0a86b05a780d", + "repeat-beta": "0a86b05a780d" + }, + "state": "3642acfe438f", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/lifecycle-b3.json b/mobile/rpc-foundation/goldens/lifecycle-b3.json new file mode 100644 index 00000000000..d4ece9e9165 --- /dev/null +++ b/mobile/rpc-foundation/goldens/lifecycle-b3.json @@ -0,0 +1,867 @@ +{ + "operation": "linear.issue-detail", + "family": "linear-detail-barrier", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "034a83431f03": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "issue refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "1696f2f90218": { + "name": "detailError", + "value": "comments transport error" + }, + "2b9e0df88a93": { + "name": "linear.getIssue#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.getIssue\",\"params\":{\"id\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "3b01c25bcd45": { + "name": "detailError", + "value": "" + }, + "3cb9a384ce0e": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "42903545f0f8": { + "error": "comments transport error", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "4e7c4654b51d": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "comments transport error", + "isRpcDeliveryUnknown": true + } + } + }, + "780aaf1d97be": { + "error": "", + "loading": true, + "payload": { + "$rpc": "null" + } + }, + "7d21147e56c1": { + "name": "detailLoading", + "value": true + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "8b45b8e00ec0": { + "name": "linear.getIssue#2", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "91a1c8142e23": { + "name": "detailLoading", + "value": false + }, + "9ea1594bdfc8": { + "name": "linear.issueComments#2", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "ae1e9660892e": { + "name": "linear.issueComments#2", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"linear.issueComments\",\"params\":{\"issueId\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "bb215a1eb59b": { + "name": "linear.getIssue#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"linear.getIssue\",\"params\":{\"id\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "e7f73629d075": { + "name": "linear.issueComments#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.issueComments\",\"params\":{\"issueId\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "fc4ce176400a": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "lifecycle-b3", + "checkpoints": [ + { + "id": "b3.prelude:pending", + "observation": { + "sender": ["fc4ce176400a", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.prelude:issue-refused-comments-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.reset-before-1:lifecycle-boundary", + "observation": { + "sender": ["fc4ce176400a", "3cb9a384ce0e", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.reset-before-1:issue-refused-comments-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.reset-before-1:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.reset-after-1:lifecycle-boundary", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.reset-after-1:issue-refused-comments-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.reset-after-1:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.reset-before-2:lifecycle-boundary", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.reset-before-2:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.reset-after-2:lifecycle-boundary", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.reset-after-2:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.unmount-before-1:lifecycle-boundary", + "observation": { + "sender": ["fc4ce176400a", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.unmount-before-1:issue-refused-comments-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.unmount-before-1:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.unmount-before-1:remounted", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.unmount-after-1:lifecycle-boundary", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.unmount-after-1:issue-refused-comments-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.unmount-after-1:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.unmount-after-1:remounted", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.unmount-before-2:lifecycle-boundary", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.unmount-before-2:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.unmount-before-2:remounted", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.unmount-after-2:lifecycle-boundary", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.unmount-after-2:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.unmount-after-2:remounted", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d", "8b45b8e00ec0", "9ea1594bdfc8"], + "payloads": ["bb215a1eb59b", "e7f73629d075", "2b9e0df88a93", "ae1e9660892e"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23", + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1" + ] + } + }, + { + "id": "b3.blur-before-1:lifecycle-boundary", + "observation": { + "sender": ["fc4ce176400a", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.blur-before-1:issue-refused-comments-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.blur-before-1:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.blur-after-1:lifecycle-boundary", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.blur-after-1:issue-refused-comments-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.blur-after-1:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.blur-before-2:lifecycle-boundary", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.blur-before-2:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.blur-after-2:lifecycle-boundary", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.blur-after-2:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/lifecycle-inventory-lifecycle.json b/mobile/rpc-foundation/goldens/lifecycle-inventory-lifecycle.json new file mode 100644 index 00000000000..05b4799c653 --- /dev/null +++ b/mobile/rpc-foundation/goldens/lifecycle-inventory-lifecycle.json @@ -0,0 +1,571 @@ +{ + "operation": "workspace.file-inventory", + "family": "legacy-inventory", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "2837f481a843": { + "name": "files.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "356af7179c37": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 120 + } + }, + "602e35a92eec": { + "files": [] + }, + "64847315695c": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "files": [ + { + "relativePath": "old.ts" + } + ] + } + } + } + }, + "9dea95bddfe5": { + "name": "files.searchPaths#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"old\",\"limit\":16}}" + }, + "b2434f1de9f6": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 120 + } + }, + "c0821dc354d7": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "d2ad71e601c4": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "$rpc": "undefined" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "fe1aebea954c": { + "files": ["old.ts"] + } + }, + "recording": { + "scenario": "lifecycle-inventory-lifecycle", + "checkpoints": [ + { + "id": "inventory-lifecycle.reset-before-1:lifecycle-boundary", + "observation": { + "sender": ["356af7179c37"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-reset": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.reset-before-1:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-reset": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.reset-after-1:lifecycle-boundary", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-reset": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.reset-after-1:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-reset": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.reset-before-2:lifecycle-boundary", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-reset": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.reset-before-2:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-reset": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.reset-after-2:lifecycle-boundary", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-reset": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.reset-after-2:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-reset": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-before-1:lifecycle-boundary", + "observation": { + "sender": ["356af7179c37"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-before-1:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-before-1:remounted", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4", + "remount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-after-1:lifecycle-boundary", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-after-1:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-after-1:remounted", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4", + "remount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-before-2:lifecycle-boundary", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-before-2:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-before-2:remounted", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4", + "remount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-after-2:lifecycle-boundary", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4" + }, + "state": "fe1aebea954c", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-after-2:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4" + }, + "state": "fe1aebea954c", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.unmount-after-2:remounted", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-unmount": "d2ad71e601c4", + "remount": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.blur-before-1:lifecycle-boundary", + "observation": { + "sender": ["356af7179c37"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-blur": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.blur-before-1:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-blur": "d2ad71e601c4" + }, + "state": "fe1aebea954c", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.blur-after-1:lifecycle-boundary", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-blur": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.blur-after-1:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-blur": "d2ad71e601c4" + }, + "state": "fe1aebea954c", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.blur-before-2:lifecycle-boundary", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-blur": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.blur-before-2:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-blur": "d2ad71e601c4" + }, + "state": "fe1aebea954c", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.blur-after-2:lifecycle-boundary", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-blur": "d2ad71e601c4" + }, + "state": "fe1aebea954c", + "effects": [] + } + }, + { + "id": "inventory-lifecycle.blur-after-2:settled", + "observation": { + "sender": ["c0821dc354d7", "64847315695c"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "lifecycle-blur": "d2ad71e601c4" + }, + "state": "fe1aebea954c", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/lifecycle-settings-bot-overrides-fulfilled.json b/mobile/rpc-foundation/goldens/lifecycle-settings-bot-overrides-fulfilled.json new file mode 100644 index 00000000000..e158171f45a --- /dev/null +++ b/mobile/rpc-foundation/goldens/lifecycle-settings-bot-overrides-fulfilled.json @@ -0,0 +1,323 @@ +{ + "operation": "settings.bot-overrides", + "family": "settings.bot-overrides", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "4f53cda18c2b": [], + "7ad8a0996352": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "7ca23c4c946b": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "8f6fe9452bda": { + "name": "settings.get#2", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "d52c8e96e222": ["bot-user"], + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "lifecycle-settings-bot-overrides-fulfilled", + "checkpoints": [ + { + "id": "settings-bot-overrides-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.reset-before-1:lifecycle-boundary", + "observation": { + "sender": ["090c88478661", "7ad8a0996352"], + "payloads": ["7ddcb1852b39", "8f6fe9452bda"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.reset-before-1:settled", + "observation": { + "sender": ["7ca23c4c946b", "7ad8a0996352"], + "payloads": ["7ddcb1852b39", "8f6fe9452bda"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.reset-after-1:lifecycle-boundary", + "observation": { + "sender": ["7ca23c4c946b", "7ad8a0996352"], + "payloads": ["7ddcb1852b39", "8f6fe9452bda"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.reset-after-1:settled", + "observation": { + "sender": ["7ca23c4c946b", "7ad8a0996352"], + "payloads": ["7ddcb1852b39", "8f6fe9452bda"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-reset": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.unmount-before-1:lifecycle-boundary", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.unmount-before-1:settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.unmount-before-1:remounted", + "observation": { + "sender": ["7ca23c4c946b", "7ad8a0996352"], + "payloads": ["7ddcb1852b39", "8f6fe9452bda"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.unmount-after-1:lifecycle-boundary", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.unmount-after-1:settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.unmount-after-1:remounted", + "observation": { + "sender": ["7ca23c4c946b", "7ad8a0996352"], + "payloads": ["7ddcb1852b39", "8f6fe9452bda"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.blur-before-1:lifecycle-boundary", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.blur-before-1:settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.blur-after-1:lifecycle-boundary", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.blur-after-1:settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/lifecycle-settings-task-hydration-fulfilled.json b/mobile/rpc-foundation/goldens/lifecycle-settings-task-hydration-fulfilled.json new file mode 100644 index 00000000000..1cbd5f00e29 --- /dev/null +++ b/mobile/rpc-foundation/goldens/lifecycle-settings-task-hydration-fulfilled.json @@ -0,0 +1,2691 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "1825a87a7ca8": { + "hydrated": false, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "58c52d8b7c76": { + "hydrated": true, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "70c1fe53348e": { + "name": "status.get#2", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "c9c0513fdcb9": { + "name": "status.get#2", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "d705fce957e8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "lifecycle-settings-task-hydration-fulfilled", + "checkpoints": [ + { + "id": "settings-task-hydration-fulfilled.prelude:settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-2:lifecycle-boundary", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-2:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-2:remounted", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "c9c0513fdcb9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-2:lifecycle-boundary", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-2:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-2:remounted", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "c9c0513fdcb9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-3:lifecycle-boundary", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-3:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-3:remounted", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "c9c0513fdcb9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-3:lifecycle-boundary", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-3:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-3:remounted", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "c9c0513fdcb9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-4:lifecycle-boundary", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-4:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-4:remounted", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "c9c0513fdcb9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-4:lifecycle-boundary", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-4:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-4:remounted", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "c9c0513fdcb9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-5:lifecycle-boundary", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-5:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-before-5:remounted", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "c9c0513fdcb9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-5:lifecycle-boundary", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-5:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.unmount-after-5:remounted", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "c9c0513fdcb9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "1825a87a7ca8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/lifecycle-settings-workspace-context-fulfilled.json b/mobile/rpc-foundation/goldens/lifecycle-settings-workspace-context-fulfilled.json new file mode 100644 index 00000000000..b7ab8a13598 --- /dev/null +++ b/mobile/rpc-foundation/goldens/lifecycle-settings-workspace-context-fulfilled.json @@ -0,0 +1,1113 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "06425d8da2e6": { + "name": "linear.status#2", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "13028e692551": { + "name": "preflight.check#2", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2a7485a88169": { + "providers": ["github"], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "39bfd36b44ed": { + "name": "ui.get#2", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "3fc2a1b54e13": { + "name": "settings.get#2", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "7ad8a0996352": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "847430ffa968": { + "name": "linear.status#2", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "84b10f34b617": { + "name": "ui.get#2", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "8a63b85fee0c": { + "providers": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "c114925e9c68": { + "name": "preflight.check#2", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + } + }, + "recording": { + "scenario": "lifecycle-settings-workspace-context-fulfilled", + "checkpoints": [ + { + "id": "settings-workspace-context-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-1:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-1:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-1:remounted", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "c114925e9c68", + "06425d8da2e6", + "7ad8a0996352", + "39bfd36b44ed" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-1:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "822040616fbb", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-1:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-1:remounted", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "c114925e9c68", + "06425d8da2e6", + "7ad8a0996352", + "39bfd36b44ed" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-2:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "822040616fbb", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-2:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-2:remounted", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "c114925e9c68", + "06425d8da2e6", + "7ad8a0996352", + "39bfd36b44ed" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-2:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-2:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-2:remounted", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "c114925e9c68", + "06425d8da2e6", + "7ad8a0996352", + "39bfd36b44ed" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-3:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-3:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-3:remounted", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "c114925e9c68", + "06425d8da2e6", + "7ad8a0996352", + "39bfd36b44ed" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-3:lifecycle-boundary", + "observation": { + "sender": ["563e4c82b345", "a4760ef5a9f4", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-3:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-3:remounted", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "c114925e9c68", + "06425d8da2e6", + "7ad8a0996352", + "39bfd36b44ed" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-4:lifecycle-boundary", + "observation": { + "sender": ["563e4c82b345", "a4760ef5a9f4", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-4:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-before-4:remounted", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "c114925e9c68", + "06425d8da2e6", + "7ad8a0996352", + "39bfd36b44ed" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-4:lifecycle-boundary", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-4:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.unmount-after-4:remounted", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "c114925e9c68", + "06425d8da2e6", + "7ad8a0996352", + "39bfd36b44ed" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-unmount": "eb79a9b3682a", + "remount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-before-1:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-before-1:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-after-1:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "822040616fbb", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-after-1:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-before-2:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "822040616fbb", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-before-2:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-after-2:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-after-2:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-before-3:lifecycle-boundary", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-before-3:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-after-3:lifecycle-boundary", + "observation": { + "sender": ["563e4c82b345", "a4760ef5a9f4", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-after-3:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-before-4:lifecycle-boundary", + "observation": { + "sender": ["563e4c82b345", "a4760ef5a9f4", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-before-4:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-after-4:lifecycle-boundary", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.blur-after-4:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "lifecycle-blur": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-repo.baserefdefault-1.json b/mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-repo.baserefdefault-1.json new file mode 100644 index 00000000000..7eb20ce8402 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-repo.baserefdefault-1.json @@ -0,0 +1,770 @@ +{ + "operation": "source-control.branch-base-ref", + "family": "git.base-ref-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0208d586a748": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "089d79f002a1": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "repos": [ + { + "id": "repo42", + "worktreeBaseRef": { + "$rpc": "null" + } + } + ] + } + } + } + }, + "0be93460f365": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "198cce9909ce": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": "origin/main" + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2843e3ab21fc": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "32a7c0ae7918": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "outer refused", + "isRpcDeliveryUnknown": false + } + }, + "4200126ab3ab": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "43be25da851a": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "467d43e1ff0f": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "4dce743b400a": { + "baseRef": "unresolved" + }, + "535f7698e80e": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "594101d24d72": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "59ad0b14ed9f": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "5f661e5b3de8": { + "baseRef": "origin/main" + }, + "634e13dcef43": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "6396d004a0e7": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "worktree": { + "baseRef": " " + } + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "a5632796ed43": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "b46548195c7a": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "defaultBaseRef": " origin/main " + } + } + } + }, + "c6857d66bf1a": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "cd73fe3775d3": { + "name": "repo.baseRefDefault#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"repo.baseRefDefault\",\"params\":{\"repo\":\"id:repo42\"}}" + }, + "cec763c8abc6": { + "name": "worktree.show#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.show\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "deac258dd8b1": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Unable to resolve branch base", + "isRpcDeliveryUnknown": false + } + }, + "e2fbc2b9e8e9": { + "baseRef": { + "$rpc": "null" + } + }, + "ea6b907523d7": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "ee20a1dc39e7": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "matrix-git.base-ref-chain-repo.baserefdefault-1", + "checkpoints": [ + { + "id": "sc-base-ref-default.prelude:requests-pending", + "observation": { + "sender": ["535f7698e80e", "26accd69bc48"], + "payloads": ["cec763c8abc6", "594101d24d72"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.prelude:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.normal:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-absent:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "634e13dcef43"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "ee20a1dc39e7" + }, + "state": "e2fbc2b9e8e9", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-null:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "59ad0b14ed9f"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "ee20a1dc39e7" + }, + "state": "e2fbc2b9e8e9", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-ok-missing:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "0be93460f365"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "ee20a1dc39e7" + }, + "state": "e2fbc2b9e8e9", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-string-error:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "2843e3ab21fc"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "ee20a1dc39e7" + }, + "state": "e2fbc2b9e8e9", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-object-error:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "467d43e1ff0f"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "ee20a1dc39e7" + }, + "state": "e2fbc2b9e8e9", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "ea6b907523d7"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "32a7c0ae7918" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused-no-message:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "0208d586a748"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "deac258dd8b1" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.method-not-found:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "43be25da851a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "ee20a1dc39e7" + }, + "state": "e2fbc2b9e8e9", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "a5632796ed43"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "a947768bc0ed" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection-no-message:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "4200126ab3ab"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "c7584e82c72f" + }, + "state": "4dce743b400a", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-repo.list-1.json b/mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-repo.list-1.json new file mode 100644 index 00000000000..b3c815527be --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-repo.list-1.json @@ -0,0 +1,837 @@ +{ + "operation": "source-control.branch-base-ref", + "family": "git.base-ref-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "089d79f002a1": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "repos": [ + { + "id": "repo42", + "worktreeBaseRef": { + "$rpc": "null" + } + } + ] + } + } + } + }, + "198cce9909ce": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": "origin/main" + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "397587780f89": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "4dce743b400a": { + "baseRef": "unresolved" + }, + "52500878f297": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "535f7698e80e": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "572ea5e1e980": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "594101d24d72": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "5f661e5b3de8": { + "baseRef": "origin/main" + }, + "6396d004a0e7": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "worktree": { + "baseRef": " " + } + } + } + } + }, + "63c1ccf6c3e3": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "6e5c6593dad8": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9eb52b24aea4": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "ae85758452ae": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "b46548195c7a": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "defaultBaseRef": " origin/main " + } + } + } + }, + "c6857d66bf1a": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "caa7fdd9839a": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "cc1facdf008c": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "cd73fe3775d3": { + "name": "repo.baseRefDefault#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"repo.baseRefDefault\",\"params\":{\"repo\":\"id:repo42\"}}" + }, + "cec763c8abc6": { + "name": "worktree.show#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.show\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "e31fdb68b5c2": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + } + }, + "recording": { + "scenario": "matrix-git.base-ref-chain-repo.list-1", + "checkpoints": [ + { + "id": "sc-base-ref-default.prelude:requests-pending", + "observation": { + "sender": ["535f7698e80e", "26accd69bc48"], + "payloads": ["cec763c8abc6", "594101d24d72"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.normal:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.normal:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-absent:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "9eb52b24aea4", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-absent:settled", + "observation": { + "sender": ["6396d004a0e7", "9eb52b24aea4", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-null:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "63c1ccf6c3e3", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-null:settled", + "observation": { + "sender": ["6396d004a0e7", "63c1ccf6c3e3", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-ok-missing:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "ae85758452ae", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-ok-missing:settled", + "observation": { + "sender": ["6396d004a0e7", "ae85758452ae", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-string-error:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "572ea5e1e980", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-string-error:settled", + "observation": { + "sender": ["6396d004a0e7", "572ea5e1e980", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-object-error:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "caa7fdd9839a", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-object-error:settled", + "observation": { + "sender": ["6396d004a0e7", "caa7fdd9839a", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "52500878f297", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused:settled", + "observation": { + "sender": ["6396d004a0e7", "52500878f297", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused-no-message:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "397587780f89", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused-no-message:settled", + "observation": { + "sender": ["6396d004a0e7", "397587780f89", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.method-not-found:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "e31fdb68b5c2", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.method-not-found:settled", + "observation": { + "sender": ["6396d004a0e7", "e31fdb68b5c2", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "6e5c6593dad8", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection:settled", + "observation": { + "sender": ["6396d004a0e7", "6e5c6593dad8", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection-no-message:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "cc1facdf008c", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection-no-message:settled", + "observation": { + "sender": ["6396d004a0e7", "cc1facdf008c", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-worktree.show-1.json b/mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-worktree.show-1.json new file mode 100644 index 00000000000..1e772a5f28a --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-worktree.show-1.json @@ -0,0 +1,837 @@ +{ + "operation": "source-control.branch-base-ref", + "family": "git.base-ref-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "089d79f002a1": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "repos": [ + { + "id": "repo42", + "worktreeBaseRef": { + "$rpc": "null" + } + } + ] + } + } + } + }, + "09126745f36c": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "198cce9909ce": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": "origin/main" + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "396134225295": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "433ef4e3f075": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "4dce743b400a": { + "baseRef": "unresolved" + }, + "535f7698e80e": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "594101d24d72": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "5f661e5b3de8": { + "baseRef": "origin/main" + }, + "6396d004a0e7": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "worktree": { + "baseRef": " " + } + } + } + } + }, + "7a891248c223": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9be4cad15ffc": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "a17ceeb9c911": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "a4456b77f02e": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "b46548195c7a": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "defaultBaseRef": " origin/main " + } + } + } + }, + "b9eb0b5172ef": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "c6857d66bf1a": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "cd73fe3775d3": { + "name": "repo.baseRefDefault#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"repo.baseRefDefault\",\"params\":{\"repo\":\"id:repo42\"}}" + }, + "cec763c8abc6": { + "name": "worktree.show#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.show\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "f200ec894167": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "f9af0bcc7ed6": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + } + }, + "recording": { + "scenario": "matrix-git.base-ref-chain-worktree.show-1", + "checkpoints": [ + { + "id": "sc-base-ref-default.prelude:requests-pending", + "observation": { + "sender": ["535f7698e80e", "26accd69bc48"], + "payloads": ["cec763c8abc6", "594101d24d72"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.normal:barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.normal:settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-absent:barrier-settled", + "observation": { + "sender": ["a17ceeb9c911", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-absent:settled", + "observation": { + "sender": ["a17ceeb9c911", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-null:barrier-settled", + "observation": { + "sender": ["9be4cad15ffc", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.result-null:settled", + "observation": { + "sender": ["9be4cad15ffc", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-ok-missing:barrier-settled", + "observation": { + "sender": ["7a891248c223", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-ok-missing:settled", + "observation": { + "sender": ["7a891248c223", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-string-error:barrier-settled", + "observation": { + "sender": ["b9eb0b5172ef", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-string-error:settled", + "observation": { + "sender": ["b9eb0b5172ef", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-object-error:barrier-settled", + "observation": { + "sender": ["396134225295", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.inner-false-object-error:settled", + "observation": { + "sender": ["396134225295", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused:barrier-settled", + "observation": { + "sender": ["433ef4e3f075", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused:settled", + "observation": { + "sender": ["433ef4e3f075", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused-no-message:barrier-settled", + "observation": { + "sender": ["a4456b77f02e", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.outer-refused-no-message:settled", + "observation": { + "sender": ["a4456b77f02e", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.method-not-found:barrier-settled", + "observation": { + "sender": ["f9af0bcc7ed6", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.method-not-found:settled", + "observation": { + "sender": ["f9af0bcc7ed6", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection:barrier-settled", + "observation": { + "sender": ["f200ec894167", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection:settled", + "observation": { + "sender": ["f200ec894167", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection-no-message:barrier-settled", + "observation": { + "sender": ["09126745f36c", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "sc-base-ref-default.transport-rejection-no-message:settled", + "observation": { + "sender": ["09126745f36c", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-git.commit-message-ai-git.generatecommitmessage-1.json b/mobile/rpc-foundation/goldens/matrix-git.commit-message-ai-git.generatecommitmessage-1.json new file mode 100644 index 00000000000..e6d8bcf5bd5 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-git.commit-message-ai-git.generatecommitmessage-1.json @@ -0,0 +1,659 @@ +{ + "operation": "source-control.commit-message", + "family": "git.commit-message-ai", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "1290c04bc26c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "message": "feat: recorded", + "success": true + } + }, + "31141af16c2d": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "3186ccdbc53f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Unknown method", + "success": false + } + }, + "3ef8a5f65bc8": { + "generated": { + "message": "feat: recorded", + "success": true + } + }, + "3f131697d120": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "46920d3cb0c1": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "5213fea85cf0": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "5246b9fd2d12": { + "generated": { + "error": "outer refused", + "success": false + } + }, + "5ad7ea556320": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "outer refused", + "success": false + } + }, + "63410fd1b187": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "6453ff669a2f": { + "generated": { + "error": "Failed to generate commit message", + "success": false + } + }, + "68e6f784ba09": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "915059a8a000": { + "generated": { + "error": "Unknown method", + "success": false + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "a0551476eb3b": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "No commit message generated", + "success": false + } + }, + "a09d0ada6684": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "a64074c2ba96": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "adb40821f3e2": { + "generated": "ungenerated" + }, + "b95c8d57adc9": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Failed to generate commit message", + "success": false + } + }, + "bfe04c9c1653": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "c39c20fa07f2": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "e96b430d7d35": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "fa7a334b373d": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "faad14b9f95d": { + "generated": { + "error": "No commit message generated", + "success": false + } + } + }, + "recording": { + "scenario": "matrix-git.commit-message-ai-git.generatecommitmessage-1", + "checkpoints": [ + { + "id": "sc-commit-message-generated.prelude:pending", + "observation": { + "sender": ["125fbea5f50a"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "9270aeb7d9c6" + }, + "state": "adb40821f3e2", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.normal:settled", + "observation": { + "sender": ["a09d0ada6684"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "1290c04bc26c" + }, + "state": "3ef8a5f65bc8", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.result-absent:settled", + "observation": { + "sender": ["bfe04c9c1653"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "b95c8d57adc9" + }, + "state": "6453ff669a2f", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.result-null:settled", + "observation": { + "sender": ["68e6f784ba09"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "b95c8d57adc9" + }, + "state": "6453ff669a2f", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.inner-ok-missing:settled", + "observation": { + "sender": ["46920d3cb0c1"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "a0551476eb3b" + }, + "state": "faad14b9f95d", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.inner-false-string-error:settled", + "observation": { + "sender": ["5213fea85cf0"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "a0551476eb3b" + }, + "state": "faad14b9f95d", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.inner-false-object-error:settled", + "observation": { + "sender": ["3f131697d120"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "a0551476eb3b" + }, + "state": "faad14b9f95d", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.outer-refused:settled", + "observation": { + "sender": ["fa7a334b373d"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "5ad7ea556320" + }, + "state": "5246b9fd2d12", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.outer-refused-no-message:settled", + "observation": { + "sender": ["63410fd1b187"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "b95c8d57adc9" + }, + "state": "6453ff669a2f", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.method-not-found:settled", + "observation": { + "sender": ["e96b430d7d35"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "3186ccdbc53f" + }, + "state": "915059a8a000", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.transport-rejection:settled", + "observation": { + "sender": ["31141af16c2d"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "a947768bc0ed" + }, + "state": "adb40821f3e2", + "effects": [] + } + }, + { + "id": "sc-commit-message-generated.transport-rejection-no-message:settled", + "observation": { + "sender": ["c39c20fa07f2"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "c7584e82c72f" + }, + "state": "adb40821f3e2", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-git.history-read-git.history-1.json b/mobile/rpc-foundation/goldens/matrix-git.history-read-git.history-1.json new file mode 100644 index 00000000000..829090d2a8e --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-git.history-read-git.history-1.json @@ -0,0 +1,719 @@ +{ + "operation": "source-control.git-history", + "family": "git.history-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "155f61ed496f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "Cannot read properties of null (reading 'items')", + "isRpcDeliveryUnknown": false + } + }, + "17bc1e177fe1": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "32a7c0ae7918": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "outer refused", + "isRpcDeliveryUnknown": false + } + }, + "437d7f38d098": { + "rows": [ + { + "author": "dev", + "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parentId": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "relativeTime": "1h", + "shortId": "aaaaaaa", + "subject": "first" + }, + { + "author": "", + "id": "cccccccccccccccccccccccccccccccccccccccc", + "parentId": { + "$rpc": "null" + }, + "relativeTime": "", + "shortId": "ccccccc", + "subject": "(no commit message)" + } + ] + }, + "4e27a22332c7": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "52b4fb4742f7": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "69d0ebdefcd3": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "6b280ce22422": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "items": [ + { + "author": "dev", + "displayId": "aaaaaaa", + "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parentIds": ["bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"], + "subject": "first", + "timestamp": 1767222000000 + }, + { + "id": "cccccccccccccccccccccccccccccccccccccccc", + "parentIds": [], + "subject": "", + "timestamp": { + "$rpc": "null" + } + } + ] + } + } + } + }, + "7d520ecb92ad": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": [ + { + "author": "dev", + "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parentId": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "relativeTime": "1h", + "shortId": "aaaaaaa", + "subject": "first" + }, + { + "author": "", + "id": "cccccccccccccccccccccccccccccccccccccccc", + "parentId": { + "$rpc": "null" + }, + "relativeTime": "", + "shortId": "ccccccc", + "subject": "(no commit message)" + } + ] + }, + "8bf6ec174c09": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "93e7019b0698": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "Cannot read properties of undefined (reading 'map')", + "isRpcDeliveryUnknown": false + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "acda0899d438": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "b834de93891d": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "b948e8307e81": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Unknown method", + "isRpcDeliveryUnknown": false + } + }, + "ba8b415f2807": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "d2ac5468a6f5": { + "name": "git.history#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.history\",\"params\":{\"worktree\":\"id:repo42::/p\",\"limit\":50}}" + }, + "d32fe6f7afe0": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "de21ba03a5c2": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "dfb377a66ab7": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "e7aad6e711f1": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Failed to load commit history", + "isRpcDeliveryUnknown": false + } + }, + "ef169a494b41": { + "rows": "unloaded" + }, + "f51f34589c7a": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "Cannot read properties of undefined (reading 'items')", + "isRpcDeliveryUnknown": false + } + } + }, + "recording": { + "scenario": "matrix-git.history-read-git.history-1", + "checkpoints": [ + { + "id": "sc-history-loaded.prelude:pending", + "observation": { + "sender": ["17bc1e177fe1"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.normal:settled", + "observation": { + "sender": ["6b280ce22422"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "7d520ecb92ad" + }, + "state": "437d7f38d098", + "effects": [] + } + }, + { + "id": "sc-history-loaded.result-absent:settled", + "observation": { + "sender": ["8bf6ec174c09"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "f51f34589c7a" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.result-null:settled", + "observation": { + "sender": ["dfb377a66ab7"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "155f61ed496f" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.inner-ok-missing:settled", + "observation": { + "sender": ["52b4fb4742f7"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "93e7019b0698" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.inner-false-string-error:settled", + "observation": { + "sender": ["ba8b415f2807"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "93e7019b0698" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.inner-false-object-error:settled", + "observation": { + "sender": ["acda0899d438"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "93e7019b0698" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.outer-refused:settled", + "observation": { + "sender": ["b834de93891d"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "32a7c0ae7918" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.outer-refused-no-message:settled", + "observation": { + "sender": ["de21ba03a5c2"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "e7aad6e711f1" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.method-not-found:settled", + "observation": { + "sender": ["d32fe6f7afe0"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "b948e8307e81" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.transport-rejection:settled", + "observation": { + "sender": ["69d0ebdefcd3"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "a947768bc0ed" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "sc-history-loaded.transport-rejection-no-message:settled", + "observation": { + "sender": ["4e27a22332c7"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "c7584e82c72f" + }, + "state": "ef169a494b41", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-git.remote-prerequisite-git.push-1.json b/mobile/rpc-foundation/goldens/matrix-git.remote-prerequisite-git.push-1.json new file mode 100644 index 00000000000..ecf44b15709 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-git.remote-prerequisite-git.push-1.json @@ -0,0 +1,657 @@ +{ + "operation": "source-control.remote-prerequisite", + "family": "git.remote-prerequisite", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "00e8a3bac22f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true, + "ran": true + } + }, + "0e00dbc486b4": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "0fe2eb2410a4": { + "outcome": { + "ok": true, + "ran": true + } + }, + "1b2778bf67a2": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "outer refused", + "ok": false + } + }, + "33b2843692a3": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "34eee892be9b": { + "outcome": { + "error": "Failed to push commits", + "ok": false + } + }, + "3718951f62b7": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "3c6a5a164e8a": { + "outcome": { + "error": "", + "ok": false + } + }, + "3e6cf1f04a9c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Failed to push commits", + "ok": false + } + }, + "403ae2f01ce3": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6c0349218dd0": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "7b027798abe5": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "95b1f2f379aa": { + "name": "git.push#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "a197c20578aa": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "transport failure", + "ok": false + } + }, + "a28defbf7f69": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "aa8b30457cff": { + "outcome": { + "error": "outer refused", + "ok": false + } + }, + "ae61c1e930df": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "cf19981c2114": { + "outcome": "unapplied" + }, + "d493a7059b00": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "e157741a28a1": { + "outcome": { + "error": "Unknown method", + "ok": false + } + }, + "e58ae363032b": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "f4ca76ee9f22": { + "outcome": { + "error": "transport failure", + "ok": false + } + }, + "f9869252c305": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "fa93ca01f266": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Unknown method", + "ok": false + } + }, + "fb4429083480": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "", + "ok": false + } + } + }, + "recording": { + "scenario": "matrix-git.remote-prerequisite-git.push-1", + "checkpoints": [ + { + "id": "sc-prerequisite-push.prelude:pending", + "observation": { + "sender": ["b7a56d89f615"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "9270aeb7d9c6" + }, + "state": "cf19981c2114", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.normal:settled", + "observation": { + "sender": ["f9869252c305"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "00e8a3bac22f" + }, + "state": "0fe2eb2410a4", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.result-absent:settled", + "observation": { + "sender": ["7b027798abe5"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "00e8a3bac22f" + }, + "state": "0fe2eb2410a4", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.result-null:settled", + "observation": { + "sender": ["e58ae363032b"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "00e8a3bac22f" + }, + "state": "0fe2eb2410a4", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.inner-ok-missing:settled", + "observation": { + "sender": ["0e00dbc486b4"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "00e8a3bac22f" + }, + "state": "0fe2eb2410a4", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.inner-false-string-error:settled", + "observation": { + "sender": ["3718951f62b7"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "00e8a3bac22f" + }, + "state": "0fe2eb2410a4", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.inner-false-object-error:settled", + "observation": { + "sender": ["a28defbf7f69"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "00e8a3bac22f" + }, + "state": "0fe2eb2410a4", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.outer-refused:settled", + "observation": { + "sender": ["d493a7059b00"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "1b2778bf67a2" + }, + "state": "aa8b30457cff", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.outer-refused-no-message:settled", + "observation": { + "sender": ["6c0349218dd0"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "3e6cf1f04a9c" + }, + "state": "34eee892be9b", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.method-not-found:settled", + "observation": { + "sender": ["ae61c1e930df"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "fa93ca01f266" + }, + "state": "e157741a28a1", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.transport-rejection:settled", + "observation": { + "sender": ["33b2843692a3"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "a197c20578aa" + }, + "state": "f4ca76ee9f22", + "effects": ["60421d882fd2"] + } + }, + { + "id": "sc-prerequisite-push.transport-rejection-no-message:settled", + "observation": { + "sender": ["403ae2f01ce3"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": ["60421d882fd2"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-git.review-preparation-git.status-1.json b/mobile/rpc-foundation/goldens/matrix-git.review-preparation-git.status-1.json new file mode 100644 index 00000000000..999ad75768f --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-git.review-preparation-git.status-1.json @@ -0,0 +1,818 @@ +{ + "operation": "source-control.review-git-preparation", + "family": "git.review-preparation", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0bd335404e92": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "14d2bbeaba4d": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "18d8663eabd9": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "1b2778bf67a2": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "outer refused", + "ok": false + } + }, + "23426bcb23a5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Unable to refresh source control", + "ok": false + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "3b1f10f51ae6": { + "committed": "uncommitted", + "status": { + "error": "outer refused", + "ok": false + } + }, + "41689f68ece0": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "483a7fd348d4": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "6decf368b25a": { + "committed": "uncommitted", + "status": { + "ok": true, + "status": { + "$rpc": "null" + } + } + }, + "85dbdff1cd63": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "89ca28c45139": { + "committed": "uncommitted", + "status": { + "error": "Unknown method", + "ok": false + } + }, + "8c85ee8c0763": { + "committed": "uncommitted", + "status": { + "error": "Unable to refresh source control", + "ok": false + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "95c2e5ca74fc": { + "committed": "uncommitted", + "status": { + "ok": true, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "ac07554f62ad": { + "committed": "uncommitted", + "status": "unread" + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "c7ee072b3a0f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "da676cfabd9b": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true, + "status": { + "$rpc": "null" + } + } + }, + "dd13d6753285": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "de6ba431eb6a": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "ded34c45400d": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "e10b4a9e84d2": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "fa93ca01f266": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Unknown method", + "ok": false + } + } + }, + "recording": { + "scenario": "matrix-git.review-preparation-git.status-1", + "checkpoints": [ + { + "id": "sc-review-status-normalized.prelude:pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "9270aeb7d9c6" + }, + "state": "ac07554f62ad", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.normal:settled", + "observation": { + "sender": ["302b94359544"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "c7ee072b3a0f" + }, + "state": "95c2e5ca74fc", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.result-absent:settled", + "observation": { + "sender": ["ded34c45400d"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "da676cfabd9b" + }, + "state": "6decf368b25a", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.result-null:settled", + "observation": { + "sender": ["de6ba431eb6a"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "da676cfabd9b" + }, + "state": "6decf368b25a", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.inner-ok-missing:settled", + "observation": { + "sender": ["85dbdff1cd63"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "da676cfabd9b" + }, + "state": "6decf368b25a", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.inner-false-string-error:settled", + "observation": { + "sender": ["14d2bbeaba4d"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "da676cfabd9b" + }, + "state": "6decf368b25a", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.inner-false-object-error:settled", + "observation": { + "sender": ["e10b4a9e84d2"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "da676cfabd9b" + }, + "state": "6decf368b25a", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.outer-refused:settled", + "observation": { + "sender": ["18d8663eabd9"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "1b2778bf67a2" + }, + "state": "3b1f10f51ae6", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.outer-refused-no-message:settled", + "observation": { + "sender": ["41689f68ece0"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "23426bcb23a5" + }, + "state": "8c85ee8c0763", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.method-not-found:settled", + "observation": { + "sender": ["483a7fd348d4"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "fa93ca01f266" + }, + "state": "89ca28c45139", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.transport-rejection:settled", + "observation": { + "sender": ["0bd335404e92"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "a947768bc0ed" + }, + "state": "ac07554f62ad", + "effects": [] + } + }, + { + "id": "sc-review-status-normalized.transport-rejection-no-message:settled", + "observation": { + "sender": ["dd13d6753285"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "c7584e82c72f" + }, + "state": "ac07554f62ad", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-git.push-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-git.push-1.json new file mode 100644 index 00000000000..24dad2ff410 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-git.push-1.json @@ -0,0 +1,1003 @@ +{ + "operation": "source-control.hosted-review-create", + "family": "hostedReview.create-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "06a94a810e5f": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Recorded title\",\"body\":\"Recorded body\",\"draft\":false}}" + }, + "06e930bb7dd8": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "0e00dbc486b4": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "1d6ecb1accd3": { + "outcome": { + "error": "Push failed. Resolve the push error, then try again.", + "ok": false + } + }, + "33b2843692a3": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "3718951f62b7": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "3f946ad0279c": { + "outcome": "uncreated" + }, + "403ae2f01ce3": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "6c0349218dd0": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "7037e9e29078": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "7b027798abe5": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "7c0cf8d696d8": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "95b1f2f379aa": { + "name": "git.push#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "9fca4a23f963": { + "outcome": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "a1f0c8bb5bcd": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a28defbf7f69": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "a942a97a5d17": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a95ae8a9ee57": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "ae61c1e930df": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "d493a7059b00": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "d9fba50c2d0c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Push failed. Resolve the push error, then try again.", + "ok": false + } + }, + "e58ae363032b": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "f9869252c305": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-chain-git.push-1", + "checkpoints": [ + { + "id": "sc-create-pushes-then-creates.prelude:push-pending", + "observation": { + "sender": ["b7a56d89f615"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.normal:create-pending", + "observation": { + "sender": ["f9869252c305", "a1f0c8bb5bcd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.normal:link-pending", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "a942a97a5d17"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.normal:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "7c0cf8d696d8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-absent:create-pending", + "observation": { + "sender": ["7b027798abe5", "a1f0c8bb5bcd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-absent:link-pending", + "observation": { + "sender": ["7b027798abe5", "7037e9e29078", "a942a97a5d17"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-absent:settled", + "observation": { + "sender": ["7b027798abe5", "7037e9e29078", "7c0cf8d696d8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-null:create-pending", + "observation": { + "sender": ["e58ae363032b", "a1f0c8bb5bcd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-null:link-pending", + "observation": { + "sender": ["e58ae363032b", "7037e9e29078", "a942a97a5d17"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-null:settled", + "observation": { + "sender": ["e58ae363032b", "7037e9e29078", "7c0cf8d696d8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-ok-missing:create-pending", + "observation": { + "sender": ["0e00dbc486b4", "a1f0c8bb5bcd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-ok-missing:link-pending", + "observation": { + "sender": ["0e00dbc486b4", "7037e9e29078", "a942a97a5d17"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-ok-missing:settled", + "observation": { + "sender": ["0e00dbc486b4", "7037e9e29078", "7c0cf8d696d8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-string-error:create-pending", + "observation": { + "sender": ["3718951f62b7", "a1f0c8bb5bcd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-string-error:link-pending", + "observation": { + "sender": ["3718951f62b7", "7037e9e29078", "a942a97a5d17"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-string-error:settled", + "observation": { + "sender": ["3718951f62b7", "7037e9e29078", "7c0cf8d696d8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-object-error:create-pending", + "observation": { + "sender": ["a28defbf7f69", "a1f0c8bb5bcd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-object-error:link-pending", + "observation": { + "sender": ["a28defbf7f69", "7037e9e29078", "a942a97a5d17"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-object-error:settled", + "observation": { + "sender": ["a28defbf7f69", "7037e9e29078", "7c0cf8d696d8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused:create-pending", + "observation": { + "sender": ["d493a7059b00"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused:link-pending", + "observation": { + "sender": ["d493a7059b00"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused:settled", + "observation": { + "sender": ["d493a7059b00"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused-no-message:create-pending", + "observation": { + "sender": ["6c0349218dd0"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused-no-message:link-pending", + "observation": { + "sender": ["6c0349218dd0"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused-no-message:settled", + "observation": { + "sender": ["6c0349218dd0"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.method-not-found:create-pending", + "observation": { + "sender": ["ae61c1e930df"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.method-not-found:link-pending", + "observation": { + "sender": ["ae61c1e930df"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.method-not-found:settled", + "observation": { + "sender": ["ae61c1e930df"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection:create-pending", + "observation": { + "sender": ["33b2843692a3"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection:link-pending", + "observation": { + "sender": ["33b2843692a3"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection:settled", + "observation": { + "sender": ["33b2843692a3"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection-no-message:create-pending", + "observation": { + "sender": ["403ae2f01ce3"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection-no-message:link-pending", + "observation": { + "sender": ["403ae2f01ce3"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection-no-message:settled", + "observation": { + "sender": ["403ae2f01ce3"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "d9fba50c2d0c" + }, + "state": "1d6ecb1accd3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-hostedreview.create-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-hostedreview.create-1.json new file mode 100644 index 00000000000..b56a4585c45 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-hostedreview.create-1.json @@ -0,0 +1,1088 @@ +{ + "operation": "source-control.hosted-review-create", + "family": "hostedReview.create-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "06a94a810e5f": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Recorded title\",\"body\":\"Recorded body\",\"draft\":false}}" + }, + "06e930bb7dd8": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "1259beb067fd": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "1843823ecb97": { + "outcome": { + "error": "Cannot read properties of undefined (reading 'ok')", + "ok": false + } + }, + "1b2778bf67a2": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "outer refused", + "ok": false + } + }, + "23b9cc94ff6c": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "2f9159f7046c": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "3a952f7d5dc7": { + "outcome": { + "error": "result.error.replace is not a function", + "ok": false + } + }, + "3c6a5a164e8a": { + "outcome": { + "error": "", + "ok": false + } + }, + "3d869a96636a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "result.error.replace is not a function", + "ok": false + } + }, + "3f946ad0279c": { + "outcome": "uncreated" + }, + "401c5b683797": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "459f52ed3a68": { + "outcome": { + "error": "Push succeeded, but PR creation failed: inner refused", + "ok": false + } + }, + "5d2f139da2de": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "6b5107782544": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "6d3c8e6e0154": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Push succeeded, but PR creation failed: inner refused", + "ok": false + } + }, + "7037e9e29078": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "7c0cf8d696d8": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "7e6f30eeafc3": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "7f2deeb332e4": { + "outcome": { + "error": "Cannot read properties of null (reading 'ok')", + "ok": false + } + }, + "859f9a1daf06": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "8a78c581fc05": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Push succeeded, but PR creation failed: refused", + "ok": false + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "95b1f2f379aa": { + "name": "git.push#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "9fca4a23f963": { + "outcome": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "a197c20578aa": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "transport failure", + "ok": false + } + }, + "a1f0c8bb5bcd": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a942a97a5d17": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a95ae8a9ee57": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "aa8b30457cff": { + "outcome": { + "error": "outer refused", + "ok": false + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "c9719bcd483a": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "d14a0dd639ad": { + "outcome": { + "error": "Failed to create pull request", + "ok": false + } + }, + "da16a2c8f57e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Cannot read properties of null (reading 'ok')", + "ok": false + } + }, + "de2020b72add": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Cannot read properties of undefined (reading 'ok')", + "ok": false + } + }, + "e12183bfd2c3": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Failed to create pull request", + "ok": false + } + }, + "e157741a28a1": { + "outcome": { + "error": "Unknown method", + "ok": false + } + }, + "e892f90f62a0": { + "outcome": { + "error": "Push succeeded, but PR creation failed: refused", + "ok": false + } + }, + "f2a1b4ba33a3": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "f4ca76ee9f22": { + "outcome": { + "error": "transport failure", + "ok": false + } + }, + "f9869252c305": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "fa93ca01f266": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Unknown method", + "ok": false + } + }, + "fb4429083480": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "", + "ok": false + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-chain-hostedreview.create-1", + "checkpoints": [ + { + "id": "sc-create-pushes-then-creates.prelude:push-pending", + "observation": { + "sender": ["b7a56d89f615"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.prelude:create-pending", + "observation": { + "sender": ["f9869252c305", "a1f0c8bb5bcd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.normal:link-pending", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "a942a97a5d17"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.normal:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "7c0cf8d696d8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-absent:link-pending", + "observation": { + "sender": ["f9869252c305", "1259beb067fd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "de2020b72add" + }, + "state": "1843823ecb97", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-absent:settled", + "observation": { + "sender": ["f9869252c305", "1259beb067fd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "de2020b72add" + }, + "state": "1843823ecb97", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-null:link-pending", + "observation": { + "sender": ["f9869252c305", "23b9cc94ff6c"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "da16a2c8f57e" + }, + "state": "7f2deeb332e4", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-null:settled", + "observation": { + "sender": ["f9869252c305", "23b9cc94ff6c"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "da16a2c8f57e" + }, + "state": "7f2deeb332e4", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-ok-missing:link-pending", + "observation": { + "sender": ["f9869252c305", "f2a1b4ba33a3"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "8a78c581fc05" + }, + "state": "e892f90f62a0", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-ok-missing:settled", + "observation": { + "sender": ["f9869252c305", "f2a1b4ba33a3"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "8a78c581fc05" + }, + "state": "e892f90f62a0", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-string-error:link-pending", + "observation": { + "sender": ["f9869252c305", "7e6f30eeafc3"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "6d3c8e6e0154" + }, + "state": "459f52ed3a68", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-string-error:settled", + "observation": { + "sender": ["f9869252c305", "7e6f30eeafc3"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "6d3c8e6e0154" + }, + "state": "459f52ed3a68", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-object-error:link-pending", + "observation": { + "sender": ["f9869252c305", "859f9a1daf06"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "3d869a96636a" + }, + "state": "3a952f7d5dc7", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-object-error:settled", + "observation": { + "sender": ["f9869252c305", "859f9a1daf06"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "3d869a96636a" + }, + "state": "3a952f7d5dc7", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused:link-pending", + "observation": { + "sender": ["f9869252c305", "c9719bcd483a"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "1b2778bf67a2" + }, + "state": "aa8b30457cff", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused:settled", + "observation": { + "sender": ["f9869252c305", "c9719bcd483a"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "1b2778bf67a2" + }, + "state": "aa8b30457cff", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused-no-message:link-pending", + "observation": { + "sender": ["f9869252c305", "2f9159f7046c"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "e12183bfd2c3" + }, + "state": "d14a0dd639ad", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused-no-message:settled", + "observation": { + "sender": ["f9869252c305", "2f9159f7046c"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "e12183bfd2c3" + }, + "state": "d14a0dd639ad", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.method-not-found:link-pending", + "observation": { + "sender": ["f9869252c305", "5d2f139da2de"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "fa93ca01f266" + }, + "state": "e157741a28a1", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.method-not-found:settled", + "observation": { + "sender": ["f9869252c305", "5d2f139da2de"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "fa93ca01f266" + }, + "state": "e157741a28a1", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection:link-pending", + "observation": { + "sender": ["f9869252c305", "6b5107782544"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "a197c20578aa" + }, + "state": "f4ca76ee9f22", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection:settled", + "observation": { + "sender": ["f9869252c305", "6b5107782544"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "a197c20578aa" + }, + "state": "f4ca76ee9f22", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection-no-message:link-pending", + "observation": { + "sender": ["f9869252c305", "401c5b683797"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection-no-message:settled", + "observation": { + "sender": ["f9869252c305", "401c5b683797"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-worktree.set-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-worktree.set-1.json new file mode 100644 index 00000000000..b32aface165 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-worktree.set-1.json @@ -0,0 +1,863 @@ +{ + "operation": "source-control.hosted-review-create", + "family": "hostedReview.create-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "03696d515352": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "06a94a810e5f": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Recorded title\",\"body\":\"Recorded body\",\"draft\":false}}" + }, + "06e930bb7dd8": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "1f4d49e300b6": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "linkError": "Unknown method", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "2da91c4e3162": { + "outcome": { + "linkError": "transport failure", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "302435bf7648": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "3f946ad0279c": { + "outcome": "uncreated" + }, + "3ff86ed23cf9": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "linkError": "Failed to update linked review", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "41e416df769f": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "4476976cf9df": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "linkError": "outer refused", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "574b5d61268a": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "59bc10a51ac0": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "7037e9e29078": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "7c0cf8d696d8": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "84157fb6091a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "linkError": "transport failure", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "8b3187a47892": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "94c5e366b94b": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "95b1f2f379aa": { + "name": "git.push#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "9fca4a23f963": { + "outcome": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "a1f0c8bb5bcd": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a942a97a5d17": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a95ae8a9ee57": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "aa3d9af19871": { + "outcome": { + "linkError": "", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "b6f80e2d9da3": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "ce725d12fb34": { + "outcome": { + "linkError": "Unknown method", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "d298ce165342": { + "outcome": { + "linkError": "outer refused", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "e107a27fa4c8": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "e5dbe1f8903e": { + "outcome": { + "linkError": "Failed to update linked review", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "e6692ac4c9c1": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "e9febbcef43b": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "linkError": "", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "f9869252c305": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-chain-worktree.set-1", + "checkpoints": [ + { + "id": "sc-create-pushes-then-creates.prelude:push-pending", + "observation": { + "sender": ["b7a56d89f615"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.prelude:create-pending", + "observation": { + "sender": ["f9869252c305", "a1f0c8bb5bcd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.prelude:link-pending", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "a942a97a5d17"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.normal:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "7c0cf8d696d8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-absent:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "59bc10a51ac0"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.result-null:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "41e416df769f"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-ok-missing:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "e107a27fa4c8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-string-error:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "94c5e366b94b"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.inner-false-object-error:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "8b3187a47892"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "574b5d61268a"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "4476976cf9df" + }, + "state": "d298ce165342", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.outer-refused-no-message:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "03696d515352"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "3ff86ed23cf9" + }, + "state": "e5dbe1f8903e", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.method-not-found:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "302435bf7648"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "1f4d49e300b6" + }, + "state": "ce725d12fb34", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "e6692ac4c9c1"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "84157fb6091a" + }, + "state": "2da91c4e3162", + "effects": [] + } + }, + { + "id": "sc-create-pushes-then-creates.transport-rejection-no-message:settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "b6f80e2d9da3"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "e9febbcef43b" + }, + "state": "aa3d9af19871", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.bulkstage-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.bulkstage-1.json new file mode 100644 index 00000000000..2c32a21683d --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.bulkstage-1.json @@ -0,0 +1,2769 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02652fe244f8": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a06528c313d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Failed to stage changes", + "ok": false + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "1b2778bf67a2": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "outer refused", + "ok": false + } + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "287d2ce39488": { + "outcome": { + "error": "Failed to stage changes", + "ok": false + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "2ca613cdd085": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "2ebbc5c27f40": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "3c6a5a164e8a": { + "outcome": { + "error": "", + "ok": false + } + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "614d26fc14b1": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "68f9e0c8d8d4": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "6a093ad5f233": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8c497b3b4121": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "906b5573d5d5": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a197c20578aa": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "transport failure", + "ok": false + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "aa8b30457cff": { + "outcome": { + "error": "outer refused", + "ok": false + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c7abd39252d2": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e157741a28a1": { + "outcome": { + "error": "Unknown method", + "ok": false + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "eb4f060af2b9": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "f4ca76ee9f22": { + "outcome": { + "error": "transport failure", + "ok": false + } + }, + "fa93ca01f266": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Unknown method", + "ok": false + } + }, + "fb4429083480": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "", + "ok": false + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-git.bulkstage-1", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c7abd39252d2", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c7abd39252d2", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c7abd39252d2", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c7abd39252d2", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c7abd39252d2", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": [ + "302b94359544", + "c7abd39252d2", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:generate-message-pending", + "observation": { + "sender": ["302b94359544", "02652fe244f8", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "02652fe244f8", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "02652fe244f8", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:push-pending", + "observation": { + "sender": [ + "302b94359544", + "02652fe244f8", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": [ + "302b94359544", + "02652fe244f8", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": [ + "302b94359544", + "02652fe244f8", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:generate-message-pending", + "observation": { + "sender": ["302b94359544", "8c497b3b4121", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "8c497b3b4121", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "8c497b3b4121", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:push-pending", + "observation": { + "sender": [ + "302b94359544", + "8c497b3b4121", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": [ + "302b94359544", + "8c497b3b4121", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": [ + "302b94359544", + "8c497b3b4121", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:generate-message-pending", + "observation": { + "sender": ["302b94359544", "2ebbc5c27f40", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "2ebbc5c27f40", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "2ebbc5c27f40", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:push-pending", + "observation": { + "sender": [ + "302b94359544", + "2ebbc5c27f40", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "2ebbc5c27f40", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": [ + "302b94359544", + "2ebbc5c27f40", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:generate-message-pending", + "observation": { + "sender": ["302b94359544", "eb4f060af2b9", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "eb4f060af2b9", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "eb4f060af2b9", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:push-pending", + "observation": { + "sender": [ + "302b94359544", + "eb4f060af2b9", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "eb4f060af2b9", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": [ + "302b94359544", + "eb4f060af2b9", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:generate-message-pending", + "observation": { + "sender": ["302b94359544", "2ca613cdd085"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "1b2778bf67a2" + }, + "state": "aa8b30457cff", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:commit-pending", + "observation": { + "sender": ["302b94359544", "2ca613cdd085"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "1b2778bf67a2" + }, + "state": "aa8b30457cff", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:prefill-pending", + "observation": { + "sender": ["302b94359544", "2ca613cdd085"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "1b2778bf67a2" + }, + "state": "aa8b30457cff", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:push-pending", + "observation": { + "sender": ["302b94359544", "2ca613cdd085"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "1b2778bf67a2" + }, + "state": "aa8b30457cff", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": ["302b94359544", "2ca613cdd085"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "1b2778bf67a2" + }, + "state": "aa8b30457cff", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": ["302b94359544", "2ca613cdd085"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "1b2778bf67a2" + }, + "state": "aa8b30457cff", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:generate-message-pending", + "observation": { + "sender": ["302b94359544", "906b5573d5d5"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "0a06528c313d" + }, + "state": "287d2ce39488", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:commit-pending", + "observation": { + "sender": ["302b94359544", "906b5573d5d5"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "0a06528c313d" + }, + "state": "287d2ce39488", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:prefill-pending", + "observation": { + "sender": ["302b94359544", "906b5573d5d5"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "0a06528c313d" + }, + "state": "287d2ce39488", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:push-pending", + "observation": { + "sender": ["302b94359544", "906b5573d5d5"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "0a06528c313d" + }, + "state": "287d2ce39488", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": ["302b94359544", "906b5573d5d5"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "0a06528c313d" + }, + "state": "287d2ce39488", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": ["302b94359544", "906b5573d5d5"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "0a06528c313d" + }, + "state": "287d2ce39488", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:generate-message-pending", + "observation": { + "sender": ["302b94359544", "68f9e0c8d8d4"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fa93ca01f266" + }, + "state": "e157741a28a1", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:commit-pending", + "observation": { + "sender": ["302b94359544", "68f9e0c8d8d4"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fa93ca01f266" + }, + "state": "e157741a28a1", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:prefill-pending", + "observation": { + "sender": ["302b94359544", "68f9e0c8d8d4"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fa93ca01f266" + }, + "state": "e157741a28a1", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:push-pending", + "observation": { + "sender": ["302b94359544", "68f9e0c8d8d4"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fa93ca01f266" + }, + "state": "e157741a28a1", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": ["302b94359544", "68f9e0c8d8d4"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fa93ca01f266" + }, + "state": "e157741a28a1", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": ["302b94359544", "68f9e0c8d8d4"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fa93ca01f266" + }, + "state": "e157741a28a1", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:generate-message-pending", + "observation": { + "sender": ["302b94359544", "614d26fc14b1"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "a197c20578aa" + }, + "state": "f4ca76ee9f22", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:commit-pending", + "observation": { + "sender": ["302b94359544", "614d26fc14b1"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "a197c20578aa" + }, + "state": "f4ca76ee9f22", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:prefill-pending", + "observation": { + "sender": ["302b94359544", "614d26fc14b1"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "a197c20578aa" + }, + "state": "f4ca76ee9f22", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:push-pending", + "observation": { + "sender": ["302b94359544", "614d26fc14b1"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "a197c20578aa" + }, + "state": "f4ca76ee9f22", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": ["302b94359544", "614d26fc14b1"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "a197c20578aa" + }, + "state": "f4ca76ee9f22", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": ["302b94359544", "614d26fc14b1"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "a197c20578aa" + }, + "state": "f4ca76ee9f22", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:generate-message-pending", + "observation": { + "sender": ["302b94359544", "6a093ad5f233"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:commit-pending", + "observation": { + "sender": ["302b94359544", "6a093ad5f233"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:prefill-pending", + "observation": { + "sender": ["302b94359544", "6a093ad5f233"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:push-pending", + "observation": { + "sender": ["302b94359544", "6a093ad5f233"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": ["302b94359544", "6a093ad5f233"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": ["302b94359544", "6a093ad5f233"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": ["368b0b9ce80a"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.commit-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.commit-1.json new file mode 100644 index 00000000000..ad5c21d71cb --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.commit-1.json @@ -0,0 +1,3254 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "0e4e820a7323": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "1d83527e29e1": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "1dcf573f4df7": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "2c921c059023": { + "outcome": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "Commit failed", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "2e35579e2fc7": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "Commit failed", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "33282210f096": { + "outcome": { + "commitMessage": "feat: recorded", + "committed": false, + "error": { + "message": "inner refused" + }, + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "43c38f02e8d3": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-5", + "ok": false + } + } + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "4edcda8d7196": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6769762c413a": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6ba30d61e50b": { + "outcome": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "6c7a8beeb4c2": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-5", + "ok": false + } + } + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "6e12eca3f727": { + "outcome": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "71d1010eb04f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "transport failure", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "73defac1bd0b": { + "outcome": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "7c91e223d962": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "83cdbcf01e38": { + "outcome": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "inner refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "85064683fc9c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "85e126c40505": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "commitMessage": "feat: recorded", + "committed": false, + "error": { + "message": "inner refused" + }, + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "8db8d9c4f48b": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "ab18fd2d5419": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "aceb861a4f8d": { + "outcome": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "ba731ea609ad": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "d49f246ff85c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "inner refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e3b66d749186": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "e5c0887630e6": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-5", + "ok": false + } + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "f16335c11521": { + "outcome": { + "commitMessage": "feat: recorded", + "committed": false, + "error": "transport failure", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-git.commit-1", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8db8d9c4f48b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8db8d9c4f48b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8db8d9c4f48b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8db8d9c4f48b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "0e4e820a7323" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "0e4e820a7323" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "0e4e820a7323" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "0e4e820a7323" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "e3b66d749186" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "85064683fc9c" + }, + "state": "73defac1bd0b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "e3b66d749186" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "85064683fc9c" + }, + "state": "73defac1bd0b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "e3b66d749186" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "85064683fc9c" + }, + "state": "73defac1bd0b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "e3b66d749186" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "85064683fc9c" + }, + "state": "73defac1bd0b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "6769762c413a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "d49f246ff85c" + }, + "state": "83cdbcf01e38", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "6769762c413a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "d49f246ff85c" + }, + "state": "83cdbcf01e38", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "6769762c413a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "d49f246ff85c" + }, + "state": "83cdbcf01e38", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "6769762c413a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "d49f246ff85c" + }, + "state": "83cdbcf01e38", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "ab18fd2d5419" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "85e126c40505" + }, + "state": "33282210f096", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "ab18fd2d5419" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "85e126c40505" + }, + "state": "33282210f096", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "ab18fd2d5419" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "85e126c40505" + }, + "state": "33282210f096", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "ab18fd2d5419" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "85e126c40505" + }, + "state": "33282210f096", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "43c38f02e8d3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "7c91e223d962" + }, + "state": "aceb861a4f8d", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "43c38f02e8d3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "7c91e223d962" + }, + "state": "aceb861a4f8d", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "43c38f02e8d3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "7c91e223d962" + }, + "state": "aceb861a4f8d", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "43c38f02e8d3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "7c91e223d962" + }, + "state": "aceb861a4f8d", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "e5c0887630e6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "e5c0887630e6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "e5c0887630e6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "e5c0887630e6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "2e35579e2fc7" + }, + "state": "2c921c059023", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "6c7a8beeb4c2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "1dcf573f4df7" + }, + "state": "6e12eca3f727", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "6c7a8beeb4c2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "1dcf573f4df7" + }, + "state": "6e12eca3f727", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "6c7a8beeb4c2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "1dcf573f4df7" + }, + "state": "6e12eca3f727", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "6c7a8beeb4c2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "1dcf573f4df7" + }, + "state": "6e12eca3f727", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "4edcda8d7196" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "71d1010eb04f" + }, + "state": "f16335c11521", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "4edcda8d7196" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "71d1010eb04f" + }, + "state": "f16335c11521", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "4edcda8d7196" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "71d1010eb04f" + }, + "state": "f16335c11521", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "4edcda8d7196" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "71d1010eb04f" + }, + "state": "f16335c11521", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "ba731ea609ad" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "1d83527e29e1" + }, + "state": "6ba30d61e50b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "ba731ea609ad" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "1d83527e29e1" + }, + "state": "6ba30d61e50b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "ba731ea609ad" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "1d83527e29e1" + }, + "state": "6ba30d61e50b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "ba731ea609ad" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "1d83527e29e1" + }, + "state": "6ba30d61e50b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.generatecommitmessage-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.generatecommitmessage-1.json new file mode 100644 index 00000000000..fcd22440108 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.generatecommitmessage-1.json @@ -0,0 +1,2149 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2a7b021ae7bf": { + "outcome": { + "committed": false, + "error": "Could not generate a commit message. Add one in Source Control, then retry.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "31141af16c2d": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "3213e432016c": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-4", + "ok": false + } + } + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "3c03a92720a9": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true + } + } + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "51a0329cc41b": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-4", + "ok": false + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "83565082fc86": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "8704e71c3b98": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "a93f3dc8c4a1": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": false, + "error": "Could not generate a commit message. Add one in Source Control, then retry.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "be35b33cb39b": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-4", + "ok": false + } + } + }, + "c39c20fa07f2": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "c948c78b7129": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "fcf8c7168aa5": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-git.generatecommitmessage-1", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3c03a92720a9"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3c03a92720a9"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3c03a92720a9"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3c03a92720a9"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3c03a92720a9"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "fcf8c7168aa5"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "fcf8c7168aa5"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "fcf8c7168aa5"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "fcf8c7168aa5"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "fcf8c7168aa5"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "8704e71c3b98"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "8704e71c3b98"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "8704e71c3b98"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "8704e71c3b98"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "8704e71c3b98"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "83565082fc86"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "83565082fc86"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "83565082fc86"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "83565082fc86"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "83565082fc86"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c948c78b7129"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c948c78b7129"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c948c78b7129"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c948c78b7129"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c948c78b7129"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "be35b33cb39b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "be35b33cb39b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "be35b33cb39b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "be35b33cb39b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "be35b33cb39b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "51a0329cc41b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "51a0329cc41b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "51a0329cc41b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "51a0329cc41b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "51a0329cc41b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3213e432016c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3213e432016c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3213e432016c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3213e432016c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "3213e432016c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a93f3dc8c4a1" + }, + "state": "2a7b021ae7bf", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "31141af16c2d"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "31141af16c2d"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "31141af16c2d"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "31141af16c2d"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "31141af16c2d"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c39c20fa07f2"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c39c20fa07f2"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c39c20fa07f2"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c39c20fa07f2"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "c39c20fa07f2"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.push-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.push-1.json new file mode 100644 index 00000000000..25a7e8e32ab --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.push-1.json @@ -0,0 +1,2439 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "0bf318ff290e": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true + } + } + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2753bd712186": { + "outcome": { + "committed": true, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "314223d33794": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "33b2843692a3": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "3b3b6edb80e0": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "403ae2f01ce3": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "44ee1cfb7fb0": { + "outcome": { + "committed": true, + "error": "Failed to push commits", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6bcd8388e50a": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "6c71b1b41cc9": { + "outcome": { + "committed": true, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "72d3658278c1": { + "outcome": { + "committed": true, + "error": "", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "7b7ef5bfe32e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Failed to push commits", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "7cc31dea5812": { + "outcome": { + "committed": true, + "error": "transport failure", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "847bd42a1815": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-8", + "ok": false + } + } + }, + "89b0fc55092d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "transport failure", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a68134b822a1": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b74fa1c5741d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c5542a51228c": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "de35bdb3d3ce": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-8", + "ok": false + } + } + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e23100c7317f": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-8", + "ok": false + } + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "ebe3b70aca42": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-git.push-1", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "0bf318ff290e", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "0bf318ff290e", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "3b3b6edb80e0", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "3b3b6edb80e0", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "6bcd8388e50a", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "6bcd8388e50a", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "a68134b822a1", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "a68134b822a1", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "c5542a51228c", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "c5542a51228c", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "de35bdb3d3ce" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "ebe3b70aca42" + }, + "state": "2753bd712186", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "de35bdb3d3ce" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "ebe3b70aca42" + }, + "state": "2753bd712186", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "e23100c7317f" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "7b7ef5bfe32e" + }, + "state": "44ee1cfb7fb0", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "e23100c7317f" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "7b7ef5bfe32e" + }, + "state": "44ee1cfb7fb0", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "847bd42a1815" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "b74fa1c5741d" + }, + "state": "6c71b1b41cc9", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "847bd42a1815" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "b74fa1c5741d" + }, + "state": "6c71b1b41cc9", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "33b2843692a3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "89b0fc55092d" + }, + "state": "7cc31dea5812", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "33b2843692a3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "89b0fc55092d" + }, + "state": "7cc31dea5812", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "403ae2f01ce3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "314223d33794" + }, + "state": "72d3658278c1", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "403ae2f01ce3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "314223d33794" + }, + "state": "72d3658278c1", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-1.json new file mode 100644 index 00000000000..8a96a264a4f --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-1.json @@ -0,0 +1,2410 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0179846b4707": { + "name": "git.status#2", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "0bd335404e92": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "14d2bbeaba4d": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "18d8663eabd9": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "1b8ac3cc961b": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Branch changed while preparing the pull request.", + "ok": false, + "status": { + "$rpc": "null" + } + } + }, + "2055f5236a47": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "333050fbf89e": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "41689f68ece0": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "483a7fd348d4": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "803cca0ce2b1": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "85dbdff1cd63": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "d8004526bf7c": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "dd13d6753285": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "de624aa7a76c": { + "outcome": { + "error": "Branch changed while preparing the pull request.", + "ok": false, + "status": { + "$rpc": "null" + } + } + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "de6ba431eb6a": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "ded34c45400d": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "e10b4a9e84d2": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "e133a9bbad2b": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "success": true + } + } + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-git.status-1", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:stage-pending", + "observation": { + "sender": ["ded34c45400d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:generate-message-pending", + "observation": { + "sender": ["ded34c45400d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:commit-pending", + "observation": { + "sender": ["ded34c45400d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:prefill-pending", + "observation": { + "sender": ["ded34c45400d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:push-pending", + "observation": { + "sender": ["ded34c45400d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": ["ded34c45400d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": ["ded34c45400d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:stage-pending", + "observation": { + "sender": ["de6ba431eb6a"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:generate-message-pending", + "observation": { + "sender": ["de6ba431eb6a"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:commit-pending", + "observation": { + "sender": ["de6ba431eb6a"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:prefill-pending", + "observation": { + "sender": ["de6ba431eb6a"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:push-pending", + "observation": { + "sender": ["de6ba431eb6a"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": ["de6ba431eb6a"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": ["de6ba431eb6a"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:stage-pending", + "observation": { + "sender": ["85dbdff1cd63"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:generate-message-pending", + "observation": { + "sender": ["85dbdff1cd63"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:commit-pending", + "observation": { + "sender": ["85dbdff1cd63"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:prefill-pending", + "observation": { + "sender": ["85dbdff1cd63"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:push-pending", + "observation": { + "sender": ["85dbdff1cd63"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": ["85dbdff1cd63"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": ["85dbdff1cd63"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:stage-pending", + "observation": { + "sender": ["14d2bbeaba4d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:generate-message-pending", + "observation": { + "sender": ["14d2bbeaba4d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:commit-pending", + "observation": { + "sender": ["14d2bbeaba4d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:prefill-pending", + "observation": { + "sender": ["14d2bbeaba4d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:push-pending", + "observation": { + "sender": ["14d2bbeaba4d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": ["14d2bbeaba4d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": ["14d2bbeaba4d"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:stage-pending", + "observation": { + "sender": ["e10b4a9e84d2"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:generate-message-pending", + "observation": { + "sender": ["e10b4a9e84d2"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:commit-pending", + "observation": { + "sender": ["e10b4a9e84d2"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:prefill-pending", + "observation": { + "sender": ["e10b4a9e84d2"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:push-pending", + "observation": { + "sender": ["e10b4a9e84d2"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": ["e10b4a9e84d2"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": ["e10b4a9e84d2"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "1b8ac3cc961b" + }, + "state": "de624aa7a76c", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:stage-pending", + "observation": { + "sender": ["18d8663eabd9", "125fbea5f50a"], + "payloads": ["5e330d49c396", "333050fbf89e"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:generate-message-pending", + "observation": { + "sender": ["18d8663eabd9", "125fbea5f50a"], + "payloads": ["5e330d49c396", "333050fbf89e"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:commit-pending", + "observation": { + "sender": ["18d8663eabd9", "d8004526bf7c", "8ca8f03c0069"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:prefill-pending", + "observation": { + "sender": ["18d8663eabd9", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:push-pending", + "observation": { + "sender": ["18d8663eabd9", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": ["18d8663eabd9", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": ["18d8663eabd9", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:stage-pending", + "observation": { + "sender": ["41689f68ece0", "125fbea5f50a"], + "payloads": ["5e330d49c396", "333050fbf89e"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:generate-message-pending", + "observation": { + "sender": ["41689f68ece0", "125fbea5f50a"], + "payloads": ["5e330d49c396", "333050fbf89e"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:commit-pending", + "observation": { + "sender": ["41689f68ece0", "d8004526bf7c", "8ca8f03c0069"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:prefill-pending", + "observation": { + "sender": ["41689f68ece0", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:push-pending", + "observation": { + "sender": ["41689f68ece0", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": ["41689f68ece0", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": ["41689f68ece0", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:stage-pending", + "observation": { + "sender": ["483a7fd348d4", "125fbea5f50a"], + "payloads": ["5e330d49c396", "333050fbf89e"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:generate-message-pending", + "observation": { + "sender": ["483a7fd348d4", "125fbea5f50a"], + "payloads": ["5e330d49c396", "333050fbf89e"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:commit-pending", + "observation": { + "sender": ["483a7fd348d4", "d8004526bf7c", "8ca8f03c0069"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:prefill-pending", + "observation": { + "sender": ["483a7fd348d4", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:push-pending", + "observation": { + "sender": ["483a7fd348d4", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": ["483a7fd348d4", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": ["483a7fd348d4", "d8004526bf7c", "e133a9bbad2b", "2055f5236a47"], + "payloads": ["5e330d49c396", "333050fbf89e", "803cca0ce2b1", "0179846b4707"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:stage-pending", + "observation": { + "sender": ["0bd335404e92"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:generate-message-pending", + "observation": { + "sender": ["0bd335404e92"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:commit-pending", + "observation": { + "sender": ["0bd335404e92"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:prefill-pending", + "observation": { + "sender": ["0bd335404e92"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:push-pending", + "observation": { + "sender": ["0bd335404e92"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": ["0bd335404e92"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": ["0bd335404e92"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:stage-pending", + "observation": { + "sender": ["dd13d6753285"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:generate-message-pending", + "observation": { + "sender": ["dd13d6753285"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:commit-pending", + "observation": { + "sender": ["dd13d6753285"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:prefill-pending", + "observation": { + "sender": ["dd13d6753285"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:push-pending", + "observation": { + "sender": ["dd13d6753285"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": ["dd13d6753285"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": ["dd13d6753285"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-2.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-2.json new file mode 100644 index 00000000000..e3c9d795e92 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-2.json @@ -0,0 +1,2640 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "006d7b20ed48": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "08adfb09d756": { + "outcome": { + "committed": false, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "0ef828d1fdbe": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "1f58e79984d0": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "21d39cc79aae": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "267a30accd66": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": false, + "error": "Unable to refresh source control", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "26d585682271": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": false, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6491de11ec00": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": false, + "error": "Branch changed while preparing the pull request.", + "ok": false, + "status": { + "$rpc": "null" + } + } + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "6e27cc3e956c": { + "outcome": { + "committed": false, + "error": "Unable to refresh source control", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "6ed121059b8b": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "76aa14fccf64": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "8f82108df54b": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b57c26002c53": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "b61524b47452": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": false, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "bc686a34f1d7": { + "outcome": { + "committed": false, + "error": "Branch changed while preparing the pull request.", + "ok": false, + "status": { + "$rpc": "null" + } + } + }, + "c16d10b6185c": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c459dd805bb5": { + "outcome": { + "committed": false, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "c8542dd26dfe": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-git.status-2", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "b57c26002c53"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "b57c26002c53"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "b57c26002c53"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "b57c26002c53"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "b57c26002c53"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "b57c26002c53"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c16d10b6185c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c16d10b6185c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c16d10b6185c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c16d10b6185c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c16d10b6185c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c16d10b6185c"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c8542dd26dfe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c8542dd26dfe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c8542dd26dfe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c8542dd26dfe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c8542dd26dfe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "c8542dd26dfe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "6ed121059b8b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "6ed121059b8b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "6ed121059b8b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "6ed121059b8b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "6ed121059b8b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "6ed121059b8b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "76aa14fccf64"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "76aa14fccf64"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "76aa14fccf64"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "76aa14fccf64"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "76aa14fccf64"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "76aa14fccf64"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "6491de11ec00" + }, + "state": "bc686a34f1d7", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "21d39cc79aae"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "26d585682271" + }, + "state": "c459dd805bb5", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "21d39cc79aae"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "26d585682271" + }, + "state": "c459dd805bb5", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "21d39cc79aae"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "26d585682271" + }, + "state": "c459dd805bb5", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "21d39cc79aae"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "26d585682271" + }, + "state": "c459dd805bb5", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "21d39cc79aae"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "26d585682271" + }, + "state": "c459dd805bb5", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "21d39cc79aae"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "26d585682271" + }, + "state": "c459dd805bb5", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "8f82108df54b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "267a30accd66" + }, + "state": "6e27cc3e956c", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "8f82108df54b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "267a30accd66" + }, + "state": "6e27cc3e956c", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "8f82108df54b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "267a30accd66" + }, + "state": "6e27cc3e956c", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "8f82108df54b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "267a30accd66" + }, + "state": "6e27cc3e956c", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "8f82108df54b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "267a30accd66" + }, + "state": "6e27cc3e956c", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "8f82108df54b"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "267a30accd66" + }, + "state": "6e27cc3e956c", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "1f58e79984d0"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "b61524b47452" + }, + "state": "08adfb09d756", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "1f58e79984d0"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "b61524b47452" + }, + "state": "08adfb09d756", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "1f58e79984d0"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "b61524b47452" + }, + "state": "08adfb09d756", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "1f58e79984d0"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "b61524b47452" + }, + "state": "08adfb09d756", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "1f58e79984d0"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "b61524b47452" + }, + "state": "08adfb09d756", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "1f58e79984d0"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "b61524b47452" + }, + "state": "08adfb09d756", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "006d7b20ed48"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "006d7b20ed48"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "006d7b20ed48"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "006d7b20ed48"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "006d7b20ed48"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "006d7b20ed48"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "0ef828d1fdbe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:commit-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "0ef828d1fdbe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:prefill-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "0ef828d1fdbe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:push-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "0ef828d1fdbe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "0ef828d1fdbe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "0ef828d1fdbe"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f"], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-3.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-3.json new file mode 100644 index 00000000000..87be6209cf9 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-3.json @@ -0,0 +1,2822 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "01bc4ad46170": { + "outcome": { + "committed": true, + "error": "Branch changed while preparing the pull request.", + "ok": false, + "status": { + "$rpc": "null" + } + } + }, + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "1325f8e894d3": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "2fe96a8d0b5a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "410fa853262b": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-6", + "ok": false + } + } + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "45e49471a27c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "4e53953c9733": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "50eda8efe42e": { + "outcome": { + "committed": true, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6cd42601ee16": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "898de61efa3c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Branch changed while preparing the pull request.", + "ok": false, + "status": { + "$rpc": "null" + } + } + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "8e83fe9850ba": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9299e1dff33e": { + "outcome": { + "committed": true, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "9ca63099691d": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-6", + "ok": false + } + } + }, + "a394e9fcd326": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-6", + "ok": false + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "afd6b6f3573f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Unable to refresh source control", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b7febe684fb8": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "cdd9bcd571e1": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "f4cca647443e": { + "outcome": { + "committed": true, + "error": "Unable to refresh source control", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "f5ed21ae1fc6": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-git.status-3", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "f5ed21ae1fc6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "f5ed21ae1fc6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "f5ed21ae1fc6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "f5ed21ae1fc6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "2fe96a8d0b5a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "2fe96a8d0b5a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "2fe96a8d0b5a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "2fe96a8d0b5a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "8e83fe9850ba" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "8e83fe9850ba" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "8e83fe9850ba" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "8e83fe9850ba" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "b7febe684fb8" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "b7febe684fb8" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "b7febe684fb8" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "b7febe684fb8" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4e53953c9733" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4e53953c9733" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4e53953c9733" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4e53953c9733" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "9ca63099691d" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "1325f8e894d3" + }, + "state": "50eda8efe42e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "9ca63099691d" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "1325f8e894d3" + }, + "state": "50eda8efe42e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "9ca63099691d" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "1325f8e894d3" + }, + "state": "50eda8efe42e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "9ca63099691d" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "1325f8e894d3" + }, + "state": "50eda8efe42e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "410fa853262b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "afd6b6f3573f" + }, + "state": "f4cca647443e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "410fa853262b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "afd6b6f3573f" + }, + "state": "f4cca647443e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "410fa853262b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "afd6b6f3573f" + }, + "state": "f4cca647443e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "410fa853262b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "afd6b6f3573f" + }, + "state": "f4cca647443e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "a394e9fcd326" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "45e49471a27c" + }, + "state": "9299e1dff33e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "a394e9fcd326" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "45e49471a27c" + }, + "state": "9299e1dff33e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "a394e9fcd326" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "45e49471a27c" + }, + "state": "9299e1dff33e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "a394e9fcd326" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "45e49471a27c" + }, + "state": "9299e1dff33e", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "6cd42601ee16" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "6cd42601ee16" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "6cd42601ee16" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "6cd42601ee16" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "cdd9bcd571e1" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "cdd9bcd571e1" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "cdd9bcd571e1" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "cdd9bcd571e1" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59" + ], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-4.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-4.json new file mode 100644 index 00000000000..a9c8b83b1b9 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-4.json @@ -0,0 +1,2278 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "01bc4ad46170": { + "outcome": { + "committed": true, + "error": "Branch changed while preparing the pull request.", + "ok": false, + "status": { + "$rpc": "null" + } + } + }, + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "15e52cb9d2d9": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true + } + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2753bd712186": { + "outcome": { + "committed": true, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "2cb0b04627aa": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-9", + "ok": false + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "34c71c2720e7": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "5f116bb49da3": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-9", + "ok": false + } + } + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "62dc892f13c5": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6c71b1b41cc9": { + "outcome": { + "committed": true, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "73bcd662ebbc": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Unable to refresh source control", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "801aa87beaf2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "898de61efa3c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Branch changed while preparing the pull request.", + "ok": false, + "status": { + "$rpc": "null" + } + } + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a47203a0c57a": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b74fa1c5741d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "cdf1fca5783b": { + "outcome": { + "committed": true, + "error": "Unable to refresh source control", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "daf170162bd9": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "db1d3db375bc": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e914f3a40828": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-9", + "ok": false + } + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "ebe3b70aca42": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-git.status-4", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "15e52cb9d2d9" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "15e52cb9d2d9" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "daf170162bd9" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "daf170162bd9" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "801aa87beaf2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "801aa87beaf2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "db1d3db375bc" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "db1d3db375bc" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "a47203a0c57a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "a47203a0c57a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "898de61efa3c" + }, + "state": "01bc4ad46170", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "5f116bb49da3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "ebe3b70aca42" + }, + "state": "2753bd712186", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "5f116bb49da3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "ebe3b70aca42" + }, + "state": "2753bd712186", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "e914f3a40828" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "73bcd662ebbc" + }, + "state": "cdf1fca5783b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "e914f3a40828" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "73bcd662ebbc" + }, + "state": "cdf1fca5783b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2cb0b04627aa" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "b74fa1c5741d" + }, + "state": "6c71b1b41cc9", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2cb0b04627aa" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "b74fa1c5741d" + }, + "state": "6c71b1b41cc9", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "34c71c2720e7" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "34c71c2720e7" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "a947768bc0ed" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "62dc892f13c5" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "62dc892f13c5" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969" + ], + "settlements": { + "run": "c7584e82c72f" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.create-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.create-1.json new file mode 100644 index 00000000000..5051fd51ac1 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.create-1.json @@ -0,0 +1,2488 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "000efa3053f3": { + "outcome": { + "committed": true, + "error": "Cannot read properties of null (reading 'ok')", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "0215b92c4449": { + "outcome": { + "committed": true, + "error": "Failed to create pull request", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "155c16551bc0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "183dab44d2de": { + "outcome": { + "committed": true, + "error": "inner refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "335c63cb1957": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true + } + } + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "4a4639fa3798": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": { + "message": "inner refused" + }, + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "4b12390e509a": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-11", + "ok": false + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "658bb4ca2398": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6c46647d78ab": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-11", + "ok": false + } + } + }, + "6d9570b41a8b": { + "outcome": { + "committed": true, + "error": "Cannot read properties of undefined (reading 'ok')", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "6e6633f1d2cf": { + "outcome": { + "committed": true, + "error": "outer refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "79e3e96a32ee": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "8ab675a90044": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-11", + "ok": false + } + } + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "8cf9a0df089e": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "91302c0f318e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "transport failure", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a3d6789c75bc": { + "outcome": { + "committed": true, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "a794f08fc368": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "a9be442451de": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Unknown method", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b2814f99b696": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c2d62db0725f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c8ac63638dd4": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "inner refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "c955a0980eb4": { + "outcome": { + "committed": true, + "error": { + "message": "inner refused" + }, + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "d59e8c9e4a5b": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "d6eed3ce26c0": { + "outcome": { + "committed": true, + "error": "", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "dccb31fddadc": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Failed to create pull request", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "dd1b91af7945": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e19dc901cb36": { + "outcome": { + "committed": true, + "error": "refused", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "e6d858bcb05d": { + "outcome": { + "committed": true, + "error": "transport failure", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "f2d31538d6f8": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Cannot read properties of undefined (reading 'ok')", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "f7a1885f58b2": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Cannot read properties of null (reading 'ok')", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-hostedreview.create-1", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "335c63cb1957" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "f2d31538d6f8" + }, + "state": "6d9570b41a8b", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "8cf9a0df089e" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "f7a1885f58b2" + }, + "state": "000efa3053f3", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "155c16551bc0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "b2814f99b696" + }, + "state": "e19dc901cb36", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "a794f08fc368" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "c8ac63638dd4" + }, + "state": "183dab44d2de", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "d59e8c9e4a5b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "4a4639fa3798" + }, + "state": "c955a0980eb4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "6c46647d78ab" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "658bb4ca2398" + }, + "state": "6e6633f1d2cf", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "8ab675a90044" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "dccb31fddadc" + }, + "state": "0215b92c4449", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "4b12390e509a" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "a9be442451de" + }, + "state": "a3d6789c75bc", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "79e3e96a32ee" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "91302c0f318e" + }, + "state": "e6d858bcb05d", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "dd1b91af7945" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "c2d62db0725f" + }, + "state": "d6eed3ce26c0", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-1.json new file mode 100644 index 00000000000..f85869dbf43 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-1.json @@ -0,0 +1,2528 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "16efc4c3e134": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-7", + "ok": false + } + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "1bfbb544c337": { + "outcome": { + "committed": true, + "error": "This branch is not ready for a pull request yet.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27e776272038": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-7", + "ok": false + } + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "510a18903eb7": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-7", + "ok": false + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "5ea657a21118": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6538ade0d25d": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "6a504df2edc9": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "83e80c98d259": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Orca could not confirm whether this branch already has a pull request. Try again in a moment.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "946a415dfd1b": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c52104f2b422": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "dd5d9b4070b7": { + "outcome": { + "committed": true, + "error": "Orca could not confirm whether this branch already has a pull request. Try again in a moment.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e6f94c399ee4": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "This branch is not ready for a pull request yet.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "fe917cde11e2": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true + } + } + }, + "ff1b42f4ed7c": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-1", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "fe917cde11e2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "fe917cde11e2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "fe917cde11e2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "6538ade0d25d" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "6538ade0d25d" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "6538ade0d25d" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "946a415dfd1b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "83e80c98d259" + }, + "state": "dd5d9b4070b7", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "946a415dfd1b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "83e80c98d259" + }, + "state": "dd5d9b4070b7", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "946a415dfd1b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "83e80c98d259" + }, + "state": "dd5d9b4070b7", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "c52104f2b422" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "83e80c98d259" + }, + "state": "dd5d9b4070b7", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "c52104f2b422" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "83e80c98d259" + }, + "state": "dd5d9b4070b7", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "c52104f2b422" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "83e80c98d259" + }, + "state": "dd5d9b4070b7", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "ff1b42f4ed7c" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "83e80c98d259" + }, + "state": "dd5d9b4070b7", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "ff1b42f4ed7c" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "83e80c98d259" + }, + "state": "dd5d9b4070b7", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "ff1b42f4ed7c" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "83e80c98d259" + }, + "state": "dd5d9b4070b7", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "510a18903eb7" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "510a18903eb7" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "510a18903eb7" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "27e776272038" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "27e776272038" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "27e776272038" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "16efc4c3e134" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "16efc4c3e134" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "16efc4c3e134" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "6a504df2edc9" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "6a504df2edc9" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "6a504df2edc9" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "5ea657a21118" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "5ea657a21118" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "5ea657a21118" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "e6f94c399ee4" + }, + "state": "1bfbb544c337", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-2.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-2.json new file mode 100644 index 00000000000..94560aaaf90 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-2.json @@ -0,0 +1,2368 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "0ea11c3b0bda": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "1402e70471f8": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "1ce01a83322f": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-10", + "ok": false + } + } + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2342c6f737d2": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-10", + "ok": false + } + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "3baf33626add": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "This branch is not ready for a pull request yet.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "44dd632a8def": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5a0d2dca259b": { + "outcome": { + "committed": true, + "error": "Orca could not confirm whether this branch already has a pull request. Try again in a moment.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6bdfb4167cc6": { + "outcome": { + "committed": true, + "error": "This branch is not ready for a pull request yet.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "6f10a6bfd795": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "73e6cf23f0b3": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "bf0e050653a2": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "error": "Orca could not confirm whether this branch already has a pull request. Try again in a moment.", + "ok": false, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "d0dab08215c6": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "da6ca0b0c7f1": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-10", + "ok": false + } + } + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "ede606fdecdb": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-2", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "ede606fdecdb" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "ede606fdecdb" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "0ea11c3b0bda" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "0ea11c3b0bda" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "d0dab08215c6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "bf0e050653a2" + }, + "state": "5a0d2dca259b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "d0dab08215c6" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "bf0e050653a2" + }, + "state": "5a0d2dca259b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "44dd632a8def" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "bf0e050653a2" + }, + "state": "5a0d2dca259b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "44dd632a8def" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "bf0e050653a2" + }, + "state": "5a0d2dca259b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "6f10a6bfd795" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "bf0e050653a2" + }, + "state": "5a0d2dca259b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "6f10a6bfd795" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "bf0e050653a2" + }, + "state": "5a0d2dca259b", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "2342c6f737d2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "2342c6f737d2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "1ce01a83322f" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "1ce01a83322f" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "da6ca0b0c7f1" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "da6ca0b0c7f1" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "73e6cf23f0b3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "73e6cf23f0b3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "1402e70471f8" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "1402e70471f8" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939" + ], + "settlements": { + "run": "3baf33626add" + }, + "state": "6bdfb4167cc6", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-worktree.set-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-worktree.set-1.json new file mode 100644 index 00000000000..034f30b9b0c --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-worktree.set-1.json @@ -0,0 +1,1971 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "0fe249ca3852": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-12", + "ok": false + } + } + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "13e54f79599b": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "15281746d27f": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2b5e4002eb52": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "2c6dd148501e": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": "Pull Request created, but Orca could not refresh it yet." + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "ab6081caf799": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-12", + "ok": false + } + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b661d30b2d73": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": "Pull Request created, but Orca could not refresh it yet." + } + }, + "b6f80e2d9da3": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "bfe1edd2ca60": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true + } + } + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "d99d42852fd2": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-12", + "ok": false + } + } + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e6692ac4c9c1": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "f81c9538ae46": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.create-intent-worktree.set-1", + "checkpoints": [ + { + "id": "sc-create-intent-stage-commit-push-create.prelude:initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.prelude:create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.normal:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-absent:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "bfe1edd2ca60" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.result-null:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "f81c9538ae46" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-ok-missing:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "13e54f79599b" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-string-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "15281746d27f" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.inner-false-object-error:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "2b5e4002eb52" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "d99d42852fd2" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "b661d30b2d73" + }, + "state": "2c6dd148501e", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.outer-refused-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ab6081caf799" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "b661d30b2d73" + }, + "state": "2c6dd148501e", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.method-not-found:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "0fe249ca3852" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "b661d30b2d73" + }, + "state": "2c6dd148501e", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "e6692ac4c9c1" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "b661d30b2d73" + }, + "state": "2c6dd148501e", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "sc-create-intent-stage-commit-push-create.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "b6f80e2d9da3" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-hostedreview.eligibility-hostedreview.getcreationeligibility-1.json b/mobile/rpc-foundation/goldens/matrix-hostedreview.eligibility-hostedreview.getcreationeligibility-1.json new file mode 100644 index 00000000000..ccd1bd2bd4f --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-hostedreview.eligibility-hostedreview.getcreationeligibility-1.json @@ -0,0 +1,841 @@ +{ + "operation": "source-control.hosted-review-eligibility", + "family": "hostedReview.eligibility", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "099a55e691ed": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "198e064322d5": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "1c4e890f9aaf": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "24bd84c9fb40": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "gitlab", + "reviewLookupOutcome": "none", + "title": "Host title" + } + }, + "291496f6f93a": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "2cbc383a17fc": { + "eligibility": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "gitlab", + "reviewLookupOutcome": "none", + "title": "Host title" + }, + "prefill": "unresolved" + }, + "301151228fa3": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "refused" + } + }, + "485a0942bda3": { + "eligibility": "unfetched", + "prefill": "unresolved" + }, + "4dfe4f2ad75c": { + "eligibility": { + "$rpc": "null" + }, + "prefill": "unresolved" + }, + "5f12cd4867ce": { + "eligibility": { + "error": "inner refused", + "ok": false + }, + "prefill": "unresolved" + }, + "6506a6ec7ac3": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "6c52d90237b7": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "79c3a2ea5c23": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "7bf63f31c702": { + "eligibility": { + "$rpc": "undefined" + }, + "prefill": "unresolved" + }, + "7fb1231fd64d": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "87a2ebdbec89": { + "eligibility": { + "error": { + "message": "inner refused" + }, + "ok": false + }, + "prefill": "unresolved" + }, + "899a024357b9": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "gitlab", + "reviewLookupOutcome": "none", + "title": "Host title" + } + } + } + }, + "8cef4aaa067c": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9f00dd54ba64": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "inner refused", + "ok": false + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "ad8a954e879d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "message": "inner refused" + }, + "ok": false + } + }, + "b925156655c6": { + "eligibility": { + "error": "refused" + }, + "prefill": "unresolved" + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "cc09b6142ccb": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "e41e491351c2": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee20a1dc39e7": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "null" + } + }, + "fed21873c57f": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + } + }, + "recording": { + "scenario": "matrix-hostedreview.eligibility-hostedreview.getcreationeligibility-1", + "checkpoints": [ + { + "id": "sc-eligibility-fetched.prelude:pending", + "observation": { + "sender": ["e41e491351c2"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "9270aeb7d9c6" + }, + "state": "485a0942bda3", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.normal:settled", + "observation": { + "sender": ["899a024357b9"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "24bd84c9fb40" + }, + "state": "2cbc383a17fc", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.result-absent:settled", + "observation": { + "sender": ["099a55e691ed"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "eb79a9b3682a" + }, + "state": "7bf63f31c702", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.result-null:settled", + "observation": { + "sender": ["1c4e890f9aaf"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "ee20a1dc39e7" + }, + "state": "4dfe4f2ad75c", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.inner-ok-missing:settled", + "observation": { + "sender": ["8cef4aaa067c"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "301151228fa3" + }, + "state": "b925156655c6", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.inner-false-string-error:settled", + "observation": { + "sender": ["6c52d90237b7"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "9f00dd54ba64" + }, + "state": "5f12cd4867ce", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.inner-false-object-error:settled", + "observation": { + "sender": ["fed21873c57f"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "ad8a954e879d" + }, + "state": "87a2ebdbec89", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.outer-refused:settled", + "observation": { + "sender": ["6506a6ec7ac3"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "ee20a1dc39e7" + }, + "state": "4dfe4f2ad75c", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.outer-refused-no-message:settled", + "observation": { + "sender": ["291496f6f93a"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "ee20a1dc39e7" + }, + "state": "4dfe4f2ad75c", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.method-not-found:settled", + "observation": { + "sender": ["198e064322d5"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "ee20a1dc39e7" + }, + "state": "4dfe4f2ad75c", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.transport-rejection:settled", + "observation": { + "sender": ["7fb1231fd64d"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "a947768bc0ed" + }, + "state": "485a0942bda3", + "effects": [] + } + }, + { + "id": "sc-eligibility-fetched.transport-rejection-no-message:settled", + "observation": { + "sender": ["79c3a2ea5c23"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "c7584e82c72f" + }, + "state": "485a0942bda3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-legacy-inventory-files.searchpaths-1.json b/mobile/rpc-foundation/goldens/matrix-legacy-inventory-files.searchpaths-1.json new file mode 100644 index 00000000000..030b834cd85 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-legacy-inventory-files.searchpaths-1.json @@ -0,0 +1,1383 @@ +{ + "operation": "workspace.file-inventory", + "family": "legacy-inventory", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "003a57e2bf31": { + "files": ["alpha.ts"] + }, + "0c8457700f43": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "0d903486cbe8": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 240 + } + }, + "11a8a2850aa6": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "126c76eb14a1": { + "name": "files.searchPaths#2", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"fresh\",\"limit\":16}}" + }, + "1ba589a74085": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "22aae8ed95e4": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "26cf7e0b111e": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "2837f481a843": { + "name": "files.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "3b6419fbab75": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "$rpc": "undefined" + } + }, + "4c6301522bc0": { + "name": "files.list#2", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "602e35a92eec": { + "files": [] + }, + "603254c040fc": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "files": [ + { + "relativePath": "old.ts" + } + ] + } + } + } + }, + "6fcbcfd641a6": { + "name": "files.searchPaths#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"fresh\",\"limit\":16}}" + }, + "869abd7d4761": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 120, + "settledAt": 120, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "99f776858ea4": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "9a2d5b890cfa": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "files": [ + { + "relativePath": "alpha.ts" + } + ] + } + } + } + }, + "9dea95bddfe5": { + "name": "files.searchPaths#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"old\",\"limit\":16}}" + }, + "a129552fdc6e": { + "files": ["third.ts"] + }, + "b2434f1de9f6": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 120 + } + }, + "c0821dc354d7": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "c0b2a9f3a528": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "c3632dc7f843": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 240 + } + }, + "c64a37571efa": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 120, + "settledAt": 120, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "d2ad71e601c4": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "$rpc": "undefined" + } + }, + "d93bbb95c81e": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "daf226a0261c": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "files": [ + { + "relativePath": "fresh.ts" + }, + { + "relativePath": "third.ts" + } + ] + } + } + } + }, + "df7fd0ad658c": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f2e78a366d8a": { + "name": "files.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + } + }, + "recording": { + "scenario": "matrix-legacy-inventory-files.searchpaths-1", + "checkpoints": [ + { + "id": "b1.normal:old-pending", + "observation": { + "sender": ["9a2d5b890cfa"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "003a57e2bf31", + "effects": [] + } + }, + { + "id": "b1.normal:stale-arrived-fresh-pending", + "observation": { + "sender": ["9a2d5b890cfa", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.normal:third-query", + "observation": { + "sender": ["9a2d5b890cfa", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.normal:fresh-arrived", + "observation": { + "sender": ["9a2d5b890cfa", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-absent:old-pending", + "observation": { + "sender": ["0c8457700f43"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-absent:stale-arrived-fresh-pending", + "observation": { + "sender": ["0c8457700f43", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-absent:third-query", + "observation": { + "sender": ["0c8457700f43", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-absent:fresh-arrived", + "observation": { + "sender": ["0c8457700f43", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:old-pending", + "observation": { + "sender": ["26cf7e0b111e"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:stale-arrived-fresh-pending", + "observation": { + "sender": ["26cf7e0b111e", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:third-query", + "observation": { + "sender": ["26cf7e0b111e", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:fresh-arrived", + "observation": { + "sender": ["26cf7e0b111e", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:old-pending", + "observation": { + "sender": ["df7fd0ad658c"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:stale-arrived-fresh-pending", + "observation": { + "sender": ["df7fd0ad658c", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:third-query", + "observation": { + "sender": ["df7fd0ad658c", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:fresh-arrived", + "observation": { + "sender": ["df7fd0ad658c", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:old-pending", + "observation": { + "sender": ["99f776858ea4"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:stale-arrived-fresh-pending", + "observation": { + "sender": ["99f776858ea4", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:third-query", + "observation": { + "sender": ["99f776858ea4", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:fresh-arrived", + "observation": { + "sender": ["99f776858ea4", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:old-pending", + "observation": { + "sender": ["c0b2a9f3a528"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0b2a9f3a528", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:third-query", + "observation": { + "sender": ["c0b2a9f3a528", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:fresh-arrived", + "observation": { + "sender": ["c0b2a9f3a528", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:old-pending", + "observation": { + "sender": ["11a8a2850aa6"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:stale-arrived-fresh-pending", + "observation": { + "sender": ["11a8a2850aa6", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:third-query", + "observation": { + "sender": ["11a8a2850aa6", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:fresh-arrived", + "observation": { + "sender": ["11a8a2850aa6", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:old-pending", + "observation": { + "sender": ["d93bbb95c81e"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:stale-arrived-fresh-pending", + "observation": { + "sender": ["d93bbb95c81e", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:third-query", + "observation": { + "sender": ["d93bbb95c81e", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:fresh-arrived", + "observation": { + "sender": ["d93bbb95c81e", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:old-pending", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:old-pending", + "observation": { + "sender": ["869abd7d4761"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:stale-arrived-fresh-pending", + "observation": { + "sender": ["869abd7d4761", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:third-query", + "observation": { + "sender": ["869abd7d4761", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:fresh-arrived", + "observation": { + "sender": ["869abd7d4761", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:old-pending", + "observation": { + "sender": ["c64a37571efa"], + "payloads": ["9dea95bddfe5"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:stale-arrived-fresh-pending", + "observation": { + "sender": ["c64a37571efa", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:third-query", + "observation": { + "sender": ["c64a37571efa", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:fresh-arrived", + "observation": { + "sender": ["c64a37571efa", "22aae8ed95e4", "c3632dc7f843"], + "payloads": ["9dea95bddfe5", "126c76eb14a1", "f2e78a366d8a"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-legacy-inventory-files.searchpaths-2.json b/mobile/rpc-foundation/goldens/matrix-legacy-inventory-files.searchpaths-2.json new file mode 100644 index 00000000000..0410d032a5a --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-legacy-inventory-files.searchpaths-2.json @@ -0,0 +1,1215 @@ +{ + "operation": "workspace.file-inventory", + "family": "legacy-inventory", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02a03f44e95f": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "039d4c02da97": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 240, + "settledAt": 240, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "0959d2b897c9": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "0d903486cbe8": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 240 + } + }, + "11617076ef90": { + "name": "files.searchPaths#3", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "third", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 360 + } + }, + "1567fc34445b": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "15b2254fad4b": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "files": [ + { + "relativePath": "beta.ts" + } + ] + } + } + } + }, + "1ba589a74085": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "1ea7547b81a5": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "1f232e1642a7": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "2837f481a843": { + "name": "files.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "3642acfe438f": { + "files": ["beta.ts"] + }, + "3b6419fbab75": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "$rpc": "undefined" + } + }, + "43f19e2e0c70": { + "name": "files.searchPaths#3", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"third\",\"limit\":16}}" + }, + "4c6301522bc0": { + "name": "files.list#2", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "602e35a92eec": { + "files": [] + }, + "603254c040fc": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "files": [ + { + "relativePath": "old.ts" + } + ] + } + } + } + }, + "6fcbcfd641a6": { + "name": "files.searchPaths#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"fresh\",\"limit\":16}}" + }, + "825b5246a9b0": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "9dea95bddfe5": { + "name": "files.searchPaths#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"old\",\"limit\":16}}" + }, + "a129552fdc6e": { + "files": ["third.ts"] + }, + "a4b06271def1": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "b2434f1de9f6": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 120 + } + }, + "c0821dc354d7": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "d2ad71e601c4": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "$rpc": "undefined" + } + }, + "daf226a0261c": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "files": [ + { + "relativePath": "fresh.ts" + }, + { + "relativePath": "third.ts" + } + ] + } + } + } + }, + "e0c06b676602": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 240, + "settledAt": 240, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "matrix-legacy-inventory-files.searchpaths-2", + "checkpoints": [ + { + "id": "b1.prelude:old-pending", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.normal:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "15b2254fad4b"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "3642acfe438f", + "effects": [] + } + }, + { + "id": "b1.normal:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "15b2254fad4b", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.normal:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "15b2254fad4b", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-absent:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1567fc34445b"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-absent:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1567fc34445b", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-absent:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1567fc34445b", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "0959d2b897c9"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "0959d2b897c9", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "0959d2b897c9", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ea7547b81a5"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ea7547b81a5", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ea7547b81a5", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1f232e1642a7"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1f232e1642a7", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1f232e1642a7", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "825b5246a9b0"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "825b5246a9b0", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "825b5246a9b0", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "a4b06271def1"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "a4b06271def1", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "a4b06271def1", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "02a03f44e95f"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "02a03f44e95f", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "02a03f44e95f", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "e0c06b676602"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "e0c06b676602", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "e0c06b676602", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "039d4c02da97"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "039d4c02da97", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "039d4c02da97", "11617076ef90"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "43f19e2e0c70"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-legacy-inventory-fresh-inventory.json b/mobile/rpc-foundation/goldens/matrix-legacy-inventory-fresh-inventory.json new file mode 100644 index 00000000000..39d9f50a31a --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-legacy-inventory-fresh-inventory.json @@ -0,0 +1,828 @@ +{ + "operation": "workspace.file-inventory", + "family": "legacy-inventory", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0d903486cbe8": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 240 + } + }, + "1ba589a74085": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "2837f481a843": { + "name": "files.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "3b6419fbab75": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "$rpc": "undefined" + } + }, + "4c6301522bc0": { + "name": "files.list#2", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "519f35cc355f": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true + } + } + }, + "5d5510c9fa8e": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "602e35a92eec": { + "files": [] + }, + "603254c040fc": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "files": [ + { + "relativePath": "old.ts" + } + ] + } + } + } + }, + "6fcbcfd641a6": { + "name": "files.searchPaths#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"fresh\",\"limit\":16}}" + }, + "7dd55e908e3e": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 240, + "settledAt": 360, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "83cec65a43c1": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 240, + "settledAt": 360, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "94e75c7ab64a": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "9dea95bddfe5": { + "name": "files.searchPaths#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"old\",\"limit\":16}}" + }, + "a129552fdc6e": { + "files": ["third.ts"] + }, + "a697ecf6864e": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-4", + "ok": false + } + } + }, + "b2434f1de9f6": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 120 + } + }, + "b97155d69b76": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "c0821dc354d7": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "d2ad71e601c4": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "$rpc": "undefined" + } + }, + "d704d5a97c9c": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-4", + "ok": false + } + } + }, + "daf226a0261c": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "files": [ + { + "relativePath": "fresh.ts" + }, + { + "relativePath": "third.ts" + } + ] + } + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ed722785cd67": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "f427ba18f654": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-4", + "ok": false + } + } + } + }, + "recording": { + "scenario": "matrix-legacy-inventory-fresh-inventory", + "checkpoints": [ + { + "id": "b1.prelude:old-pending", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.prelude:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.prelude:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.normal:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.result-absent:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "519f35cc355f"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "5d5510c9fa8e"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "b97155d69b76"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "ed722785cd67"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "94e75c7ab64a"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "f427ba18f654"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "a697ecf6864e"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "d704d5a97c9c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "83cec65a43c1"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "7dd55e908e3e"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-legacy-inventory-old-inventory.json b/mobile/rpc-foundation/goldens/matrix-legacy-inventory-old-inventory.json new file mode 100644 index 00000000000..4ac40f4e7b5 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-legacy-inventory-old-inventory.json @@ -0,0 +1,1158 @@ +{ + "operation": "workspace.file-inventory", + "family": "legacy-inventory", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0d903486cbe8": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 240 + } + }, + "0ed49b021fe0": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "1ba589a74085": { + "name": "files.searchPaths#2", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "fresh", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "2837f481a843": { + "name": "files.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "3b6419fbab75": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 240, + "value": { + "$rpc": "undefined" + } + }, + "45b173ed5496": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "4c6301522bc0": { + "name": "files.list#2", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"files.list\",\"params\":{\"worktree\":\"id:A\"}}" + }, + "4cc10442b987": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 120, + "settledAt": 240, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "4ee58046e400": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "54dffc286e10": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "592d6f61414a": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 120, + "settledAt": 240, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "602e35a92eec": { + "files": [] + }, + "603254c040fc": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "files": [ + { + "relativePath": "old.ts" + } + ] + } + } + } + }, + "6fcbcfd641a6": { + "name": "files.searchPaths#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"fresh\",\"limit\":16}}" + }, + "9882a4a07c3d": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "9dea95bddfe5": { + "name": "files.searchPaths#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"files.searchPaths\",\"params\":{\"worktree\":\"id:A\",\"query\":\"old\",\"limit\":16}}" + }, + "a129552fdc6e": { + "files": ["third.ts"] + }, + "ae9e53776360": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "b2434f1de9f6": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 120 + } + }, + "b70578465e9a": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "c0821dc354d7": { + "name": "files.searchPaths#1", + "args": [ + { + "name": "method", + "value": "files.searchPaths" + }, + { + "name": "params", + "value": { + "limit": 16, + "query": "old", + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "d2ad71e601c4": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 120, + "value": { + "$rpc": "undefined" + } + }, + "d9aea3f5d7a5": { + "name": "files.list#1", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 120, + "settledAt": 240, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "daf226a0261c": { + "name": "files.list#2", + "args": [ + { + "name": "method", + "value": "files.list" + }, + { + "name": "params", + "value": { + "worktree": "id:A" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 240, + "settledAt": 360, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "files": [ + { + "relativePath": "fresh.ts" + }, + { + "relativePath": "third.ts" + } + ] + } + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "matrix-legacy-inventory-old-inventory", + "checkpoints": [ + { + "id": "b1.prelude:old-pending", + "observation": { + "sender": ["c0821dc354d7", "b2434f1de9f6"], + "payloads": ["9dea95bddfe5", "2837f481a843"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.normal:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.normal:third-query", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.normal:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "603254c040fc", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.result-absent:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "ae9e53776360", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-absent:third-query", + "observation": { + "sender": ["c0821dc354d7", "ae9e53776360", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-absent:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "ae9e53776360", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.result-null:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "b70578465e9a", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:third-query", + "observation": { + "sender": ["c0821dc354d7", "b70578465e9a", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.result-null:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "b70578465e9a", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "54dffc286e10", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:third-query", + "observation": { + "sender": ["c0821dc354d7", "54dffc286e10", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-ok-missing:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "54dffc286e10", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "45b173ed5496", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:third-query", + "observation": { + "sender": ["c0821dc354d7", "45b173ed5496", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-string-error:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "45b173ed5496", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "0ed49b021fe0", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:third-query", + "observation": { + "sender": ["c0821dc354d7", "0ed49b021fe0", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.inner-false-object-error:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "0ed49b021fe0", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.outer-refused:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "4ee58046e400", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:third-query", + "observation": { + "sender": ["c0821dc354d7", "4ee58046e400", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "4ee58046e400", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "d9aea3f5d7a5", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:third-query", + "observation": { + "sender": ["c0821dc354d7", "d9aea3f5d7a5", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.outer-refused-no-message:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "d9aea3f5d7a5", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.method-not-found:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "9882a4a07c3d", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:third-query", + "observation": { + "sender": ["c0821dc354d7", "9882a4a07c3d", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.method-not-found:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "9882a4a07c3d", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "4cc10442b987", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:third-query", + "observation": { + "sender": ["c0821dc354d7", "4cc10442b987", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "4cc10442b987", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:stale-arrived-fresh-pending", + "observation": { + "sender": ["c0821dc354d7", "592d6f61414a", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:third-query", + "observation": { + "sender": ["c0821dc354d7", "592d6f61414a", "1ba589a74085", "0d903486cbe8"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "602e35a92eec", + "effects": [] + } + }, + { + "id": "b1.transport-rejection-no-message:fresh-arrived", + "observation": { + "sender": ["c0821dc354d7", "592d6f61414a", "1ba589a74085", "daf226a0261c"], + "payloads": ["9dea95bddfe5", "2837f481a843", "6fcbcfd641a6", "4c6301522bc0"], + "settlements": { + "mount": "eb79a9b3682a", + "old": "eb79a9b3682a", + "select-b": "d2ad71e601c4", + "reset-a": "d2ad71e601c4", + "fresh": "d2ad71e601c4", + "third": "3b6419fbab75" + }, + "state": "a129552fdc6e", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-linear-detail-barrier-linear.getissue-1.json b/mobile/rpc-foundation/goldens/matrix-linear-detail-barrier-linear.getissue-1.json new file mode 100644 index 00000000000..cb5e22b1f25 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-linear-detail-barrier-linear.getissue-1.json @@ -0,0 +1,905 @@ +{ + "operation": "linear.issue-detail", + "family": "linear-detail-barrier", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "1696f2f90218": { + "name": "detailError", + "value": "comments transport error" + }, + "1736ff39135a": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "3b01c25bcd45": { + "name": "detailError", + "value": "" + }, + "3cb9a384ce0e": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "4209c465bb82": { + "error": "transport failure", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "42903545f0f8": { + "error": "comments transport error", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "468cc28b676c": { + "name": "detailError", + "value": "transport failure" + }, + "4e7c4654b51d": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "comments transport error", + "isRpcDeliveryUnknown": true + } + } + }, + "51f19b7d1380": { + "error": "", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "5ce7f3fa558f": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "68f4ab6eb5df": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "77d756736896": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "780aaf1d97be": { + "error": "", + "loading": true, + "payload": { + "$rpc": "null" + } + }, + "7d21147e56c1": { + "name": "detailLoading", + "value": true + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "8ec7d930f214": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "91a1c8142e23": { + "name": "detailLoading", + "value": false + }, + "a1504f9a0912": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "a91a12c2af5d": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "description": "recorded", + "id": "issue-1", + "labels": [], + "subIssues": [] + } + } + } + }, + "b15e02226c97": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "bb215a1eb59b": { + "name": "linear.getIssue#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"linear.getIssue\",\"params\":{\"id\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "bc9642565680": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "d5a45b61726a": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "e7f73629d075": { + "name": "linear.issueComments#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.issueComments\",\"params\":{\"issueId\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "fc4ce176400a": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "ff164d27a928": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + } + }, + "recording": { + "scenario": "matrix-linear-detail-barrier-linear.getissue-1", + "checkpoints": [ + { + "id": "b3.prelude:pending", + "observation": { + "sender": ["fc4ce176400a", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.normal:issue-refused-comments-pending", + "observation": { + "sender": ["a91a12c2af5d", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.normal:settled", + "observation": { + "sender": ["a91a12c2af5d", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.result-absent:issue-refused-comments-pending", + "observation": { + "sender": ["77d756736896", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.result-absent:settled", + "observation": { + "sender": ["77d756736896", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.result-null:issue-refused-comments-pending", + "observation": { + "sender": ["68f4ab6eb5df", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.result-null:settled", + "observation": { + "sender": ["68f4ab6eb5df", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.inner-ok-missing:issue-refused-comments-pending", + "observation": { + "sender": ["d5a45b61726a", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.inner-ok-missing:settled", + "observation": { + "sender": ["d5a45b61726a", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.inner-false-string-error:issue-refused-comments-pending", + "observation": { + "sender": ["a1504f9a0912", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.inner-false-string-error:settled", + "observation": { + "sender": ["a1504f9a0912", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.inner-false-object-error:issue-refused-comments-pending", + "observation": { + "sender": ["5ce7f3fa558f", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.inner-false-object-error:settled", + "observation": { + "sender": ["5ce7f3fa558f", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.outer-refused:issue-refused-comments-pending", + "observation": { + "sender": ["ff164d27a928", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.outer-refused:settled", + "observation": { + "sender": ["ff164d27a928", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.outer-refused-no-message:issue-refused-comments-pending", + "observation": { + "sender": ["1736ff39135a", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.outer-refused-no-message:settled", + "observation": { + "sender": ["1736ff39135a", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.method-not-found:issue-refused-comments-pending", + "observation": { + "sender": ["8ec7d930f214", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.method-not-found:settled", + "observation": { + "sender": ["8ec7d930f214", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.transport-rejection:issue-refused-comments-pending", + "observation": { + "sender": ["bc9642565680", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4209c465bb82", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "468cc28b676c", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.transport-rejection:settled", + "observation": { + "sender": ["bc9642565680", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4209c465bb82", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "468cc28b676c", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.transport-rejection-no-message:issue-refused-comments-pending", + "observation": { + "sender": ["b15e02226c97", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "51f19b7d1380", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "3b01c25bcd45", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.transport-rejection-no-message:settled", + "observation": { + "sender": ["b15e02226c97", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "51f19b7d1380", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "3b01c25bcd45", + "91a1c8142e23" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-linear-detail-barrier-linear.issuecomments-1.json b/mobile/rpc-foundation/goldens/matrix-linear-detail-barrier-linear.issuecomments-1.json new file mode 100644 index 00000000000..66b7b237bca --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-linear-detail-barrier-linear.issuecomments-1.json @@ -0,0 +1,773 @@ +{ + "operation": "linear.issue-detail", + "family": "linear-detail-barrier", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "034a83431f03": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "issue refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "16e0cc3237e8": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "3276e1a41446": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "3b01c25bcd45": { + "name": "detailError", + "value": "" + }, + "3bb04fc55c1a": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "3cb9a384ce0e": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "3df3437aa9b4": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "4209c465bb82": { + "error": "transport failure", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "468cc28b676c": { + "name": "detailError", + "value": "transport failure" + }, + "51f19b7d1380": { + "error": "", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "780aaf1d97be": { + "error": "", + "loading": true, + "payload": { + "$rpc": "null" + } + }, + "7d21147e56c1": { + "name": "detailLoading", + "value": true + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "91a1c8142e23": { + "name": "detailLoading", + "value": false + }, + "9f8c9f7294a0": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "a2450a300ddf": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "a4b8ea721dcf": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "comments": [] + } + } + } + }, + "bb215a1eb59b": { + "name": "linear.getIssue#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"linear.getIssue\",\"params\":{\"id\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "c360db88accd": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "c92234b1167b": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "dff907b2355c": { + "error": "issue refused", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "e1a8c572690f": { + "name": "detailError", + "value": "issue refused" + }, + "e7f73629d075": { + "name": "linear.issueComments#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.issueComments\",\"params\":{\"issueId\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ecb0f6b35964": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "f60c595d990e": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "fc4ce176400a": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "matrix-linear-detail-barrier-linear.issuecomments-1", + "checkpoints": [ + { + "id": "b3.prelude:pending", + "observation": { + "sender": ["fc4ce176400a", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.prelude:issue-refused-comments-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.normal:settled", + "observation": { + "sender": ["034a83431f03", "a4b8ea721dcf"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "dff907b2355c", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "e1a8c572690f", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.result-absent:settled", + "observation": { + "sender": ["034a83431f03", "16e0cc3237e8"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "dff907b2355c", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "e1a8c572690f", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.result-null:settled", + "observation": { + "sender": ["034a83431f03", "f60c595d990e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "dff907b2355c", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "e1a8c572690f", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.inner-ok-missing:settled", + "observation": { + "sender": ["034a83431f03", "c360db88accd"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "dff907b2355c", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "e1a8c572690f", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.inner-false-string-error:settled", + "observation": { + "sender": ["034a83431f03", "c92234b1167b"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "dff907b2355c", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "e1a8c572690f", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.inner-false-object-error:settled", + "observation": { + "sender": ["034a83431f03", "3276e1a41446"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "dff907b2355c", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "e1a8c572690f", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.outer-refused:settled", + "observation": { + "sender": ["034a83431f03", "a2450a300ddf"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "dff907b2355c", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "e1a8c572690f", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.outer-refused-no-message:settled", + "observation": { + "sender": ["034a83431f03", "9f8c9f7294a0"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "dff907b2355c", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "e1a8c572690f", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.method-not-found:settled", + "observation": { + "sender": ["034a83431f03", "3bb04fc55c1a"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "dff907b2355c", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "e1a8c572690f", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.transport-rejection:settled", + "observation": { + "sender": ["034a83431f03", "ecb0f6b35964"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4209c465bb82", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "468cc28b676c", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.transport-rejection-no-message:settled", + "observation": { + "sender": ["034a83431f03", "3df3437aa9b4"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "51f19b7d1380", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "3b01c25bcd45", + "91a1c8142e23" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-project-explicit-false-github.project.updateissuebyslug-1.json b/mobile/rpc-foundation/goldens/matrix-project-explicit-false-github.project.updateissuebyslug-1.json new file mode 100644 index 00000000000..c51d82d7bb4 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-project-explicit-false-github.project.updateissuebyslug-1.json @@ -0,0 +1,949 @@ +{ + "operation": "project.update-metadata", + "family": "project-explicit-false", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "057a0b5a420b": { + "name": "projectRowDetailError", + "value": "" + }, + "064bc8399cbc": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "0924615699bf": { + "name": "projectRowDetailError", + "value": "transport failure" + }, + "0c4dced3e005": { + "error": "", + "mutating": true, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "1ddee45b4bc3": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "204a5c5728c2": { + "error": "Cannot read properties of null (reading 'ok')", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "22021a77bba3": { + "error": "Unknown method", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "27f506c59cc7": { + "name": "projectRowDetailError", + "value": "outer refused" + }, + "29f9b15bed7a": { + "error": "Cannot read properties of undefined (reading 'ok')", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "2b3c1b95331e": { + "error": "outer refused", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "2cd14f7121a5": { + "name": "projectMutating", + "value": false + }, + "2e2da1bbd7ed": { + "name": "projectRowDetailError", + "value": "Cannot read properties of undefined (reading 'ok')" + }, + "32cc1f3ceec8": { + "error": "inner refused", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "37124163eb76": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "3f996c0d0403": { + "error": "", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "52a7a7239fbb": { + "name": "github.project.updateIssueBySlug#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"github.project.updateIssueBySlug\",\"params\":{\"owner\":\"owner\",\"repo\":\"repo\",\"host\":\"github.enterprise.test\",\"number\":1,\"updates\":{\"addLabels\":[\"recorded\"]}}}" + }, + "538107aee28b": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "5ea692508d69": { + "error": "transport failure", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "5f998cf9a955": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "6b5f90ac558c": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "6b6431f01d00": { + "name": "projectRowDetailError", + "value": "Unknown method" + }, + "6f0142de3930": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "6fe1c7d73e4d": { + "name": "projectRowDetailError", + "value": "inner refused" + }, + "7a55b2ec205b": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "7df10429e862": { + "error": "", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [ + { + "color": "808080", + "name": "recorded" + } + ], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "90cf28d0b84a": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "c1213bb55edc": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + }, + "c2a271fc5d97": { + "name": "projectMutating", + "value": true + }, + "c679565dc881": { + "error": "Failed to update GitHub item", + "mutating": false, + "row": { + "content": { + "assignees": [], + "labels": [], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "cb9738a42f12": { + "name": "projectRowItem", + "value": { + "content": { + "assignees": [], + "labels": [ + { + "color": "808080", + "name": "recorded" + } + ], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + }, + "cbdef49cc723": { + "name": "projectRowDetailError", + "value": "Failed to update GitHub item" + }, + "d330309fabb3": { + "name": "projectRowDetailError", + "value": "Cannot read properties of null (reading 'ok')" + }, + "e5673036d45e": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f12e58847110": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "f6a325457a33": { + "name": "github.project.updateIssueBySlug#1", + "args": [ + { + "name": "method", + "value": "github.project.updateIssueBySlug" + }, + { + "name": "params", + "value": { + "host": "github.enterprise.test", + "number": 1, + "owner": "owner", + "repo": "repo", + "updates": { + "addLabels": ["recorded"] + } + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "f871d643501c": { + "name": "projectRowDetailError", + "value": "Connection closed" + }, + "fa333bb6724e": { + "name": "githubProjectTable", + "value": { + "rows": [ + { + "content": { + "assignees": [], + "labels": [ + { + "color": "808080", + "name": "recorded" + } + ], + "number": 1, + "repository": "owner/repo" + }, + "id": "item-1", + "itemType": "ISSUE" + } + ] + } + } + }, + "recording": { + "scenario": "matrix-project-explicit-false-github.project.updateissuebyslug-1", + "checkpoints": [ + { + "id": "b2.prelude:pending", + "observation": { + "sender": ["e5673036d45e"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "0c4dced3e005", + "effects": ["c2a271fc5d97"] + } + }, + { + "id": "b2.prelude:cleanup", + "observation": { + "sender": ["c1213bb55edc"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "0c4dced3e005", + "effects": ["c2a271fc5d97", "f871d643501c", "2cd14f7121a5"] + } + }, + { + "id": "b2.normal:settled", + "observation": { + "sender": ["f6a325457a33"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "7df10429e862", + "effects": [ + "c2a271fc5d97", + "cb9738a42f12", + "fa333bb6724e", + "347cc433c473", + "2cd14f7121a5" + ] + } + }, + { + "id": "b2.result-absent:settled", + "observation": { + "sender": ["1ddee45b4bc3"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "29f9b15bed7a", + "effects": ["c2a271fc5d97", "2e2da1bbd7ed", "2cd14f7121a5"] + } + }, + { + "id": "b2.result-null:settled", + "observation": { + "sender": ["6f0142de3930"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "204a5c5728c2", + "effects": ["c2a271fc5d97", "d330309fabb3", "2cd14f7121a5"] + } + }, + { + "id": "b2.inner-ok-missing:settled", + "observation": { + "sender": ["7a55b2ec205b"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "7df10429e862", + "effects": [ + "c2a271fc5d97", + "cb9738a42f12", + "fa333bb6724e", + "347cc433c473", + "2cd14f7121a5" + ] + } + }, + { + "id": "b2.inner-false-string-error:settled", + "observation": { + "sender": ["90cf28d0b84a"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "c679565dc881", + "effects": ["c2a271fc5d97", "cbdef49cc723", "2cd14f7121a5"] + } + }, + { + "id": "b2.inner-false-object-error:settled", + "observation": { + "sender": ["6b5f90ac558c"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "32cc1f3ceec8", + "effects": ["c2a271fc5d97", "6fe1c7d73e4d", "2cd14f7121a5"] + } + }, + { + "id": "b2.outer-refused:settled", + "observation": { + "sender": ["f12e58847110"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2b3c1b95331e", + "effects": ["c2a271fc5d97", "27f506c59cc7", "2cd14f7121a5"] + } + }, + { + "id": "b2.outer-refused-no-message:settled", + "observation": { + "sender": ["5f998cf9a955"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "3f996c0d0403", + "effects": ["c2a271fc5d97", "057a0b5a420b", "2cd14f7121a5"] + } + }, + { + "id": "b2.method-not-found:settled", + "observation": { + "sender": ["064bc8399cbc"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "22021a77bba3", + "effects": ["c2a271fc5d97", "6b6431f01d00", "2cd14f7121a5"] + } + }, + { + "id": "b2.transport-rejection:settled", + "observation": { + "sender": ["538107aee28b"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "5ea692508d69", + "effects": ["c2a271fc5d97", "0924615699bf", "2cd14f7121a5"] + } + }, + { + "id": "b2.transport-rejection-no-message:settled", + "observation": { + "sender": ["37124163eb76"], + "payloads": ["52a7a7239fbb"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "3f996c0d0403", + "effects": ["c2a271fc5d97", "057a0b5a420b", "2cd14f7121a5"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-session.tab-reveal-session.tabs.activate-1.json b/mobile/rpc-foundation/goldens/matrix-session.tab-reveal-session.tabs.activate-1.json new file mode 100644 index 00000000000..da5847f5874 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-session.tab-reveal-session.tabs.activate-1.json @@ -0,0 +1,712 @@ +{ + "operation": "source-control.session-diff-reveal", + "family": "session.tab-reveal", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0f9f4df04699": { + "name": "session.tabs.activate#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.activate\",\"params\":{\"worktree\":\"id:repo42::/p\",\"tabId\":\"tab-1\",\"notifyClients\":false,\"navigation\":\"caller\",\"intent\":\"user\"}}" + }, + "2384a82b2f68": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "33ae0e26bf62": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "35ed60d6e127": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "4c133e67c92a": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "5fbe284a7387": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "60ef11dd407d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": "revealed" + }, + "77bd8427d179": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "92b5192ed75d": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "tabs": [ + { + "id": "tab-term", + "type": "terminal" + }, + { + "id": "tab-other", + "mode": "diff", + "relativePath": "src/other.ts", + "type": "file" + }, + { + "diffSource": "unstaged", + "id": "tab-1", + "mode": "diff", + "relativePath": "src/app.ts", + "type": "file" + } + ] + } + } + } + }, + "bb3b4ee6b927": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "activeTabId": "tab-1" + } + } + } + }, + "bde782b3557a": { + "result": "revealed" + }, + "c7a157cde28d": { + "result": "unrevealed" + }, + "d23ecdfde21c": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "d9fa0bff7ae7": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "e0a0bb81e43c": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "ea1d154a9fcf": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "eb116b4d99bb": { + "name": "session.tabs.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.list\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "f2afcb7dd64d": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "f884811cfa05": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "matrix-session.tab-reveal-session.tabs.activate-1", + "checkpoints": [ + { + "id": "sc-reveal-first-poll.prelude:list-pending", + "observation": { + "sender": ["f884811cfa05"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.prelude:activate-pending", + "observation": { + "sender": ["92b5192ed75d", "5fbe284a7387"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.normal:settled", + "observation": { + "sender": ["92b5192ed75d", "bb3b4ee6b927"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "60ef11dd407d" + }, + "state": "bde782b3557a", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.result-absent:settled", + "observation": { + "sender": ["92b5192ed75d", "2384a82b2f68"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.result-null:settled", + "observation": { + "sender": ["92b5192ed75d", "77bd8427d179"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.inner-ok-missing:settled", + "observation": { + "sender": ["92b5192ed75d", "d23ecdfde21c"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.inner-false-string-error:settled", + "observation": { + "sender": ["92b5192ed75d", "d9fa0bff7ae7"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.inner-false-object-error:settled", + "observation": { + "sender": ["92b5192ed75d", "35ed60d6e127"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.outer-refused:settled", + "observation": { + "sender": ["92b5192ed75d", "ea1d154a9fcf"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.outer-refused-no-message:settled", + "observation": { + "sender": ["92b5192ed75d", "f2afcb7dd64d"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.method-not-found:settled", + "observation": { + "sender": ["92b5192ed75d", "4c133e67c92a"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.transport-rejection:settled", + "observation": { + "sender": ["92b5192ed75d", "e0a0bb81e43c"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.transport-rejection-no-message:settled", + "observation": { + "sender": ["92b5192ed75d", "33ae0e26bf62"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-session.tab-reveal-session.tabs.list-1.json b/mobile/rpc-foundation/goldens/matrix-session.tab-reveal-session.tabs.list-1.json new file mode 100644 index 00000000000..bf2bf6082aa --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-session.tab-reveal-session.tabs.list-1.json @@ -0,0 +1,792 @@ +{ + "operation": "source-control.session-diff-reveal", + "family": "session.tab-reveal", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0f9f4df04699": { + "name": "session.tabs.activate#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.activate\",\"params\":{\"worktree\":\"id:repo42::/p\",\"tabId\":\"tab-1\",\"notifyClients\":false,\"navigation\":\"caller\",\"intent\":\"user\"}}" + }, + "12380cd54c7c": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "4fe73924ca34": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "5fbe284a7387": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "60ef11dd407d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": "revealed" + }, + "63a99e79af5b": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "661ed2754e93": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "7eb00dad4d0d": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "92b5192ed75d": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "tabs": [ + { + "id": "tab-term", + "type": "terminal" + }, + { + "id": "tab-other", + "mode": "diff", + "relativePath": "src/other.ts", + "type": "file" + }, + { + "diffSource": "unstaged", + "id": "tab-1", + "mode": "diff", + "relativePath": "src/app.ts", + "type": "file" + } + ] + } + } + } + }, + "94db2ba485c5": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "b5a14b5bcd38": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "bb3b4ee6b927": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "activeTabId": "tab-1" + } + } + } + }, + "bde782b3557a": { + "result": "revealed" + }, + "c3ee87ce1af9": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "c7a157cde28d": { + "result": "unrevealed" + }, + "c7d63e6d1ae1": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "eb116b4d99bb": { + "name": "session.tabs.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.list\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "f0e11346d0fc": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "f884811cfa05": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "matrix-session.tab-reveal-session.tabs.list-1", + "checkpoints": [ + { + "id": "sc-reveal-first-poll.prelude:list-pending", + "observation": { + "sender": ["f884811cfa05"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.normal:activate-pending", + "observation": { + "sender": ["92b5192ed75d", "5fbe284a7387"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.normal:settled", + "observation": { + "sender": ["92b5192ed75d", "bb3b4ee6b927"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "60ef11dd407d" + }, + "state": "bde782b3557a", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.result-absent:activate-pending", + "observation": { + "sender": ["94db2ba485c5"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.result-absent:settled", + "observation": { + "sender": ["94db2ba485c5"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.result-null:activate-pending", + "observation": { + "sender": ["7eb00dad4d0d"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.result-null:settled", + "observation": { + "sender": ["7eb00dad4d0d"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.inner-ok-missing:activate-pending", + "observation": { + "sender": ["c3ee87ce1af9"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.inner-ok-missing:settled", + "observation": { + "sender": ["c3ee87ce1af9"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.inner-false-string-error:activate-pending", + "observation": { + "sender": ["f0e11346d0fc"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.inner-false-string-error:settled", + "observation": { + "sender": ["f0e11346d0fc"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.inner-false-object-error:activate-pending", + "observation": { + "sender": ["12380cd54c7c"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.inner-false-object-error:settled", + "observation": { + "sender": ["12380cd54c7c"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.outer-refused:activate-pending", + "observation": { + "sender": ["661ed2754e93"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.outer-refused:settled", + "observation": { + "sender": ["661ed2754e93"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.outer-refused-no-message:activate-pending", + "observation": { + "sender": ["c7d63e6d1ae1"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.outer-refused-no-message:settled", + "observation": { + "sender": ["c7d63e6d1ae1"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.method-not-found:activate-pending", + "observation": { + "sender": ["b5a14b5bcd38"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.method-not-found:settled", + "observation": { + "sender": ["b5a14b5bcd38"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.transport-rejection:activate-pending", + "observation": { + "sender": ["4fe73924ca34"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.transport-rejection:settled", + "observation": { + "sender": ["4fe73924ca34"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.transport-rejection-no-message:activate-pending", + "observation": { + "sender": ["63a99e79af5b"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "sc-reveal-first-poll.transport-rejection-no-message:settled", + "observation": { + "sender": ["63a99e79af5b"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings-agent-read-preflight.detectremoteagents-1.json b/mobile/rpc-foundation/goldens/matrix-settings-agent-read-preflight.detectremoteagents-1.json new file mode 100644 index 00000000000..cdc97e82af9 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings-agent-read-preflight.detectremoteagents-1.json @@ -0,0 +1,747 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "07d4c9b0eaf2": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fc9b6295af5": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "25716369cd8f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": [] + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2f067ba3a711": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "32a7c0ae7918": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "outer refused", + "isRpcDeliveryUnknown": false + } + }, + "3cc72974b9bb": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "44136fa355b3": {}, + "4ed35c961a4b": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "554718767f5a": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": [] + } + } + } + } + }, + "5651342f395d": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "detectedAgents is not iterable", + "isRpcDeliveryUnknown": false + } + }, + "63c912abe2bc": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "6fe734ca80ae": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "95dee1165f95": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "9c4be43625f0": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": ["codex", "claude"] + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "b27c85677730": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": [ + { + "agent": "codex", + "label": "Codex" + }, + { + "agent": "claude", + "label": "Claude" + } + ] + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "b948e8307e81": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Unknown method", + "isRpcDeliveryUnknown": false + } + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "c2a61640d827": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "d32b9c7891a0": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f3b516f62081": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": false + } + } + }, + "recording": { + "scenario": "matrix-settings-agent-read-preflight.detectremoteagents-1", + "checkpoints": [ + { + "id": "settings-new-tab-ssh.prelude:pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.normal:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b27c85677730" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.result-absent:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "4ed35c961a4b"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "25716369cd8f" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.result-null:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "6fe734ca80ae"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "25716369cd8f" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.inner-ok-missing:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "0fc9b6295af5"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "5651342f395d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.inner-false-string-error:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "2f067ba3a711"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "5651342f395d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.inner-false-object-error:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "63c912abe2bc"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "5651342f395d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.outer-refused:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "d32b9c7891a0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "32a7c0ae7918" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.outer-refused-no-message:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "3cc72974b9bb"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "f3b516f62081" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.method-not-found:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "c2a61640d827"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b948e8307e81" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.transport-rejection:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "07d4c9b0eaf2"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "a947768bc0ed" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.transport-rejection-no-message:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "95dee1165f95"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "c7584e82c72f" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings-agent-read-repo.list-1.json b/mobile/rpc-foundation/goldens/matrix-settings-agent-read-repo.list-1.json new file mode 100644 index 00000000000..0a187865dc5 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings-agent-read-repo.list-1.json @@ -0,0 +1,761 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "06b63e0d9986": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "06fc8e7b85d5": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2381a3fe154e": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "Cannot read properties of undefined (reading 'repos')", + "isRpcDeliveryUnknown": false + } + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2ebe4d776f9b": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "32a7c0ae7918": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "outer refused", + "isRpcDeliveryUnknown": false + } + }, + "37a374f87be0": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "worktree_repo_not_found", + "isRpcDeliveryUnknown": false + } + }, + "38e790fd9e9c": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "44136fa355b3": {}, + "554718767f5a": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": [] + } + } + } + } + }, + "63dfbb6942f2": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "Cannot read properties of null (reading 'repos')", + "isRpcDeliveryUnknown": false + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "6e5c6593dad8": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9c4be43625f0": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": ["codex", "claude"] + } + } + }, + "9d3fa0db2665": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "b27c85677730": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": [ + { + "agent": "codex", + "label": "Codex" + }, + { + "agent": "claude", + "label": "Claude" + } + ] + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "b948e8307e81": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Unknown method", + "isRpcDeliveryUnknown": false + } + }, + "b9f0f1e94cd9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "cc1facdf008c": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "e341bd05e614": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f3b516f62081": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": false + } + }, + "f96e83d33565": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings-agent-read-repo.list-1", + "checkpoints": [ + { + "id": "settings-new-tab-ssh.prelude:pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.normal:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b27c85677730" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.result-absent:settled", + "observation": { + "sender": ["2ebe4d776f9b", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "2381a3fe154e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.result-null:settled", + "observation": { + "sender": ["38e790fd9e9c", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "63dfbb6942f2" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.inner-ok-missing:settled", + "observation": { + "sender": ["06b63e0d9986", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "37a374f87be0" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.inner-false-string-error:settled", + "observation": { + "sender": ["f96e83d33565", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "37a374f87be0" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.inner-false-object-error:settled", + "observation": { + "sender": ["9d3fa0db2665", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "37a374f87be0" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.outer-refused:settled", + "observation": { + "sender": ["b9f0f1e94cd9", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "32a7c0ae7918" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.outer-refused-no-message:settled", + "observation": { + "sender": ["06fc8e7b85d5", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "f3b516f62081" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.method-not-found:settled", + "observation": { + "sender": ["e341bd05e614", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "b948e8307e81" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.transport-rejection:settled", + "observation": { + "sender": ["6e5c6593dad8", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "a947768bc0ed" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.transport-rejection-no-message:settled", + "observation": { + "sender": ["cc1facdf008c", "554718767f5a"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "c7584e82c72f" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings-agent-read-settings.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings-agent-read-settings.get-1.json new file mode 100644 index 00000000000..effd65b83a9 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings-agent-read-settings.get-1.json @@ -0,0 +1,766 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "1a04332d2ee1": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "Cannot read properties of null (reading 'settings')", + "isRpcDeliveryUnknown": false + } + }, + "1c10eabc36a4": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "Cannot read properties of undefined (reading 'settings')", + "isRpcDeliveryUnknown": false + } + }, + "1e7f0f9265cc": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2ae8bb906793": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "2b3aa0da0852": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "32a7c0ae7918": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "outer refused", + "isRpcDeliveryUnknown": false + } + }, + "35584987e88e": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "3c911d72c9be": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": [ + { + "agent": "claude", + "label": "Claude" + }, + { + "agent": "codex", + "label": "Codex" + } + ] + }, + "44136fa355b3": {}, + "554718767f5a": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": [] + } + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "6d584492e802": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "72d637915e56": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "8b77098df0c3": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "8bbc0944abe9": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "924e33dd1165": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9c4be43625f0": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": ["codex", "claude"] + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "b27c85677730": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": [ + { + "agent": "codex", + "label": "Codex" + }, + { + "agent": "claude", + "label": "Claude" + } + ] + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "b948e8307e81": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Unknown method", + "isRpcDeliveryUnknown": false + } + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "ed866f202034": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "f3b516f62081": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": false + } + } + }, + "recording": { + "scenario": "matrix-settings-agent-read-settings.get-1", + "checkpoints": [ + { + "id": "settings-new-tab-ssh.prelude:pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.normal:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b27c85677730" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.result-absent:settled", + "observation": { + "sender": ["bae1ab4f96f9", "ed866f202034", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "1c10eabc36a4" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.result-null:settled", + "observation": { + "sender": ["bae1ab4f96f9", "924e33dd1165", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "1a04332d2ee1" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.inner-ok-missing:settled", + "observation": { + "sender": ["bae1ab4f96f9", "35584987e88e", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "3c911d72c9be" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.inner-false-string-error:settled", + "observation": { + "sender": ["bae1ab4f96f9", "1e7f0f9265cc", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "3c911d72c9be" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.inner-false-object-error:settled", + "observation": { + "sender": ["bae1ab4f96f9", "8bbc0944abe9", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "3c911d72c9be" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.outer-refused:settled", + "observation": { + "sender": ["bae1ab4f96f9", "72d637915e56", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "32a7c0ae7918" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.outer-refused-no-message:settled", + "observation": { + "sender": ["bae1ab4f96f9", "6d584492e802", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "f3b516f62081" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.method-not-found:settled", + "observation": { + "sender": ["bae1ab4f96f9", "2ae8bb906793", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b948e8307e81" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.transport-rejection:settled", + "observation": { + "sender": ["bae1ab4f96f9", "8b77098df0c3", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "a947768bc0ed" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.transport-rejection-no-message:settled", + "observation": { + "sender": ["bae1ab4f96f9", "2b3aa0da0852", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "c7584e82c72f" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings-best-effort-settings.update-1.json b/mobile/rpc-foundation/goldens/matrix-settings-best-effort-settings.update-1.json new file mode 100644 index 00000000000..9197c37cd94 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings-best-effort-settings.update-1.json @@ -0,0 +1,583 @@ +{ + "operation": "settings.task-preferences", + "family": "settings-best-effort", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "178d4ef77ad7": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "1ba7a60a2f98": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "2369258c9999": { + "name": "settings.update#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.update\",\"params\":{\"defaultTaskViewPreset\":\"assigned\"}}" + }, + "2b21a178e827": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "5b0cac0bdf84": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "5db909d58c6f": { + "preset": "assigned" + }, + "71459ddb091d": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "71615e0dba6b": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "74827568abb0": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "79d43c68f387": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "9b81c7f38dcf": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "a90dfad3297a": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "b2897d5daa49": { + "name": "defaultGitHubPreset", + "value": "assigned" + }, + "d26aa345f588": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f9d1c4554592": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + } + }, + "recording": { + "scenario": "matrix-settings-best-effort-settings.update-1", + "checkpoints": [ + { + "id": "settings-task-write.prelude:optimistic", + "observation": { + "sender": ["74827568abb0"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.normal:settled", + "observation": { + "sender": ["5b0cac0bdf84"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.result-absent:settled", + "observation": { + "sender": ["79d43c68f387"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.result-null:settled", + "observation": { + "sender": ["71615e0dba6b"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.inner-ok-missing:settled", + "observation": { + "sender": ["a90dfad3297a"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.inner-false-string-error:settled", + "observation": { + "sender": ["71459ddb091d"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.inner-false-object-error:settled", + "observation": { + "sender": ["2b21a178e827"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.outer-refused:settled", + "observation": { + "sender": ["1ba7a60a2f98"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.outer-refused-no-message:settled", + "observation": { + "sender": ["9b81c7f38dcf"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.method-not-found:settled", + "observation": { + "sender": ["f9d1c4554592"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.transport-rejection:settled", + "observation": { + "sender": ["178d4ef77ad7"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settings-task-write.transport-rejection-no-message:settled", + "observation": { + "sender": ["d26aa345f588"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.bot-overrides-settings.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.bot-overrides-settings.get-1.json new file mode 100644 index 00000000000..d6076f02626 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.bot-overrides-settings.get-1.json @@ -0,0 +1,572 @@ +{ + "operation": "settings.bot-overrides", + "family": "settings.bot-overrides", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fc3e204e7ba": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "127ad2bdc042": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "2b3aa0da0852": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "4f53cda18c2b": [], + "6a98511b6371": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "7ca23c4c946b": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "8b77098df0c3": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "8f8296303a77": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "b759ab27e4dd": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "d27ce798af34": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "d52c8e96e222": ["bot-user"], + "e0cf1af55a54": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "e1bd8b4a5d70": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "matrix-settings.bot-overrides-settings.get-1", + "checkpoints": [ + { + "id": "settings-bot-overrides-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.normal:settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.result-absent:settled", + "observation": { + "sender": ["e0cf1af55a54"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.result-null:settled", + "observation": { + "sender": ["e1bd8b4a5d70"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["0fc3e204e7ba"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["d27ce798af34"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["127ad2bdc042"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.outer-refused:settled", + "observation": { + "sender": ["8f8296303a77"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["6a98511b6371"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.method-not-found:settled", + "observation": { + "sender": ["b759ab27e4dd"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["8b77098df0c3"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settings-bot-overrides-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["2b3aa0da0852"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.home-providers-linear.status-1.json b/mobile/rpc-foundation/goldens/matrix-settings.home-providers-linear.status-1.json new file mode 100644 index 00000000000..7e85d9235b2 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.home-providers-linear.status-1.json @@ -0,0 +1,706 @@ +{ + "operation": "settings.home-providers", + "family": "settings.home-providers", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0e7c79cad23f": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "24054d93a95f": { + "name": "providers", + "value": { + "host-1": ["github"] + } + }, + "27e92f99be15": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "2c906720f812": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "349f2cb31004": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "34aa2df10382": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "42701bb4f394": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "44136fa355b3": {}, + "49ba5f0a06c8": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "569aea0064f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "59c1e048ffc5": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "66bc794cca63": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "79b8c1b0d1d1": { + "host-1": ["github"] + }, + "7aa41c1293ae": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "7dadf370725c": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "8f4c679a09be": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "a3c30fa6fdda": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "ab4cddba914f": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "ad11a8182697": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "da2c3b49481f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ed179042b8c8": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.home-providers-linear.status-1", + "checkpoints": [ + { + "id": "settings-home-providers-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["da2c3b49481f", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-home-providers-fulfilled.normal:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.result-absent:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "8f4c679a09be"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.result-null:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "ab4cddba914f"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "59c1e048ffc5"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "ed179042b8c8"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "ad11a8182697"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.outer-refused:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "34aa2df10382"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "0e7c79cad23f"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.method-not-found:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "2c906720f812"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "49ba5f0a06c8"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "7aa41c1293ae"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.home-providers-preflight.check-1.json b/mobile/rpc-foundation/goldens/matrix-settings.home-providers-preflight.check-1.json new file mode 100644 index 00000000000..e6cfe226ed1 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.home-providers-preflight.check-1.json @@ -0,0 +1,706 @@ +{ + "operation": "settings.home-providers", + "family": "settings.home-providers", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0dcc6f40d62e": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "24054d93a95f": { + "name": "providers", + "value": { + "host-1": ["github"] + } + }, + "27e92f99be15": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "349f2cb31004": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "38ac58305f52": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "42701bb4f394": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "44136fa355b3": {}, + "569aea0064f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "66bc794cca63": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "74ecdd98d1e6": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "753d9a4acc88": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "79b8c1b0d1d1": { + "host-1": ["github"] + }, + "7dadf370725c": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "a3c30fa6fdda": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "c54f9d6cd594": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "d6cbbd40a61d": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "da2c3b49481f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e2d1516ff734": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "eb54685d6e7e": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f351709792d2": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "fb840c0b39e9": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + } + }, + "recording": { + "scenario": "matrix-settings.home-providers-preflight.check-1", + "checkpoints": [ + { + "id": "settings-home-providers-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["da2c3b49481f", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-home-providers-fulfilled.normal:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.result-absent:settled", + "observation": { + "sender": ["7dadf370725c", "fb840c0b39e9", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.result-null:settled", + "observation": { + "sender": ["7dadf370725c", "f351709792d2", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["7dadf370725c", "0dcc6f40d62e", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["7dadf370725c", "74ecdd98d1e6", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["7dadf370725c", "e2d1516ff734", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.outer-refused:settled", + "observation": { + "sender": ["7dadf370725c", "c54f9d6cd594", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["7dadf370725c", "38ac58305f52", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.method-not-found:settled", + "observation": { + "sender": ["7dadf370725c", "d6cbbd40a61d", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["7dadf370725c", "eb54685d6e7e", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["7dadf370725c", "753d9a4acc88", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.home-providers-settings.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.home-providers-settings.get-1.json new file mode 100644 index 00000000000..33f572a839d --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.home-providers-settings.get-1.json @@ -0,0 +1,706 @@ +{ + "operation": "settings.home-providers", + "family": "settings.home-providers", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090d7111bcf7": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "24054d93a95f": { + "name": "providers", + "value": { + "host-1": ["github"] + } + }, + "272a1c90c400": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "27e92f99be15": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "31bffe41a47f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "349f2cb31004": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "3870e54005de": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "3c9d36434dd9": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "40b5654c1d45": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "42701bb4f394": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "44136fa355b3": {}, + "569aea0064f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6493002b4410": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "66bc794cca63": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "68046551307c": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "79b8c1b0d1d1": { + "host-1": ["github"] + }, + "7dadf370725c": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "a3c30fa6fdda": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "c14c60dab8a3": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "d08bd2846cf7": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "da2c3b49481f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "matrix-settings.home-providers-settings.get-1", + "checkpoints": [ + { + "id": "settings-home-providers-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["da2c3b49481f", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-home-providers-fulfilled.normal:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.result-absent:settled", + "observation": { + "sender": ["d08bd2846cf7", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.result-null:settled", + "observation": { + "sender": ["40b5654c1d45", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["272a1c90c400", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["6493002b4410", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["c14c60dab8a3", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.outer-refused:settled", + "observation": { + "sender": ["090d7111bcf7", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["31bffe41a47f", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.method-not-found:settled", + "observation": { + "sender": ["3870e54005de", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["3c9d36434dd9", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["68046551307c", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-host.platform-1.json b/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-host.platform-1.json new file mode 100644 index 00000000000..c186d6125e7 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-host.platform-1.json @@ -0,0 +1,958 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fdf9f35751e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "186c2437de25": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "1de50f3b4aac": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": { + "$rpc": "null" + }, + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4bec80c16f02": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "4bf86567ed13": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-4", + "ok": false + } + } + }, + "4fa7f6058fbd": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7ddd37ed8da5": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "83f3f1b40ac7": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-4", + "ok": false + } + } + }, + "8400cb9da553": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9acf4d7a0ba1": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a6443e8b2129": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "c20cbed07b1d": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-4", + "ok": false + } + } + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "e24ce14b72e9": { + "name": "hostPlatform", + "value": { + "$rpc": "null" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.repo-metadata-host.platform-1", + "checkpoints": [ + { + "id": "settings-repo-metadata-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.prelude:cleanup", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "9acf4d7a0ba1"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "6134b73f18d0", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.normal:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-absent:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "8400cb9da553"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-null:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "a6443e8b2129"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "186c2437de25"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "0fdf9f35751e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7ddd37ed8da5"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "c20cbed07b1d"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "83f3f1b40ac7"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.method-not-found:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "4bf86567ed13"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "4fa7f6058fbd"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "4bec80c16f02"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-repo.list-1.json b/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-repo.list-1.json new file mode 100644 index 00000000000..8dfd2f51d2d --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-repo.list-1.json @@ -0,0 +1,943 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "06b63e0d9986": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "06fc8e7b85d5": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "2ebe4d776f9b": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "38e790fd9e9c": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "44136fa355b3": {}, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "6e5c6593dad8": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9d3fa0db2665": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "b9f0f1e94cd9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "cc1facdf008c": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "e341bd05e614": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + }, + "f96e83d33565": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.repo-metadata-repo.list-1", + "checkpoints": [ + { + "id": "settings-repo-metadata-fulfilled.normal:settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.normal:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-absent:settings-pending", + "observation": { + "sender": ["2ebe4d776f9b"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-absent:settled", + "observation": { + "sender": ["2ebe4d776f9b"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-null:settings-pending", + "observation": { + "sender": ["38e790fd9e9c"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-null:settled", + "observation": { + "sender": ["38e790fd9e9c"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-ok-missing:settings-pending", + "observation": { + "sender": ["06b63e0d9986"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["06b63e0d9986"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-string-error:settings-pending", + "observation": { + "sender": ["f96e83d33565"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["f96e83d33565"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-object-error:settings-pending", + "observation": { + "sender": ["9d3fa0db2665"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["9d3fa0db2665"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused:settings-pending", + "observation": { + "sender": ["b9f0f1e94cd9"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused:settled", + "observation": { + "sender": ["b9f0f1e94cd9"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused-no-message:settings-pending", + "observation": { + "sender": ["06fc8e7b85d5"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["06fc8e7b85d5"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.method-not-found:settings-pending", + "observation": { + "sender": ["e341bd05e614"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.method-not-found:settled", + "observation": { + "sender": ["e341bd05e614"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection:settings-pending", + "observation": { + "sender": ["6e5c6593dad8"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["6e5c6593dad8"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection-no-message:settings-pending", + "observation": { + "sender": ["cc1facdf008c"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["cc1facdf008c"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-settings.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-settings.get-1.json new file mode 100644 index 00000000000..4bce7998ce5 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-settings.get-1.json @@ -0,0 +1,970 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "099b501d90c2": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "0c433d37dba9": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "2b3aa0da0852": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "329ace7b96e9": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "4043cd1b2634": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "8b77098df0c3": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9582447b1277": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "9a2df19b1d5f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "9acf4d7a0ba1": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d3eea0a00315": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "e24ce14b72e9": { + "name": "hostPlatform", + "value": { + "$rpc": "null" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + }, + "f84a8688af61": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + }, + "ff34527b3e2e": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.repo-metadata-settings.get-1", + "checkpoints": [ + { + "id": "settings-repo-metadata-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.prelude:cleanup", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "f84a8688af61", "9acf4d7a0ba1"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "6134b73f18d0", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.normal:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-absent:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "329ace7b96e9", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-null:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "9582447b1277", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "ff34527b3e2e", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "4043cd1b2634", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "099b501d90c2", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "0c433d37dba9", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "9a2df19b1d5f", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.method-not-found:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "d3eea0a00315", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "8b77098df0c3", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "2b3aa0da0852", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-ssh.listtargetsummaries-1.json b/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-ssh.listtargetsummaries-1.json new file mode 100644 index 00000000000..89915146449 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-ssh.listtargetsummaries-1.json @@ -0,0 +1,1033 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "153aad174580": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "205d78f95e06": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "5fd9a3414746": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "700210d17d9e": { + "name": "hostLabelById", + "value": [] + }, + "70f9ee89a1da": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "900068047f8a": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9fdaf48cf9b6": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "cb88e4c74a37": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d589c372905b": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "dcd949b896ed": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "eb68427ac627": { + "hostLabelById": [], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + }, + "f7da3ff7d52e": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + } + }, + "recording": { + "scenario": "matrix-settings.repo-metadata-ssh.listtargetsummaries-1", + "checkpoints": [ + { + "id": "settings-repo-metadata-fulfilled.normal:settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.normal:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-absent:settings-pending", + "observation": { + "sender": ["b40605df86b7", "70f9ee89a1da", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-absent:settled", + "observation": { + "sender": ["b40605df86b7", "70f9ee89a1da", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-null:settings-pending", + "observation": { + "sender": ["b40605df86b7", "9fdaf48cf9b6", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.result-null:settled", + "observation": { + "sender": ["b40605df86b7", "9fdaf48cf9b6", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-ok-missing:settings-pending", + "observation": { + "sender": ["b40605df86b7", "153aad174580", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["b40605df86b7", "153aad174580", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-string-error:settings-pending", + "observation": { + "sender": ["b40605df86b7", "d589c372905b", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["b40605df86b7", "d589c372905b", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-object-error:settings-pending", + "observation": { + "sender": ["b40605df86b7", "205d78f95e06", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["b40605df86b7", "205d78f95e06", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused:settings-pending", + "observation": { + "sender": ["b40605df86b7", "5fd9a3414746", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused:settled", + "observation": { + "sender": ["b40605df86b7", "5fd9a3414746", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused-no-message:settings-pending", + "observation": { + "sender": ["b40605df86b7", "dcd949b896ed", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["b40605df86b7", "dcd949b896ed", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.method-not-found:settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7da3ff7d52e", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.method-not-found:settled", + "observation": { + "sender": ["b40605df86b7", "f7da3ff7d52e", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection:settings-pending", + "observation": { + "sender": ["b40605df86b7", "900068047f8a", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["b40605df86b7", "900068047f8a", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection-no-message:settings-pending", + "observation": { + "sender": ["b40605df86b7", "cb88e4c74a37", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["b40605df86b7", "cb88e4c74a37", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "eb68427ac627", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "700210d17d9e", + "388d7275af5f" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-folderworkspace.list-1.json b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-folderworkspace.list-1.json new file mode 100644 index 00000000000..2c8c593e51a --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-folderworkspace.list-1.json @@ -0,0 +1,1142 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "181e302d461f": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "18d27f5a5ff4": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "34d20dd52a59": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3c70da5d6d8e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "worktrees": [] + } + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "83189a0d5814": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "83c45fc0a236": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "9d3dff45ace3": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "ad1591bd5112": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "c541b2156a80": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "c749c7d8ac26": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "e7348f1edb42": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + }, + "f9ed4fd4d151": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.resume-metadata-folderworkspace.list-1", + "checkpoints": [ + { + "id": "settings-resume-metadata-fulfilled.normal:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.normal:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-absent:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "9d3dff45ace3", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-absent:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "9d3dff45ace3", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-null:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "e7348f1edb42", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-null:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "e7348f1edb42", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-ok-missing:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "f9ed4fd4d151", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "f9ed4fd4d151", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-string-error:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "83c45fc0a236", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "83c45fc0a236", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-object-error:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "83189a0d5814", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "83189a0d5814", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "c749c7d8ac26", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "c749c7d8ac26", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused-no-message:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "181e302d461f", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "181e302d461f", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.method-not-found:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "34d20dd52a59", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.method-not-found:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "34d20dd52a59", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "ad1591bd5112", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "ad1591bd5112", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection-no-message:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "c541b2156a80", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "c541b2156a80", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-projectgroup.list-1.json b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-projectgroup.list-1.json new file mode 100644 index 00000000000..f53788ef9c8 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-projectgroup.list-1.json @@ -0,0 +1,1142 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "01bc8208ba89": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "18d27f5a5ff4": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "1e6417970216": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "215a85dc1f8b": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "22f9b426b0c2": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3c70da5d6d8e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "worktrees": [] + } + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "4325c9c561d9": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "44136fa355b3": {}, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "8d2b0b707eda": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9410355ae6d7": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "a36922df60c5": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "a4ae13faed91": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "c25d799a53c1": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.resume-metadata-projectgroup.list-1", + "checkpoints": [ + { + "id": "settings-resume-metadata-fulfilled.normal:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.normal:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-absent:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "a4ae13faed91", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-absent:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "a4ae13faed91", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-null:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "22f9b426b0c2", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-null:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "22f9b426b0c2", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-ok-missing:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "215a85dc1f8b", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "215a85dc1f8b", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-string-error:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "c25d799a53c1", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "c25d799a53c1", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-object-error:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "a36922df60c5", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "a36922df60c5", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "8d2b0b707eda", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "8d2b0b707eda", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused-no-message:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "01bc8208ba89", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "01bc8208ba89", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.method-not-found:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "4325c9c561d9", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.method-not-found:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "4325c9c561d9", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "9410355ae6d7", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "9410355ae6d7", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection-no-message:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "1e6417970216", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "1e6417970216", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-repo.list-1.json b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-repo.list-1.json new file mode 100644 index 00000000000..b1633d81741 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-repo.list-1.json @@ -0,0 +1,1212 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0ae64c827aea": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "18d27f5a5ff4": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2381a3fe154e": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "Cannot read properties of undefined (reading 'repos')", + "isRpcDeliveryUnknown": false + } + }, + "32a7c0ae7918": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "outer refused", + "isRpcDeliveryUnknown": false + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3c70da5d6d8e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "worktrees": [] + } + }, + "3c82d75649f6": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "52bfda76d878": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "63dfbb6942f2": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "TypeError", + "message": "Cannot read properties of null (reading 'repos')", + "isRpcDeliveryUnknown": false + } + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "66ae612713eb": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "903707b33a87": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "a2ce659a6ba1": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "a4de68fe31f0": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "ab291c60ed46": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Unable to load workspace metadata.", + "isRpcDeliveryUnknown": false + } + }, + "b0434d55fb58": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "b948e8307e81": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Unknown method", + "isRpcDeliveryUnknown": false + } + }, + "c06aaf9dd8f5": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "c7584e82c72f": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + }, + "ff39fc8a6845": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.resume-metadata-repo.list-1", + "checkpoints": [ + { + "id": "settings-resume-metadata-fulfilled.normal:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.normal:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-absent:settings-pending", + "observation": { + "sender": [ + "c06aaf9dd8f5", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-absent:settled", + "observation": { + "sender": [ + "c06aaf9dd8f5", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "2381a3fe154e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-null:settings-pending", + "observation": { + "sender": [ + "52bfda76d878", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-null:settled", + "observation": { + "sender": [ + "52bfda76d878", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "63dfbb6942f2" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-ok-missing:settings-pending", + "observation": { + "sender": [ + "b0434d55fb58", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": [ + "b0434d55fb58", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-string-error:settings-pending", + "observation": { + "sender": [ + "ff39fc8a6845", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": [ + "ff39fc8a6845", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-object-error:settings-pending", + "observation": { + "sender": [ + "0ae64c827aea", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": [ + "0ae64c827aea", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused:settings-pending", + "observation": { + "sender": [ + "66ae612713eb", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused:settled", + "observation": { + "sender": [ + "66ae612713eb", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "32a7c0ae7918" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused-no-message:settings-pending", + "observation": { + "sender": [ + "903707b33a87", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": [ + "903707b33a87", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "ab291c60ed46" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.method-not-found:settings-pending", + "observation": { + "sender": [ + "a4de68fe31f0", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.method-not-found:settled", + "observation": { + "sender": [ + "a4de68fe31f0", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "b948e8307e81" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection:settings-pending", + "observation": { + "sender": [ + "3c82d75649f6", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "a947768bc0ed" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection:settled", + "observation": { + "sender": [ + "3c82d75649f6", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "a947768bc0ed" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection-no-message:settings-pending", + "observation": { + "sender": [ + "a2ce659a6ba1", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "c7584e82c72f" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "a2ce659a6ba1", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "c7584e82c72f" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-settings.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-settings.get-1.json new file mode 100644 index 00000000000..52f02304203 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-settings.get-1.json @@ -0,0 +1,916 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "172c1804073c": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "18d27f5a5ff4": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3c70da5d6d8e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "worktrees": [] + } + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "51376d8c72f9": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7dd8f694eab8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "ae5863344a60": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-4", + "ok": false + } + } + }, + "b01e4c71013d": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "b370b1b6811e": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "bef8ec25072d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "$rpc": "null" + }, + "worktrees": [] + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "cf53d83f071d": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "cff79a616f26": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-4", + "ok": false + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "e64a052ce032": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true + } + } + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + }, + "f970b472a5c6": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-4", + "ok": false + } + } + } + }, + "recording": { + "scenario": "matrix-settings.resume-metadata-settings.get-1", + "checkpoints": [ + { + "id": "settings-resume-metadata-fulfilled.prelude:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.normal:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-absent:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "e64a052ce032", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-null:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "172c1804073c", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "7dd8f694eab8", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "b01e4c71013d", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "b370b1b6811e", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "ae5863344a60", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "f970b472a5c6", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.method-not-found:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "cff79a616f26", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "51376d8c72f9", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "cf53d83f071d", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-worktree.ps-1.json b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-worktree.ps-1.json new file mode 100644 index 00000000000..a8b52f0aaec --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-worktree.ps-1.json @@ -0,0 +1,922 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0620c0819077": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "worktrees": { + "$rpc": "null" + } + } + }, + "063aab8060dc": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "18d27f5a5ff4": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "202490f13aba": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-5", + "ok": false + } + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3c70da5d6d8e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "worktrees": [] + } + }, + "3d2a818fc3a4": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "4248358a67cb": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "44136fa355b3": {}, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "5d7904f5569d": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "77d369a76345": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "7b6c7d3ffc56": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-5", + "ok": false + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "9bac7c18c6f2": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-5", + "ok": false + } + } + }, + "a469b68534ac": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true + } + } + }, + "c6caf75a15d6": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.resume-metadata-worktree.ps-1", + "checkpoints": [ + { + "id": "settings-resume-metadata-fulfilled.prelude:settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.normal:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-absent:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "a469b68534ac" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.result-null:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "063aab8060dc" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "3d2a818fc3a4" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "c6caf75a15d6" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "5d7904f5569d" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "7b6c7d3ffc56" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "9bac7c18c6f2" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.method-not-found:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "202490f13aba" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "4248358a67cb" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "77d369a76345" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "0620c0819077" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-linear.status-1.json b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-linear.status-1.json new file mode 100644 index 00000000000..e1adbce9025 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-linear.status-1.json @@ -0,0 +1,1907 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "0188d88101b8": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-5", + "ok": false + } + } + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "158449a16852": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "4620b5cc7ae9": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "58c52d8b7c76": { + "hydrated": true, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "79d765c34258": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-5", + "ok": false + } + } + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "9203cee5313f": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "945ea389c1ef": { + "name": "error", + "value": "transport failure" + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "a9b0412f8019": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-5", + "ok": false + } + } + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c0659c6ea513": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "c9e80e33c0bf": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true + } + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d04b03f317eb": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "d705fce957e8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ed4a7babca45": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "matrix-settings.task-hydration-linear.status-1", + "checkpoints": [ + { + "id": "settings-task-hydration-fulfilled.prelude:settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.normal:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-absent:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "c9e80e33c0bf" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-null:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "9203cee5313f" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "ed4a7babca45" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "d04b03f317eb" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "c0659c6ea513" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "0188d88101b8" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "79d765c34258" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.method-not-found:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "a9b0412f8019" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "158449a16852" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "945ea389c1ef", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "4620b5cc7ae9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "82cd71d524c8", + "bbbd4bc0a4ef" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-preflight.check-1.json b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-preflight.check-1.json new file mode 100644 index 00000000000..f1a5a0b5513 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-preflight.check-1.json @@ -0,0 +1,1907 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "3432b49304a5": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4cc1b000bcfc": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-4", + "ok": false + } + } + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "535a11fdd274": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-4", + "ok": false + } + } + }, + "53979e0eec1b": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "58c52d8b7c76": { + "hydrated": true, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5daecca27f06": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "753d67797760": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "945ea389c1ef": { + "name": "error", + "value": "transport failure" + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "a042b29c0044": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c7515370fa5c": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-4", + "ok": false + } + } + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "ca8f5459b39f": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "cb5554e28eb2": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true + } + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "d705fce957e8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "matrix-settings.task-hydration-preflight.check-1", + "checkpoints": [ + { + "id": "settings-task-hydration-fulfilled.prelude:settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.normal:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-absent:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "cb5554e28eb2", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-null:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "53979e0eec1b", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "753d67797760", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "3432b49304a5", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "5daecca27f06", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "4cc1b000bcfc", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "535a11fdd274", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.method-not-found:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "c7515370fa5c", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "a042b29c0044", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "945ea389c1ef", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "ca8f5459b39f", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "82cd71d524c8", + "bbbd4bc0a4ef" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-settings.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-settings.get-1.json new file mode 100644 index 00000000000..1712f46acdd --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-settings.get-1.json @@ -0,0 +1,1889 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1e7f0f9265cc": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2ae8bb906793": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "2b3aa0da0852": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "35584987e88e": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "58c52d8b7c76": { + "hydrated": true, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6d584492e802": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "72d637915e56": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "8ac078069a5d": { + "name": "error", + "value": "Cannot read properties of null (reading 'settings')" + }, + "8b77098df0c3": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "8bbc0944abe9": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "924e33dd1165": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "945ea389c1ef": { + "name": "error", + "value": "transport failure" + }, + "963a91c532c8": { + "hydrated": true, + "settings": {} + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "d705fce957e8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "dae7907f03cc": { + "name": "runtimeTaskSettings", + "value": {} + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ed866f202034": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "eef5e6921665": { + "name": "error", + "value": "Cannot read properties of undefined (reading 'settings')" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "matrix-settings.task-hydration-settings.get-1", + "checkpoints": [ + { + "id": "settings-task-hydration-fulfilled.prelude:settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.normal:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-absent:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "ed866f202034", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "eef5e6921665", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-null:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "924e33dd1165", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "8ac078069a5d", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "35584987e88e", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "963a91c532c8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "dae7907f03cc", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "1e7f0f9265cc", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "963a91c532c8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "dae7907f03cc", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "8bbc0944abe9", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "963a91c532c8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "dae7907f03cc", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "72d637915e56", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "963a91c532c8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "dae7907f03cc", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "6d584492e802", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "963a91c532c8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "dae7907f03cc", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.method-not-found:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "2ae8bb906793", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "963a91c532c8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "dae7907f03cc", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "8b77098df0c3", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "945ea389c1ef", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "2b3aa0da0852", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "82cd71d524c8", + "bbbd4bc0a4ef" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-status.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-status.get-1.json new file mode 100644 index 00000000000..1f50266e65c --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-status.get-1.json @@ -0,0 +1,2444 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "11b132a242c1": { + "name": "githubProjectTable", + "value": { + "$rpc": "null" + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "16cd464bf664": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "186f44bc465a": { + "name": "error", + "value": "Unknown method" + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2698c9770ad3": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "2c295738907d": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unsupported" + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "442bdfe26748": { + "name": "error", + "value": "Update Orca desktop to use Tasks on mobile." + }, + "4451bb95a76e": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "58c52d8b7c76": { + "hydrated": true, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7d3dd7f9381b": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "85338c16b05b": { + "name": "error", + "value": "Cannot read properties of null (reading 'capabilities')" + }, + "88200d49083c": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "89236e432861": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "8936cd17eb1c": { + "name": "items", + "value": [] + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "944bf432f199": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "945ea389c1ef": { + "name": "error", + "value": "transport failure" + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "9cdf3c107e7b": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "ba65a7abe43b": { + "name": "error", + "value": "outer refused" + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c71b2f8a6993": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "cffae499abea": { + "name": "error", + "value": "Cannot read properties of undefined (reading 'capabilities')" + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "d705fce957e8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "de87f6266897": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ebedcb7a3ad7": { + "name": "reset-items", + "value": { + "$rpc": "null" + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "matrix-settings.task-hydration-status.get-1", + "checkpoints": [ + { + "id": "settings-task-hydration-fulfilled.normal:settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.normal:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-absent:settings-pending", + "observation": { + "sender": ["7d3dd7f9381b"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "cffae499abea", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-absent:settled", + "observation": { + "sender": ["7d3dd7f9381b"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "cffae499abea", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-null:settings-pending", + "observation": { + "sender": ["88200d49083c"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "85338c16b05b", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-null:settled", + "observation": { + "sender": ["88200d49083c"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "85338c16b05b", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-ok-missing:settings-pending", + "observation": { + "sender": ["4451bb95a76e"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "2c295738907d", + "8936cd17eb1c", + "ebedcb7a3ad7", + "11b132a242c1", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "442bdfe26748", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["4451bb95a76e"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "2c295738907d", + "8936cd17eb1c", + "ebedcb7a3ad7", + "11b132a242c1", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "442bdfe26748", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-string-error:settings-pending", + "observation": { + "sender": ["944bf432f199"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "2c295738907d", + "8936cd17eb1c", + "ebedcb7a3ad7", + "11b132a242c1", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "442bdfe26748", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["944bf432f199"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "2c295738907d", + "8936cd17eb1c", + "ebedcb7a3ad7", + "11b132a242c1", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "442bdfe26748", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-object-error:settings-pending", + "observation": { + "sender": ["89236e432861"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "2c295738907d", + "8936cd17eb1c", + "ebedcb7a3ad7", + "11b132a242c1", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "442bdfe26748", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["89236e432861"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "2c295738907d", + "8936cd17eb1c", + "ebedcb7a3ad7", + "11b132a242c1", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "442bdfe26748", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused:settings-pending", + "observation": { + "sender": ["16cd464bf664"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "ba65a7abe43b", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused:settled", + "observation": { + "sender": ["16cd464bf664"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "ba65a7abe43b", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused-no-message:settings-pending", + "observation": { + "sender": ["9cdf3c107e7b"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "82cd71d524c8", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["9cdf3c107e7b"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "82cd71d524c8", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.method-not-found:settings-pending", + "observation": { + "sender": ["c71b2f8a6993"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "186f44bc465a", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.method-not-found:settled", + "observation": { + "sender": ["c71b2f8a6993"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "186f44bc465a", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection:settings-pending", + "observation": { + "sender": ["de87f6266897"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "945ea389c1ef", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["de87f6266897"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "945ea389c1ef", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection-no-message:settings-pending", + "observation": { + "sender": ["2698c9770ad3"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "82cd71d524c8", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["2698c9770ad3"], + "payloads": ["1e5b32902af7"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "82cd71d524c8", + "bbbd4bc0a4ef" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-ui.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-ui.get-1.json new file mode 100644 index 00000000000..8cf20f5f9ad --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.task-hydration-ui.get-1.json @@ -0,0 +1,1893 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "0039f2221403": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "1825a87a7ca8": { + "hydrated": false, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "29b675c48636": { + "name": "error", + "value": "Cannot read properties of undefined (reading 'ui')" + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "32d752320864": { + "name": "error", + "value": "Cannot read properties of null (reading 'ui')" + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "3567f6da3a57": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3d09c833d11e": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "58c52d8b7c76": { + "hydrated": true, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "58e6d47c8e59": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "71c1a40e9769": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "757d36f7d7c1": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "8c5d1428d987": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "8e434f3798db": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "945ea389c1ef": { + "name": "error", + "value": "transport failure" + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aaa76c6c664c": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "d705fce957e8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f2b6195abacc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "matrix-settings.task-hydration-ui.get-1", + "checkpoints": [ + { + "id": "settings-task-hydration-fulfilled.prelude:settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.normal:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-absent:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "aaa76c6c664c", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "1825a87a7ca8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "29b675c48636", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.result-null:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "3567f6da3a57", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "1825a87a7ca8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "32d752320864", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "8c5d1428d987", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "71c1a40e9769", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "58e6d47c8e59", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "8e434f3798db", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "3d09c833d11e", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.method-not-found:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "f2b6195abacc", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "757d36f7d7c1", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "945ea389c1ef", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "0039f2221403", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "82cd71d524c8", + "bbbd4bc0a4ef" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.task-workspace-settings.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.task-workspace-settings.get-1.json new file mode 100644 index 00000000000..148c70b1147 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.task-workspace-settings.get-1.json @@ -0,0 +1,804 @@ +{ + "operation": "settings.task-workspace", + "family": "settings.task-workspace", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fc3e204e7ba": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "127ad2bdc042": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "2b3aa0da0852": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "3405a06dce84": { + "name": "error", + "value": "Selected agent is disabled. Choose an enabled agent before creating." + }, + "3f453dd79b03": { + "name": "workspaceAgent", + "value": "codex" + }, + "6a98511b6371": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "730f92993963": { + "name": "creatingKey", + "value": "linear:1" + }, + "7abdfe20af50": { + "creating": "linear:1", + "error": "", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "7ca23c4c946b": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8b77098df0c3": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "8b8197eed660": { + "creating": { + "$rpc": "null" + }, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "8f8296303a77": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "adec34c2065c": { + "creating": { + "$rpc": "null" + }, + "error": "", + "settings": {} + }, + "b4aa36380c40": { + "name": "setupPrompt", + "value": { + "agentOverride": "claude", + "command": "setup", + "item": { + "key": "linear:1", + "provider": "linear", + "source": { + "id": "issue-1" + } + }, + "repoName": "Repo", + "source": "repo" + } + }, + "b759ab27e4dd": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "c9cb32059b8d": { + "name": "creatingKey", + "value": { + "$rpc": "null" + } + }, + "d27ce798af34": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "d5df3f6b123a": { + "creating": { + "$rpc": "null" + }, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "dae7907f03cc": { + "name": "runtimeTaskSettings", + "value": {} + }, + "e0cf1af55a54": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "e1bd8b4a5d70": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "ea709e13f0f0": { + "name": "workspaceAgentOverridden", + "value": false + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f84a8688af61": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "recording": { + "scenario": "matrix-settings.task-workspace-settings.get-1", + "checkpoints": [ + { + "id": "settings-task-workspace-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "7abdfe20af50", + "effects": ["730f92993963", "82cd71d524c8"] + } + }, + { + "id": "settings-task-workspace-fulfilled.prelude:cleanup", + "observation": { + "sender": ["f84a8688af61"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "7abdfe20af50", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.normal:settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "8b8197eed660", + "effects": [ + "730f92993963", + "82cd71d524c8", + "326e3f8f7e0b", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.result-absent:settled", + "observation": { + "sender": ["e0cf1af55a54"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "d5df3f6b123a", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.result-null:settled", + "observation": { + "sender": ["e1bd8b4a5d70"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "d5df3f6b123a", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["0fc3e204e7ba"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "adec34c2065c", + "effects": [ + "730f92993963", + "82cd71d524c8", + "dae7907f03cc", + "b4aa36380c40", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["d27ce798af34"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "adec34c2065c", + "effects": [ + "730f92993963", + "82cd71d524c8", + "dae7907f03cc", + "b4aa36380c40", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["127ad2bdc042"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "adec34c2065c", + "effects": [ + "730f92993963", + "82cd71d524c8", + "dae7907f03cc", + "b4aa36380c40", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.outer-refused:settled", + "observation": { + "sender": ["8f8296303a77"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "d5df3f6b123a", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["6a98511b6371"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "d5df3f6b123a", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.method-not-found:settled", + "observation": { + "sender": ["b759ab27e4dd"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "d5df3f6b123a", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["8b77098df0c3"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "d5df3f6b123a", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + }, + { + "id": "settings-task-workspace-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["2b3aa0da0852"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "d5df3f6b123a", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-linear.status-1.json b/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-linear.status-1.json new file mode 100644 index 00000000000..18e7e37627b --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-linear.status-1.json @@ -0,0 +1,776 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "158449a16852": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2a7485a88169": { + "providers": ["github"], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "35e63fba1bfc": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-2", + "ok": false + } + } + }, + "406d79ff45ca": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4620b5cc7ae9": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "77975bbcd4be": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "7a4c4c2227f8": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "883566e08378": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "ae32d773383c": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + }, + "f81d65015197": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "f8e51955170c": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.workspace-context-linear.status-1", + "checkpoints": [ + { + "id": "settings-workspace-context-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.normal:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.result-absent:settled", + "observation": { + "sender": ["563e4c82b345", "7a4c4c2227f8", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.result-null:settled", + "observation": { + "sender": ["563e4c82b345", "f8e51955170c", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["563e4c82b345", "406d79ff45ca", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["563e4c82b345", "ae32d773383c", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["563e4c82b345", "883566e08378", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.outer-refused:settled", + "observation": { + "sender": ["563e4c82b345", "f81d65015197", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["563e4c82b345", "77975bbcd4be", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.method-not-found:settled", + "observation": { + "sender": ["563e4c82b345", "35e63fba1bfc", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["563e4c82b345", "158449a16852", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["563e4c82b345", "4620b5cc7ae9", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-preflight.check-1.json b/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-preflight.check-1.json new file mode 100644 index 00000000000..78f6745beed --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-preflight.check-1.json @@ -0,0 +1,776 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02eac6141a1f": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2a7485a88169": { + "providers": ["github"], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "2b9e034d9983": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "5db3a8e21647": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "83ca8036193a": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "84b6f82edb6e": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "a042b29c0044": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a7aa6be3bc50": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "b2d23d4a833f": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "bb36ad1df1bc": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "ca8f5459b39f": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + } + }, + "recording": { + "scenario": "matrix-settings.workspace-context-preflight.check-1", + "checkpoints": [ + { + "id": "settings-workspace-context-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.normal:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.result-absent:settled", + "observation": { + "sender": ["a7aa6be3bc50", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.result-null:settled", + "observation": { + "sender": ["5db3a8e21647", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["84b6f82edb6e", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["83ca8036193a", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["bb36ad1df1bc", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.outer-refused:settled", + "observation": { + "sender": ["b2d23d4a833f", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["02eac6141a1f", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.method-not-found:settled", + "observation": { + "sender": ["2b9e034d9983", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["a042b29c0044", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["ca8f5459b39f", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-settings.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-settings.get-1.json new file mode 100644 index 00000000000..9322f1ad6a7 --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-settings.get-1.json @@ -0,0 +1,799 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "045f11564884": { + "name": "unhandled-rejection", + "value": { + "category": "TypeError", + "isRpcDeliveryUnknown": false, + "message": "Cannot read properties of null (reading 'settings')" + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "099b501d90c2": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "0c433d37dba9": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2a7485a88169": { + "providers": ["github"], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "2b3aa0da0852": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "329ace7b96e9": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true + } + } + }, + "3a834cb85dd8": { + "providers": ["github"], + "settings": { + "$rpc": "null" + }, + "trust": {} + }, + "4043cd1b2634": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "4fdb20ad5654": { + "name": "unhandled-rejection", + "value": { + "category": "TypeError", + "isRpcDeliveryUnknown": false, + "message": "Cannot read properties of undefined (reading 'settings')" + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "8b77098df0c3": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "9582447b1277": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "9a2df19b1d5f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-3", + "ok": false + } + } + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "d3eea0a00315": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-3", + "ok": false + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + }, + "ff34527b3e2e": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "error": "refused" + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.workspace-context-settings.get-1", + "checkpoints": [ + { + "id": "settings-workspace-context-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.normal:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.result-absent:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "329ace7b96e9", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": ["4fdb20ad5654"] + } + }, + { + "id": "settings-workspace-context-fulfilled.result-null:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "9582447b1277", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": ["045f11564884"] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "ff34527b3e2e", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "4043cd1b2634", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "099b501d90c2", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.outer-refused:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "0c433d37dba9", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "9a2df19b1d5f", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.method-not-found:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "d3eea0a00315", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "8b77098df0c3", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "2b3aa0da0852", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-ui.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-ui.get-1.json new file mode 100644 index 00000000000..3f2e02be3fc --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.workspace-context-ui.get-1.json @@ -0,0 +1,803 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0039f2221403": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0949ca378eeb": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true + } + } + }, + "0d56880d8286": { + "name": "unhandled-rejection", + "value": { + "category": "TypeError", + "isRpcDeliveryUnknown": false, + "message": "Cannot read properties of undefined (reading 'ui')" + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2a7485a88169": { + "providers": ["github"], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "531bba7bae49": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6b1ec8280e91": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-4", + "ok": false + } + } + }, + "757d36f7d7c1": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "78b8435a485f": { + "name": "unhandled-rejection", + "value": { + "category": "TypeError", + "isRpcDeliveryUnknown": false, + "message": "Cannot read properties of null (reading 'ui')" + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "8947d9c9202f": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "8a63b85fee0c": { + "providers": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "8be416d0b1ef": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-4", + "ok": false + } + } + }, + "8cbd7ddc26d9": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-4", + "ok": false + } + } + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e9f764966b3b": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + }, + "fdb9d6146352": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + } + }, + "recording": { + "scenario": "matrix-settings.workspace-context-ui.get-1", + "checkpoints": [ + { + "id": "settings-workspace-context-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.normal:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.result-absent:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "0949ca378eeb"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": ["0d56880d8286"] + } + }, + { + "id": "settings-workspace-context-fulfilled.result-null:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "8947d9c9202f"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "8a63b85fee0c", + "effects": ["78b8435a485f"] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "531bba7bae49"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "fdb9d6146352"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "e9f764966b3b"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.outer-refused:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "8be416d0b1ef"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "6b1ec8280e91"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.method-not-found:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "8cbd7ddc26d9"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "757d36f7d7c1"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "0039f2221403"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-settings.workspace-submit-settings.get-1.json b/mobile/rpc-foundation/goldens/matrix-settings.workspace-submit-settings.get-1.json new file mode 100644 index 00000000000..faadddb002e --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-settings.workspace-submit-settings.get-1.json @@ -0,0 +1,818 @@ +{ + "operation": "settings.workspace-submit", + "family": "settings.workspace-submit", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fc3e204e7ba": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "127ad2bdc042": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "13c996e4ec2b": { + "creating": true, + "error": "", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "2b3aa0da0852": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "2e8e352c8dd1": { + "creating": false, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "3405a06dce84": { + "name": "error", + "value": "Selected agent is disabled. Choose an enabled agent before creating." + }, + "588949297c83": { + "name": "worktree.create#1", + "args": [ + { + "name": "method", + "value": "worktree.create" + }, + { + "name": "params", + "value": { + "createdWithAgent": "claude", + "displayName": "recorded", + "displayNameKind": "user", + "name": "recorded", + "repo": "id:repo-1", + "setupDecision": "inherit", + "startupAgent": "claude" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 600000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + }, + "5efbd884ea5a": { + "creating": false, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "6a98511b6371": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "6c2789ab0e4b": { + "name": "runtimeSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "6f447a389087": { + "name": "runtimeSettings", + "value": { + "$rpc": "undefined" + } + }, + "7b1c9637063f": { + "creating": true, + "error": "", + "settings": { + "$rpc": "undefined" + } + }, + "7ca23c4c946b": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8b77098df0c3": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "8f8296303a77": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9f82f10075a3": { + "name": "error", + "value": "Connection closed" + }, + "ae291b5dba88": { + "name": "agentOverridden", + "value": false + }, + "b759ab27e4dd": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "d27ce798af34": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "e0cf1af55a54": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "e1bd8b4a5d70": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "eb6f7a9c5bf1": { + "name": "selectedAgent", + "value": { + "id": "codex", + "label": "Codex" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f0d91b98b6a3": { + "name": "worktree.create#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.create\",\"params\":{\"repo\":\"id:repo-1\",\"setupDecision\":\"inherit\",\"name\":\"recorded\",\"displayName\":\"recorded\",\"displayNameKind\":\"user\",\"startupAgent\":\"claude\",\"createdWithAgent\":\"claude\"}}" + }, + "f84a8688af61": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + }, + "fbc1bf929509": { + "name": "worktree.create#1", + "args": [ + { + "name": "method", + "value": "worktree.create" + }, + { + "name": "params", + "value": { + "createdWithAgent": "claude", + "displayName": "recorded", + "displayNameKind": "user", + "name": "recorded", + "repo": "id:repo-1", + "setupDecision": "inherit", + "startupAgent": "claude" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 600000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "matrix-settings.workspace-submit-settings.get-1", + "checkpoints": [ + { + "id": "settings-workspace-submit-fulfilled.prelude:settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "13c996e4ec2b", + "effects": ["82cd71d524c8"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.prelude:cleanup", + "observation": { + "sender": ["f84a8688af61"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "13c996e4ec2b", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.normal:settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "5efbd884ea5a", + "effects": [ + "82cd71d524c8", + "6c2789ab0e4b", + "eb6f7a9c5bf1", + "ae291b5dba88", + "3405a06dce84" + ] + } + }, + { + "id": "settings-workspace-submit-fulfilled.result-absent:settled", + "observation": { + "sender": ["e0cf1af55a54"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2e8e352c8dd1", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.result-null:settled", + "observation": { + "sender": ["e1bd8b4a5d70"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2e8e352c8dd1", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.inner-ok-missing:settled", + "observation": { + "sender": ["0fc3e204e7ba", "fbc1bf929509"], + "payloads": ["7ddcb1852b39", "f0d91b98b6a3"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "7b1c9637063f", + "effects": ["82cd71d524c8", "6f447a389087"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.inner-ok-missing:cleanup", + "observation": { + "sender": ["0fc3e204e7ba", "588949297c83"], + "payloads": ["7ddcb1852b39", "f0d91b98b6a3"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "7b1c9637063f", + "effects": ["82cd71d524c8", "6f447a389087", "9f82f10075a3"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.inner-false-string-error:settled", + "observation": { + "sender": ["d27ce798af34", "fbc1bf929509"], + "payloads": ["7ddcb1852b39", "f0d91b98b6a3"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "7b1c9637063f", + "effects": ["82cd71d524c8", "6f447a389087"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.inner-false-string-error:cleanup", + "observation": { + "sender": ["d27ce798af34", "588949297c83"], + "payloads": ["7ddcb1852b39", "f0d91b98b6a3"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "7b1c9637063f", + "effects": ["82cd71d524c8", "6f447a389087", "9f82f10075a3"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.inner-false-object-error:settled", + "observation": { + "sender": ["127ad2bdc042", "fbc1bf929509"], + "payloads": ["7ddcb1852b39", "f0d91b98b6a3"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "7b1c9637063f", + "effects": ["82cd71d524c8", "6f447a389087"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.inner-false-object-error:cleanup", + "observation": { + "sender": ["127ad2bdc042", "588949297c83"], + "payloads": ["7ddcb1852b39", "f0d91b98b6a3"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "7b1c9637063f", + "effects": ["82cd71d524c8", "6f447a389087", "9f82f10075a3"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.outer-refused:settled", + "observation": { + "sender": ["8f8296303a77"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2e8e352c8dd1", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.outer-refused-no-message:settled", + "observation": { + "sender": ["6a98511b6371"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2e8e352c8dd1", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.method-not-found:settled", + "observation": { + "sender": ["b759ab27e4dd"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2e8e352c8dd1", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.transport-rejection:settled", + "observation": { + "sender": ["8b77098df0c3"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2e8e352c8dd1", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + }, + { + "id": "settings-workspace-submit-fulfilled.transport-rejection-no-message:settled", + "observation": { + "sender": ["2b3aa0da0852"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2e8e352c8dd1", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/matrix-worktree.review-link-worktree.set-1.json b/mobile/rpc-foundation/goldens/matrix-worktree.review-link-worktree.set-1.json new file mode 100644 index 00000000000..b86fd4be1fa --- /dev/null +++ b/mobile/rpc-foundation/goldens/matrix-worktree.review-link-worktree.set-1.json @@ -0,0 +1,670 @@ +{ + "operation": "source-control.pr-link", + "family": "worktree.review-link", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0d39ad71ac82": { + "linkedPR": "unread", + "outcome": { + "error": "Unknown method", + "ok": false + } + }, + "1852c739af4f": { + "linkedPR": "unread", + "outcome": { + "ok": true + } + }, + "1b2778bf67a2": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "outer refused", + "ok": false + } + }, + "2c746c8732cd": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2dadf8156e0a": { + "linkedPR": "unread", + "outcome": { + "error": "Failed to update linked pull request", + "ok": false + } + }, + "319aa77fad74": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true + } + } + }, + "35cef38d4b19": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "3beb771c862a": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "41bdce9de379": { + "linkedPR": "unread", + "outcome": "unlinked" + }, + "45e5fb9620bf": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": { + "message": "inner refused" + }, + "ok": false + } + } + } + }, + "86441203344c": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "898327d6d921": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "inner refused", + "ok": false + } + } + } + }, + "921b977a5f07": { + "linkedPR": "unread", + "outcome": { + "error": "outer refused", + "ok": false + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "a197c20578aa": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "transport failure", + "ok": false + } + }, + "a42570f300ad": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Failed to update linked pull request", + "ok": false + } + }, + "b91c2f7fddc7": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "c49c62e3c88e": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "outer refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "c5cfd8d3e2ed": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "c7ae0a3a6e6e": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"linkedPR\":12}}" + }, + "c8de0688e42c": { + "linkedPR": "unread", + "outcome": { + "error": "transport failure", + "ok": false + } + }, + "d10cb6e1e0b5": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + }, + "e04a0178bf7f": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "refused" + } + } + } + }, + "f384395675ad": { + "linkedPR": "unread", + "outcome": { + "error": "", + "ok": false + } + }, + "fa93ca01f266": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Unknown method", + "ok": false + } + }, + "fb4429083480": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "", + "ok": false + } + }, + "fbc958e4d46e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true + } + } + }, + "recording": { + "scenario": "matrix-worktree.review-link-worktree.set-1", + "checkpoints": [ + { + "id": "sc-pr-link-set.prelude:pending", + "observation": { + "sender": ["2c746c8732cd"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "9270aeb7d9c6" + }, + "state": "41bdce9de379", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.normal:settled", + "observation": { + "sender": ["86441203344c"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "fbc958e4d46e" + }, + "state": "1852c739af4f", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.result-absent:settled", + "observation": { + "sender": ["319aa77fad74"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "fbc958e4d46e" + }, + "state": "1852c739af4f", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.result-null:settled", + "observation": { + "sender": ["3beb771c862a"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "fbc958e4d46e" + }, + "state": "1852c739af4f", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.inner-ok-missing:settled", + "observation": { + "sender": ["e04a0178bf7f"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "fbc958e4d46e" + }, + "state": "1852c739af4f", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.inner-false-string-error:settled", + "observation": { + "sender": ["898327d6d921"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "fbc958e4d46e" + }, + "state": "1852c739af4f", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.inner-false-object-error:settled", + "observation": { + "sender": ["45e5fb9620bf"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "fbc958e4d46e" + }, + "state": "1852c739af4f", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.outer-refused:settled", + "observation": { + "sender": ["c49c62e3c88e"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "1b2778bf67a2" + }, + "state": "921b977a5f07", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.outer-refused-no-message:settled", + "observation": { + "sender": ["35cef38d4b19"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "a42570f300ad" + }, + "state": "2dadf8156e0a", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.method-not-found:settled", + "observation": { + "sender": ["d10cb6e1e0b5"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "fa93ca01f266" + }, + "state": "0d39ad71ac82", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.transport-rejection:settled", + "observation": { + "sender": ["b91c2f7fddc7"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "a197c20578aa" + }, + "state": "c8de0688e42c", + "effects": [] + } + }, + { + "id": "sc-pr-link-set.transport-rejection-no-message:settled", + "observation": { + "sender": ["c5cfd8d3e2ed"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "fb4429083480" + }, + "state": "f384395675ad", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/probe-new-tab-both-refused.json b/mobile/rpc-foundation/goldens/probe-new-tab-both-refused.json new file mode 100644 index 00000000000..e162af1a201 --- /dev/null +++ b/mobile/rpc-foundation/goldens/probe-new-tab-both-refused.json @@ -0,0 +1,227 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "68155c1eb584": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "943484d45f2e": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "agents refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "b5553341aa32": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings refused", + "isRpcDeliveryUnknown": false + } + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + } + }, + "recording": { + "scenario": "probe-new-tab-both-refused", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["bae1ab4f96f9", "68155c1eb584", "943484d45f2e"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b5553341aa32" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/probe-new-tab-null-sibling-refused.json b/mobile/rpc-foundation/goldens/probe-new-tab-null-sibling-refused.json new file mode 100644 index 00000000000..a8661486565 --- /dev/null +++ b/mobile/rpc-foundation/goldens/probe-new-tab-null-sibling-refused.json @@ -0,0 +1,226 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "373710a63329": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "agents refused", + "isRpcDeliveryUnknown": false + } + }, + "44136fa355b3": {}, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "924e33dd1165": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "943484d45f2e": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "agents refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + } + }, + "recording": { + "scenario": "probe-new-tab-null-sibling-refused", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["bae1ab4f96f9", "924e33dd1165", "943484d45f2e"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "373710a63329" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/probe-new-tab-refused-sibling-rejects.json b/mobile/rpc-foundation/goldens/probe-new-tab-refused-sibling-rejects.json new file mode 100644 index 00000000000..a9d59429b6a --- /dev/null +++ b/mobile/rpc-foundation/goldens/probe-new-tab-refused-sibling-rejects.json @@ -0,0 +1,224 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "68155c1eb584": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7d14967a1151": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "agents disconnected", + "isRpcDeliveryUnknown": true + } + }, + "8da6b504bc95": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "agents disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + } + }, + "recording": { + "scenario": "probe-new-tab-refused-sibling-rejects", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["bae1ab4f96f9", "68155c1eb584", "8da6b504bc95"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "7d14967a1151" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/probe-new-tab-rejects-sibling-refused.json b/mobile/rpc-foundation/goldens/probe-new-tab-rejects-sibling-refused.json new file mode 100644 index 00000000000..d1eef4a3c31 --- /dev/null +++ b/mobile/rpc-foundation/goldens/probe-new-tab-rejects-sibling-refused.json @@ -0,0 +1,224 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "10aeb294c268": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "618234017ab2": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "943484d45f2e": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "agents refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + } + }, + "recording": { + "scenario": "probe-new-tab-rejects-sibling-refused", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["bae1ab4f96f9", "10aeb294c268", "943484d45f2e"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "618234017ab2" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-base-ref-default.json b/mobile/rpc-foundation/goldens/sc-base-ref-default.json new file mode 100644 index 00000000000..5db55685a29 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-base-ref-default.json @@ -0,0 +1,267 @@ +{ + "operation": "source-control.branch-base-ref", + "family": "git.base-ref-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "089d79f002a1": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "repos": [ + { + "id": "repo42", + "worktreeBaseRef": { + "$rpc": "null" + } + } + ] + } + } + } + }, + "198cce9909ce": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": "origin/main" + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "4dce743b400a": { + "baseRef": "unresolved" + }, + "535f7698e80e": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "594101d24d72": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "5f661e5b3de8": { + "baseRef": "origin/main" + }, + "6396d004a0e7": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "worktree": { + "baseRef": " " + } + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "b46548195c7a": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "defaultBaseRef": " origin/main " + } + } + } + }, + "c6857d66bf1a": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "cd73fe3775d3": { + "name": "repo.baseRefDefault#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"repo.baseRefDefault\",\"params\":{\"repo\":\"id:repo42\"}}" + }, + "cec763c8abc6": { + "name": "worktree.show#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.show\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + } + }, + "recording": { + "scenario": "sc-base-ref-default", + "checkpoints": [ + { + "id": "requests-pending", + "observation": { + "sender": ["535f7698e80e", "26accd69bc48"], + "payloads": ["cec763c8abc6", "594101d24d72"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "barrier-settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "c6857d66bf1a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["6396d004a0e7", "089d79f002a1", "b46548195c7a"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "198cce9909ce" + }, + "state": "5f661e5b3de8", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-base-ref-repo-fallback.json b/mobile/rpc-foundation/goldens/sc-base-ref-repo-fallback.json new file mode 100644 index 00000000000..5af5b4f1296 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-base-ref-repo-fallback.json @@ -0,0 +1,121 @@ +{ + "operation": "source-control.branch-base-ref", + "family": "git.base-ref-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "594101d24d72": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "74dda17aff6f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": "origin/rel" + }, + "b2161cb8d5b5": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "no worktree" + }, + "id": "frame-1", + "ok": false + } + } + }, + "cec763c8abc6": { + "name": "worktree.show#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.show\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "dc11f1ff4a3d": { + "baseRef": "origin/rel" + }, + "f6f2870a1e9d": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "repos": [ + { + "id": "repo42", + "worktreeBaseRef": " origin/rel " + } + ] + } + } + } + } + }, + "recording": { + "scenario": "sc-base-ref-repo-fallback", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["b2161cb8d5b5", "f6f2870a1e9d"], + "payloads": ["cec763c8abc6", "594101d24d72"], + "settlements": { + "resolve": "74dda17aff6f" + }, + "state": "dc11f1ff4a3d", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-base-ref-unavailable.json b/mobile/rpc-foundation/goldens/sc-base-ref-unavailable.json new file mode 100644 index 00000000000..a7bc4b6b138 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-base-ref-unavailable.json @@ -0,0 +1,159 @@ +{ + "operation": "source-control.branch-base-ref", + "family": "git.base-ref-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "594101d24d72": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "8c0c5002db30": { + "name": "repo.baseRefDefault#1", + "args": [ + { + "name": "method", + "value": "repo.baseRefDefault" + }, + { + "name": "params", + "value": { + "repo": "id:repo42" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "forbidden", + "message": "git is not available to mobile clients" + }, + "id": "frame-3", + "ok": false + } + } + }, + "cd73fe3775d3": { + "name": "repo.baseRefDefault#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"repo.baseRefDefault\",\"params\":{\"repo\":\"id:repo42\"}}" + }, + "cec763c8abc6": { + "name": "worktree.show#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.show\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "de82d9737123": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "forbidden", + "message": "nope" + }, + "id": "frame-2", + "ok": false + } + } + }, + "e2fbc2b9e8e9": { + "baseRef": { + "$rpc": "null" + } + }, + "ee20a1dc39e7": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "null" + } + }, + "f9af0bcc7ed6": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "method_not_found", + "message": "Unknown method" + }, + "id": "frame-1", + "ok": false + } + } + } + }, + "recording": { + "scenario": "sc-base-ref-unavailable", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["f9af0bcc7ed6", "de82d9737123", "8c0c5002db30"], + "payloads": ["cec763c8abc6", "594101d24d72", "cd73fe3775d3"], + "settlements": { + "resolve": "ee20a1dc39e7" + }, + "state": "e2fbc2b9e8e9", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-base-ref-worktree-hit.json b/mobile/rpc-foundation/goldens/sc-base-ref-worktree-hit.json new file mode 100644 index 00000000000..89064dffb11 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-base-ref-worktree-hit.json @@ -0,0 +1,161 @@ +{ + "operation": "source-control.branch-base-ref", + "family": "git.base-ref-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "4dce743b400a": { + "baseRef": "unresolved" + }, + "576578948f60": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": "origin/dev" + }, + "594101d24d72": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "69d1fb735581": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "cec763c8abc6": { + "name": "worktree.show#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.show\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "d33da78bedd6": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "worktree": { + "baseRef": "origin/dev" + } + } + } + } + }, + "e4807fbe173c": { + "baseRef": "origin/dev" + } + }, + "recording": { + "scenario": "sc-base-ref-worktree-hit", + "checkpoints": [ + { + "id": "repo-list-outstanding", + "observation": { + "sender": ["d33da78bedd6", "26accd69bc48"], + "payloads": ["cec763c8abc6", "594101d24d72"], + "settlements": { + "resolve": "9270aeb7d9c6" + }, + "state": "4dce743b400a", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["d33da78bedd6", "69d1fb735581"], + "payloads": ["cec763c8abc6", "594101d24d72"], + "settlements": { + "resolve": "576578948f60" + }, + "state": "e4807fbe173c", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-commit-message-cancel-rejected.json b/mobile/rpc-foundation/goldens/sc-commit-message-cancel-rejected.json new file mode 100644 index 00000000000..a9f618e2b54 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-commit-message-cancel-rejected.json @@ -0,0 +1,80 @@ +{ + "operation": "source-control.commit-message", + "family": "git.commit-message-ai", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "029ea2c16f05": { + "name": "git.cancelGenerateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.cancelGenerateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "677c1cb5e628": { + "name": "git.cancelGenerateCommitMessage#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.cancelGenerateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "a947768bc0ed": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + }, + "adb40821f3e2": { + "generated": "ungenerated" + } + }, + "recording": { + "scenario": "sc-commit-message-cancel-rejected", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["029ea2c16f05"], + "payloads": ["677c1cb5e628"], + "settlements": { + "cancel": "a947768bc0ed" + }, + "state": "adb40821f3e2", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-commit-message-canceled.json b/mobile/rpc-foundation/goldens/sc-commit-message-canceled.json new file mode 100644 index 00000000000..043d31da9d6 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-commit-message-canceled.json @@ -0,0 +1,147 @@ +{ + "operation": "source-control.commit-message", + "family": "git.commit-message-ai", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0aeb6552c58a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "canceled": true, + "error": "", + "success": false + } + } + } + }, + "6e5abe3439c9": { + "name": "git.cancelGenerateCommitMessage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.cancelGenerateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "71c27de39c72": { + "generated": { + "canceled": true, + "error": "No commit message generated", + "success": false + } + }, + "9971630c4d20": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "canceled": true, + "error": "No commit message generated", + "success": false + } + }, + "a30abf951ff2": { + "name": "git.cancelGenerateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.cancelGenerateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "internal", + "message": "late" + }, + "id": "frame-2", + "ok": false + } + } + }, + "a64074c2ba96": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "sc-commit-message-canceled", + "checkpoints": [ + { + "id": "generate-settled", + "observation": { + "sender": ["0aeb6552c58a"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "9971630c4d20" + }, + "state": "71c27de39c72", + "effects": [] + } + }, + { + "id": "cancel-settled", + "observation": { + "sender": ["0aeb6552c58a", "a30abf951ff2"], + "payloads": ["a64074c2ba96", "6e5abe3439c9"], + "settlements": { + "generate": "9971630c4d20", + "cancel": "eb79a9b3682a" + }, + "state": "71c27de39c72", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-commit-message-generated.json b/mobile/rpc-foundation/goldens/sc-commit-message-generated.json new file mode 100644 index 00000000000..8553ac2c8b8 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-commit-message-generated.json @@ -0,0 +1,129 @@ +{ + "operation": "source-control.commit-message", + "family": "git.commit-message-ai", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "1290c04bc26c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "message": "feat: recorded", + "success": true + } + }, + "3ef8a5f65bc8": { + "generated": { + "message": "feat: recorded", + "success": true + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "a09d0ada6684": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "a64074c2ba96": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "adb40821f3e2": { + "generated": "ungenerated" + } + }, + "recording": { + "scenario": "sc-commit-message-generated", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["125fbea5f50a"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "9270aeb7d9c6" + }, + "state": "adb40821f3e2", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["a09d0ada6684"], + "payloads": ["a64074c2ba96"], + "settlements": { + "generate": "1290c04bc26c" + }, + "state": "3ef8a5f65bc8", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-create-existing-review.json b/mobile/rpc-foundation/goldens/sc-create-existing-review.json new file mode 100644 index 00000000000..4f714babe7d --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-create-existing-review.json @@ -0,0 +1,139 @@ +{ + "operation": "source-control.hosted-review-create", + "family": "hostedReview.create-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "1617f98dc371": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Recorded title\",\"body\":\"Recorded body\",\"draft\":false}}" + }, + "2cc2895eb25e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "existing": true, + "number": 9, + "ok": true, + "url": "https://review.test/9" + } + }, + "3827fc206d36": { + "outcome": { + "existing": true, + "number": 9, + "ok": true, + "url": "https://review.test/9" + } + }, + "9fec416f759d": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 9, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "a6c47567c630": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":9}}" + }, + "fc66abdd58c9": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "Create pull request failed: already exists", + "existingReview": { + "number": 9, + "url": "https://review.test/9" + }, + "ok": false + } + } + } + } + }, + "recording": { + "scenario": "sc-create-existing-review", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["fc66abdd58c9", "9fec416f759d"], + "payloads": ["1617f98dc371", "a6c47567c630"], + "settlements": { + "create": "2cc2895eb25e" + }, + "state": "3827fc206d36", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-create-intent-stage-commit-push-create.json b/mobile/rpc-foundation/goldens/sc-create-intent-stage-commit-push-create.json new file mode 100644 index 00000000000..4334e60261f --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-create-intent-stage-commit-push-create.json @@ -0,0 +1,1094 @@ +{ + "operation": "source-control.create-intent", + "family": "hostedReview.create-intent", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "079e57b28866": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "blockedReason": "needs_push", + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "0a191e58baef": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-11\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Host title\",\"body\":\"Host body\",\"draft\":false}}" + }, + "125fbea5f50a": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "16f662c17969": { + "name": "git.status#4", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "21c1956cb4f7": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27e9d0778f22": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "success": true + } + } + } + }, + "2af3debae21a": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"feat: recorded\"}}" + }, + "2c3c06911cb2": { + "name": "git.status#4", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "319e2b2ccc22": { + "name": "git.bulkStage#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"git.bulkStage\",\"params\":{\"worktree\":\"id:repo42::/p\",\"filePaths\":[\"src/new.ts\"]}}" + }, + "368b0b9ce80a": { + "name": "progress", + "value": "staging" + }, + "43ccfe31d2a4": { + "outcome": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "4c9c8122480a": { + "name": "git.status#3", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "branch": "feature", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5975e0bdd4a4": { + "name": "progress", + "value": "creating_review" + }, + "5b46f52533a0": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "5b5a307c10d7": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-12\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "6a5c9570c542": { + "name": "progress", + "value": "generating_commit_message" + }, + "6df8e4961ee3": { + "name": "git.generateCommitMessage#1", + "args": [ + { + "name": "method", + "value": "git.generateCommitMessage" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "message": "feat: recorded", + "success": true + } + } + } + }, + "72b388fd3302": { + "outcome": "unrun" + }, + "7679f4e521d1": { + "name": "git.push#1", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "7778d4c43a58": { + "name": "progress", + "value": "committing" + }, + "788869e46db6": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "8302a20e080f": { + "name": "git.status#2", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "8b784bb9dff5": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "committed": true, + "ok": true, + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + }, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [], + "head": "def5678", + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + }, + "url": "https://review.test/5", + "warning": { + "$rpc": "undefined" + } + } + }, + "8ca8f03c0069": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "feat: recorded", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "98b13de38dae": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Host body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Host title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-11", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "9bc50e10f310": { + "name": "hostedReview.getCreationEligibility#2", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 0, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "not_found", + "title": "Host title" + } + } + } + }, + "a6f6cd5af9d1": { + "name": "git.status#2", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "ac748ef3fb83": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-12", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b87dea84b950": { + "name": "git.generateCommitMessage#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"git.generateCommitMessage\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c444aeacec59": { + "name": "git.status#3", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "c51356d4650a": { + "name": "git.bulkStage#1", + "args": [ + { + "name": "method", + "value": "git.bulkStage" + }, + { + "name": "params", + "value": { + "filePaths": ["src/new.ts"], + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c997e6a2a82a": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":1,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "de647ad73f93": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "ahead": 1, + "base": { + "$rpc": "null" + }, + "behind": 0, + "branch": "feature", + "hasUncommittedChanges": false, + "hasUpstream": true, + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eab004af0939": { + "name": "hostedReview.getCreationEligibility#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"hasUncommittedChanges\":false,\"hasUpstream\":true,\"ahead\":0,\"behind\":0,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + } + }, + "recording": { + "scenario": "sc-create-intent-stage-commit-push-create", + "checkpoints": [ + { + "id": "initial-status-pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [] + } + }, + { + "id": "stage-pending", + "observation": { + "sender": ["302b94359544", "21c1956cb4f7"], + "payloads": ["5e330d49c396", "319e2b2ccc22"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a"] + } + }, + { + "id": "generate-message-pending", + "observation": { + "sender": ["302b94359544", "c51356d4650a", "a6f6cd5af9d1", "125fbea5f50a"], + "payloads": ["5e330d49c396", "319e2b2ccc22", "8302a20e080f", "b87dea84b950"], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542"] + } + }, + { + "id": "commit-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "8ca8f03c0069" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "prefill-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "de647ad73f93" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58"] + } + }, + { + "id": "push-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "b7a56d89f615" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": ["368b0b9ce80a", "6a5c9570c542", "7778d4c43a58", "60421d882fd2"] + } + }, + { + "id": "create-pending", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "5b46f52533a0" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef" + ], + "settlements": { + "run": "9270aeb7d9c6" + }, + "state": "72b388fd3302", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "302b94359544", + "c51356d4650a", + "a6f6cd5af9d1", + "6df8e4961ee3", + "27e9d0778f22", + "4c9c8122480a", + "079e57b28866", + "788869e46db6", + "2c3c06911cb2", + "9bc50e10f310", + "98b13de38dae", + "ac748ef3fb83" + ], + "payloads": [ + "5e330d49c396", + "319e2b2ccc22", + "8302a20e080f", + "b87dea84b950", + "2af3debae21a", + "c444aeacec59", + "c997e6a2a82a", + "7679f4e521d1", + "16f662c17969", + "eab004af0939", + "0a191e58baef", + "5b5a307c10d7" + ], + "settlements": { + "run": "8b784bb9dff5" + }, + "state": "43ccfe31d2a4", + "effects": [ + "368b0b9ce80a", + "6a5c9570c542", + "7778d4c43a58", + "60421d882fd2", + "5975e0bdd4a4" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-create-link-failure-is-non-fatal.json b/mobile/rpc-foundation/goldens/sc-create-link-failure-is-non-fatal.json new file mode 100644 index 00000000000..4fa79747bdb --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-create-link-failure-is-non-fatal.json @@ -0,0 +1,137 @@ +{ + "operation": "source-control.hosted-review-create", + "family": "hostedReview.create-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "122ef8a1f0b9": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "1617f98dc371": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Recorded title\",\"body\":\"Recorded body\",\"draft\":false}}" + }, + "3ff86ed23cf9": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "linkError": "Failed to update linked review", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "7b353f33f66f": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "91f262b2079b": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "internal", + "message": "" + }, + "id": "frame-2", + "ok": false + } + } + }, + "e5dbe1f8903e": { + "outcome": { + "linkError": "Failed to update linked review", + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + }, + "recording": { + "scenario": "sc-create-link-failure-is-non-fatal", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["122ef8a1f0b9", "91f262b2079b"], + "payloads": ["1617f98dc371", "7b353f33f66f"], + "settlements": { + "create": "3ff86ed23cf9" + }, + "state": "e5dbe1f8903e", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-create-pushes-then-creates.json b/mobile/rpc-foundation/goldens/sc-create-pushes-then-creates.json new file mode 100644 index 00000000000..7731fd78fea --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-create-pushes-then-creates.json @@ -0,0 +1,298 @@ +{ + "operation": "source-control.hosted-review-create", + "family": "hostedReview.create-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "06a94a810e5f": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Recorded title\",\"body\":\"Recorded body\",\"draft\":false}}" + }, + "06e930bb7dd8": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"main\",\"linkedPR\":5}}" + }, + "3f946ad0279c": { + "outcome": "uncreated" + }, + "7037e9e29078": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + } + } + }, + "7c0cf8d696d8": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "95b1f2f379aa": { + "name": "git.push#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "9fca4a23f963": { + "outcome": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "a1f0c8bb5bcd": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a942a97a5d17": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "main", + "linkedPR": 5, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a95ae8a9ee57": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "number": 5, + "ok": true, + "url": "https://review.test/5" + } + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "f9869252c305": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + } + }, + "recording": { + "scenario": "sc-create-pushes-then-creates", + "checkpoints": [ + { + "id": "push-pending", + "observation": { + "sender": ["b7a56d89f615"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "create-pending", + "observation": { + "sender": ["f9869252c305", "a1f0c8bb5bcd"], + "payloads": ["95b1f2f379aa", "06a94a810e5f"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "link-pending", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "a942a97a5d17"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "9270aeb7d9c6" + }, + "state": "3f946ad0279c", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["f9869252c305", "7037e9e29078", "7c0cf8d696d8"], + "payloads": ["95b1f2f379aa", "06a94a810e5f", "06e930bb7dd8"], + "settlements": { + "create": "a95ae8a9ee57" + }, + "state": "9fca4a23f963", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-create-refused-empty-message.json b/mobile/rpc-foundation/goldens/sc-create-refused-empty-message.json new file mode 100644 index 00000000000..3367315375a --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-create-refused-empty-message.json @@ -0,0 +1,92 @@ +{ + "operation": "source-control.hosted-review-create", + "family": "hostedReview.create-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "1617f98dc371": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Recorded title\",\"body\":\"Recorded body\",\"draft\":false}}" + }, + "5b3abe5b6ee3": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "internal", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "d14a0dd639ad": { + "outcome": { + "error": "Failed to create pull request", + "ok": false + } + }, + "e12183bfd2c3": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Failed to create pull request", + "ok": false + } + } + }, + "recording": { + "scenario": "sc-create-refused-empty-message", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["5b3abe5b6ee3"], + "payloads": ["1617f98dc371"], + "settlements": { + "create": "e12183bfd2c3" + }, + "state": "d14a0dd639ad", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-create-rejected-empty-message.json b/mobile/rpc-foundation/goldens/sc-create-rejected-empty-message.json new file mode 100644 index 00000000000..7e4a85c7807 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-create-rejected-empty-message.json @@ -0,0 +1,89 @@ +{ + "operation": "source-control.hosted-review-create", + "family": "hostedReview.create-chain", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "1617f98dc371": { + "name": "hostedReview.create#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.create\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"provider\":\"github\",\"base\":\"main\",\"head\":\"feature\",\"title\":\"Recorded title\",\"body\":\"Recorded body\",\"draft\":false}}" + }, + "3c6a5a164e8a": { + "outcome": { + "error": "", + "ok": false + } + }, + "401c5b683797": { + "name": "hostedReview.create#1", + "args": [ + { + "name": "method", + "value": "hostedReview.create" + }, + { + "name": "params", + "value": { + "base": "main", + "body": "Recorded body", + "draft": false, + "head": "feature", + "provider": "github", + "repo": "id:repo42", + "title": "Recorded title", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "", + "isRpcDeliveryUnknown": true + } + } + }, + "fb4429083480": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "", + "ok": false + } + } + }, + "recording": { + "scenario": "sc-create-rejected-empty-message", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["401c5b683797"], + "payloads": ["1617f98dc371"], + "settlements": { + "create": "fb4429083480" + }, + "state": "3c6a5a164e8a", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-eligibility-fetched.json b/mobile/rpc-foundation/goldens/sc-eligibility-fetched.json new file mode 100644 index 00000000000..42479b8d881 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-eligibility-fetched.json @@ -0,0 +1,183 @@ +{ + "operation": "source-control.hosted-review-eligibility", + "family": "hostedReview.eligibility", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "24bd84c9fb40": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "gitlab", + "reviewLookupOutcome": "none", + "title": "Host title" + } + }, + "2cbc383a17fc": { + "eligibility": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "gitlab", + "reviewLookupOutcome": "none", + "title": "Host title" + }, + "prefill": "unresolved" + }, + "485a0942bda3": { + "eligibility": "unfetched", + "prefill": "unresolved" + }, + "899a024357b9": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "blockedReason": { + "$rpc": "null" + }, + "body": "Host body", + "canCreate": true, + "defaultBaseRef": "main", + "nextAction": { + "$rpc": "null" + }, + "provider": "gitlab", + "reviewLookupOutcome": "none", + "title": "Host title" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "cc09b6142ccb": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + }, + "e41e491351c2": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "sc-eligibility-fetched", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["e41e491351c2"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "9270aeb7d9c6" + }, + "state": "485a0942bda3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["899a024357b9"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "fetch": "24bd84c9fb40" + }, + "state": "2cbc383a17fc", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-history-loaded.json b/mobile/rpc-foundation/goldens/sc-history-loaded.json new file mode 100644 index 00000000000..eb98e12f8bb --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-history-loaded.json @@ -0,0 +1,179 @@ +{ + "operation": "source-control.git-history", + "family": "git.history-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "17bc1e177fe1": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "437d7f38d098": { + "rows": [ + { + "author": "dev", + "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parentId": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "relativeTime": "1h", + "shortId": "aaaaaaa", + "subject": "first" + }, + { + "author": "", + "id": "cccccccccccccccccccccccccccccccccccccccc", + "parentId": { + "$rpc": "null" + }, + "relativeTime": "", + "shortId": "ccccccc", + "subject": "(no commit message)" + } + ] + }, + "6b280ce22422": { + "name": "git.history#1", + "args": [ + { + "name": "method", + "value": "git.history" + }, + { + "name": "params", + "value": { + "limit": 50, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "items": [ + { + "author": "dev", + "displayId": "aaaaaaa", + "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parentIds": ["bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"], + "subject": "first", + "timestamp": 1767222000000 + }, + { + "id": "cccccccccccccccccccccccccccccccccccccccc", + "parentIds": [], + "subject": "", + "timestamp": { + "$rpc": "null" + } + } + ] + } + } + } + }, + "7d520ecb92ad": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": [ + { + "author": "dev", + "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "parentId": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "relativeTime": "1h", + "shortId": "aaaaaaa", + "subject": "first" + }, + { + "author": "", + "id": "cccccccccccccccccccccccccccccccccccccccc", + "parentId": { + "$rpc": "null" + }, + "relativeTime": "", + "shortId": "ccccccc", + "subject": "(no commit message)" + } + ] + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "d2ac5468a6f5": { + "name": "git.history#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.history\",\"params\":{\"worktree\":\"id:repo42::/p\",\"limit\":50}}" + }, + "ef169a494b41": { + "rows": "unloaded" + } + }, + "recording": { + "scenario": "sc-history-loaded", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["17bc1e177fe1"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "ef169a494b41", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["6b280ce22422"], + "payloads": ["d2ac5468a6f5"], + "settlements": { + "load": "7d520ecb92ad" + }, + "state": "437d7f38d098", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-pr-link-hosted-review.json b/mobile/rpc-foundation/goldens/sc-pr-link-hosted-review.json new file mode 100644 index 00000000000..c81fb9f324c --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-pr-link-hosted-review.json @@ -0,0 +1,126 @@ +{ + "operation": "source-control.pr-link", + "family": "worktree.review-link", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "1852c739af4f": { + "linkedPR": "unread", + "outcome": { + "ok": true + } + }, + "1a42edf0b52f": { + "name": "worktree.set#2", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": { + "$rpc": "null" + }, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "9da958eddaa9": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "baseRef": "origin/release", + "linkedGitLabMR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "c2ccaf58540c": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"baseRef\":\"origin/release\",\"linkedGitLabMR\":12}}" + }, + "e3b095dbc61d": { + "name": "worktree.set#2", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"linkedPR\":null}}" + }, + "fbc958e4d46e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true + } + } + }, + "recording": { + "scenario": "sc-pr-link-hosted-review", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["9da958eddaa9", "1a42edf0b52f"], + "payloads": ["c2ccaf58540c", "e3b095dbc61d"], + "settlements": { + "link-review": "fbc958e4d46e", + "unlink": "fbc958e4d46e" + }, + "state": "1852c739af4f", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-pr-link-read.json b/mobile/rpc-foundation/goldens/sc-pr-link-read.json new file mode 100644 index 00000000000..350c6ff06b9 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-pr-link-read.json @@ -0,0 +1,145 @@ +{ + "operation": "source-control.pr-link", + "family": "worktree.review-link", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "17ab8ab0a9f4": { + "linkedPR": 7, + "outcome": "unlinked" + }, + "6f0c2307a94d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": 7 + }, + "ae6ed2aa18df": { + "linkedPR": { + "$rpc": "null" + }, + "outcome": "unlinked" + }, + "cec763c8abc6": { + "name": "worktree.show#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.show\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "e29f6962cb3e": { + "name": "worktree.show#2", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "$rpc": "null" + } + } + } + }, + "e499e48f3fce": { + "name": "worktree.show#2", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.show\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "ee20a1dc39e7": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "null" + } + }, + "f2580933d0e2": { + "name": "worktree.show#1", + "args": [ + { + "name": "method", + "value": "worktree.show" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "worktree": { + "linkedPR": 7 + } + } + } + } + } + }, + "recording": { + "scenario": "sc-pr-link-read", + "checkpoints": [ + { + "id": "read-settled", + "observation": { + "sender": ["f2580933d0e2"], + "payloads": ["cec763c8abc6"], + "settlements": { + "read": "6f0c2307a94d" + }, + "state": "17ab8ab0a9f4", + "effects": [] + } + }, + { + "id": "null-result-settled", + "observation": { + "sender": ["f2580933d0e2", "e29f6962cb3e"], + "payloads": ["cec763c8abc6", "e499e48f3fce"], + "settlements": { + "read": "6f0c2307a94d", + "read-again": "ee20a1dc39e7" + }, + "state": "ae6ed2aa18df", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-pr-link-set.json b/mobile/rpc-foundation/goldens/sc-pr-link-set.json new file mode 100644 index 00000000000..891b55fa1cb --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-pr-link-set.json @@ -0,0 +1,130 @@ +{ + "operation": "source-control.pr-link", + "family": "worktree.review-link", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "1852c739af4f": { + "linkedPR": "unread", + "outcome": { + "ok": true + } + }, + "2c746c8732cd": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "41bdce9de379": { + "linkedPR": "unread", + "outcome": "unlinked" + }, + "86441203344c": { + "name": "worktree.set#1", + "args": [ + { + "name": "method", + "value": "worktree.set" + }, + { + "name": "params", + "value": { + "linkedPR": 12, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "c7ae0a3a6e6e": { + "name": "worktree.set#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.set\",\"params\":{\"worktree\":\"id:repo42::/p\",\"linkedPR\":12}}" + }, + "fbc958e4d46e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true + } + } + }, + "recording": { + "scenario": "sc-pr-link-set", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["2c746c8732cd"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "9270aeb7d9c6" + }, + "state": "41bdce9de379", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["86441203344c"], + "payloads": ["c7ae0a3a6e6e"], + "settlements": { + "link": "fbc958e4d46e" + }, + "state": "1852c739af4f", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-prefill-unavailable-on-refusal.json b/mobile/rpc-foundation/goldens/sc-prefill-unavailable-on-refusal.json new file mode 100644 index 00000000000..f56ad5b0719 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-prefill-unavailable-on-refusal.json @@ -0,0 +1,117 @@ +{ + "operation": "source-control.hosted-review-eligibility", + "family": "hostedReview.eligibility", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0710fc7e2b71": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "no eligibility" + }, + "id": "frame-1", + "ok": false + } + } + }, + "2f56274e5397": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "", + "canCreate": false, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "unavailable", + "title": "Recorded title" + } + }, + "77a5a5f8b111": { + "eligibility": "unfetched", + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "", + "canCreate": false, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "unavailable", + "title": "Recorded title" + } + }, + "cc09b6142ccb": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + } + }, + "recording": { + "scenario": "sc-prefill-unavailable-on-refusal", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["0710fc7e2b71"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "prefill": "2f56274e5397" + }, + "state": "77a5a5f8b111", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-prefill-unavailable-on-rejection.json b/mobile/rpc-foundation/goldens/sc-prefill-unavailable-on-rejection.json new file mode 100644 index 00000000000..408c547a998 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-prefill-unavailable-on-rejection.json @@ -0,0 +1,114 @@ +{ + "operation": "source-control.hosted-review-eligibility", + "family": "hostedReview.eligibility", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "2f56274e5397": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "", + "canCreate": false, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "unavailable", + "title": "Recorded title" + } + }, + "77a5a5f8b111": { + "eligibility": "unfetched", + "prefill": { + "base": "main", + "blockedReason": { + "$rpc": "null" + }, + "body": "", + "canCreate": false, + "nextAction": { + "$rpc": "null" + }, + "provider": "github", + "reviewLookupOutcome": "unavailable", + "title": "Recorded title" + } + }, + "7fb1231fd64d": { + "name": "hostedReview.getCreationEligibility#1", + "args": [ + { + "name": "method", + "value": "hostedReview.getCreationEligibility" + }, + { + "name": "params", + "value": { + "base": { + "$rpc": "null" + }, + "branch": "feature", + "linkedGitHubPR": { + "$rpc": "null" + }, + "linkedGitLabMR": { + "$rpc": "null" + }, + "repo": "id:repo42", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "cc09b6142ccb": { + "name": "hostedReview.getCreationEligibility#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"hostedReview.getCreationEligibility\",\"params\":{\"repo\":\"id:repo42\",\"worktree\":\"id:repo42::/p\",\"branch\":\"feature\",\"base\":null,\"linkedGitHubPR\":null,\"linkedGitLabMR\":null}}" + } + }, + "recording": { + "scenario": "sc-prefill-unavailable-on-rejection", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["7fb1231fd64d"], + "payloads": ["cc09b6142ccb"], + "settlements": { + "prefill": "2f56274e5397" + }, + "state": "77a5a5f8b111", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-prerequisite-force-with-lease.json b/mobile/rpc-foundation/goldens/sc-prerequisite-force-with-lease.json new file mode 100644 index 00000000000..3cd399e645c --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-prerequisite-force-with-lease.json @@ -0,0 +1,89 @@ +{ + "operation": "source-control.remote-prerequisite", + "family": "git.remote-prerequisite", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "00e8a3bac22f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true, + "ran": true + } + }, + "0fe2eb2410a4": { + "outcome": { + "ok": true, + "ran": true + } + }, + "3d5bc718d103": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "forceWithLease": true, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "ef6c20bf075b": { + "name": "git.push#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\",\"forceWithLease\":true}}" + }, + "f664712ae7ac": { + "name": "progress", + "value": "force_pushing" + } + }, + "recording": { + "scenario": "sc-prerequisite-force-with-lease", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["3d5bc718d103"], + "payloads": ["ef6c20bf075b"], + "settlements": { + "apply": "00e8a3bac22f" + }, + "state": "0fe2eb2410a4", + "effects": ["f664712ae7ac"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-prerequisite-publish.json b/mobile/rpc-foundation/goldens/sc-prerequisite-publish.json new file mode 100644 index 00000000000..f89f6433c9f --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-prerequisite-publish.json @@ -0,0 +1,89 @@ +{ + "operation": "source-control.remote-prerequisite", + "family": "git.remote-prerequisite", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "00e8a3bac22f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true, + "ran": true + } + }, + "0fe2eb2410a4": { + "outcome": { + "ok": true, + "ran": true + } + }, + "387442f96b16": { + "name": "git.push#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\",\"publish\":true}}" + }, + "b12e1ce5068c": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "publish": true, + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + }, + "dc538c734db2": { + "name": "progress", + "value": "publishing" + } + }, + "recording": { + "scenario": "sc-prerequisite-publish", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["b12e1ce5068c"], + "payloads": ["387442f96b16"], + "settlements": { + "apply": "00e8a3bac22f" + }, + "state": "0fe2eb2410a4", + "effects": ["dc538c734db2"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-prerequisite-push.json b/mobile/rpc-foundation/goldens/sc-prerequisite-push.json new file mode 100644 index 00000000000..92ae6703db9 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-prerequisite-push.json @@ -0,0 +1,132 @@ +{ + "operation": "source-control.remote-prerequisite", + "family": "git.remote-prerequisite", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "00e8a3bac22f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true, + "ran": true + } + }, + "0fe2eb2410a4": { + "outcome": { + "ok": true, + "ran": true + } + }, + "60421d882fd2": { + "name": "progress", + "value": "pushing" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "95b1f2f379aa": { + "name": "git.push#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.push\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "b7a56d89f615": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "cf19981c2114": { + "outcome": "unapplied" + }, + "f9869252c305": { + "name": "git.push#1", + "args": [ + { + "name": "method", + "value": "git.push" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "ok": true + } + } + } + } + }, + "recording": { + "scenario": "sc-prerequisite-push", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["b7a56d89f615"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "9270aeb7d9c6" + }, + "state": "cf19981c2114", + "effects": ["60421d882fd2"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["f9869252c305"], + "payloads": ["95b1f2f379aa"], + "settlements": { + "apply": "00e8a3bac22f" + }, + "state": "0fe2eb2410a4", + "effects": ["60421d882fd2"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-prerequisite-skipped.json b/mobile/rpc-foundation/goldens/sc-prerequisite-skipped.json new file mode 100644 index 00000000000..5ceb47f5809 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-prerequisite-skipped.json @@ -0,0 +1,47 @@ +{ + "operation": "source-control.remote-prerequisite", + "family": "git.remote-prerequisite", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "69f421c50546": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true, + "ran": false + } + }, + "cede2a5d35c8": { + "outcome": { + "ok": true, + "ran": false + } + } + }, + "recording": { + "scenario": "sc-prerequisite-skipped", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": [], + "payloads": [], + "settlements": { + "apply": "69f421c50546" + }, + "state": "cede2a5d35c8", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-reveal-first-poll.json b/mobile/rpc-foundation/goldens/sc-reveal-first-poll.json new file mode 100644 index 00000000000..509d1be2e70 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-reveal-first-poll.json @@ -0,0 +1,222 @@ +{ + "operation": "source-control.session-diff-reveal", + "family": "session.tab-reveal", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0f9f4df04699": { + "name": "session.tabs.activate#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.activate\",\"params\":{\"worktree\":\"id:repo42::/p\",\"tabId\":\"tab-1\",\"notifyClients\":false,\"navigation\":\"caller\",\"intent\":\"user\"}}" + }, + "5fbe284a7387": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "60ef11dd407d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": "revealed" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "92b5192ed75d": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "tabs": [ + { + "id": "tab-term", + "type": "terminal" + }, + { + "id": "tab-other", + "mode": "diff", + "relativePath": "src/other.ts", + "type": "file" + }, + { + "diffSource": "unstaged", + "id": "tab-1", + "mode": "diff", + "relativePath": "src/app.ts", + "type": "file" + } + ] + } + } + } + }, + "bb3b4ee6b927": { + "name": "session.tabs.activate#1", + "args": [ + { + "name": "method", + "value": "session.tabs.activate" + }, + { + "name": "params", + "value": { + "intent": "user", + "navigation": "caller", + "notifyClients": false, + "tabId": "tab-1", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "activeTabId": "tab-1" + } + } + } + }, + "bde782b3557a": { + "result": "revealed" + }, + "c7a157cde28d": { + "result": "unrevealed" + }, + "eb116b4d99bb": { + "name": "session.tabs.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.list\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "f884811cfa05": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "sc-reveal-first-poll", + "checkpoints": [ + { + "id": "list-pending", + "observation": { + "sender": ["f884811cfa05"], + "payloads": ["eb116b4d99bb"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "activate-pending", + "observation": { + "sender": ["92b5192ed75d", "5fbe284a7387"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["92b5192ed75d", "bb3b4ee6b927"], + "payloads": ["eb116b4d99bb", "0f9f4df04699"], + "settlements": { + "reveal": "60ef11dd407d" + }, + "state": "bde782b3557a", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-reveal-timeout.json b/mobile/rpc-foundation/goldens/sc-reveal-timeout.json new file mode 100644 index 00000000000..780aab803c4 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-reveal-timeout.json @@ -0,0 +1,211 @@ +{ + "operation": "source-control.session-diff-reveal", + "family": "session.tab-reveal", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "3dbdccea1da9": { + "name": "session.tabs.list#3", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 900, + "settledAt": 900, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "tabs": [ + { + "id": 1 + } + ] + } + } + } + }, + "421eab74382e": { + "name": "session.tabs.list#2", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.list\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9ae795d19e6a": { + "name": "session.tabs.list#3", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.list\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "a24b101a6ab8": { + "name": "session.tabs.list#4", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 1800, + "settledAt": 1800, + "error": { + "category": "Error", + "message": "transport failure", + "isRpcDeliveryUnknown": true + } + } + }, + "b636d34122fd": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 1800, + "value": "timeout" + }, + "b78420b7aa2c": { + "result": "timeout" + }, + "b85e7c9343ce": { + "name": "session.tabs.list#2", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 300, + "settledAt": 300, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "tabs": [] + } + } + } + }, + "bea2cb9fbfb3": { + "name": "session.tabs.list#1", + "args": [ + { + "name": "method", + "value": "session.tabs.list" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "no tabs" + }, + "id": "frame-1", + "ok": false + } + } + }, + "c7a157cde28d": { + "result": "unrevealed" + }, + "e1859439e0b8": { + "name": "session.tabs.list#4", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.list\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "eb116b4d99bb": { + "name": "session.tabs.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"session.tabs.list\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + } + }, + "recording": { + "scenario": "sc-reveal-timeout", + "checkpoints": [ + { + "id": "second-poll-empty", + "observation": { + "sender": ["bea2cb9fbfb3", "b85e7c9343ce"], + "payloads": ["eb116b4d99bb", "421eab74382e"], + "settlements": { + "reveal": "9270aeb7d9c6" + }, + "state": "c7a157cde28d", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["bea2cb9fbfb3", "b85e7c9343ce", "3dbdccea1da9", "a24b101a6ab8"], + "payloads": ["eb116b4d99bb", "421eab74382e", "9ae795d19e6a", "e1859439e0b8"], + "settlements": { + "reveal": "b636d34122fd" + }, + "state": "b78420b7aa2c", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-review-commit-inner-failure.json b/mobile/rpc-foundation/goldens/sc-review-commit-inner-failure.json new file mode 100644 index 00000000000..8ea6d83bb2c --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-review-commit-inner-failure.json @@ -0,0 +1,87 @@ +{ + "operation": "source-control.review-git-preparation", + "family": "git.review-preparation", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "88185276c233": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "nothing staged", + "ok": false + } + }, + "a96ee3f6fd5e": { + "committed": { + "error": "nothing staged", + "ok": false + }, + "status": "unread" + }, + "e9c816eee026": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"recorded message\"}}" + }, + "f29b710be334": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "recorded message", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "error": "nothing staged", + "success": false + } + } + } + } + }, + "recording": { + "scenario": "sc-review-commit-inner-failure", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["f29b710be334"], + "payloads": ["e9c816eee026"], + "settlements": { + "commit": "88185276c233" + }, + "state": "a96ee3f6fd5e", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-review-commit-refused-empty-message.json b/mobile/rpc-foundation/goldens/sc-review-commit-refused-empty-message.json new file mode 100644 index 00000000000..e430c438492 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-review-commit-refused-empty-message.json @@ -0,0 +1,87 @@ +{ + "operation": "source-control.review-git-preparation", + "family": "git.review-preparation", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "45f289a0f3ae": { + "committed": { + "error": "Commit failed", + "ok": false + }, + "status": "unread" + }, + "9dac5d637ed4": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "Commit failed", + "ok": false + } + }, + "a130dfa9b176": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "recorded message", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "internal", + "message": "" + }, + "id": "frame-1", + "ok": false + } + } + }, + "e9c816eee026": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"recorded message\"}}" + } + }, + "recording": { + "scenario": "sc-review-commit-refused-empty-message", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["a130dfa9b176"], + "payloads": ["e9c816eee026"], + "settlements": { + "commit": "9dac5d637ed4" + }, + "state": "45f289a0f3ae", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-review-commit-rejected.json b/mobile/rpc-foundation/goldens/sc-review-commit-rejected.json new file mode 100644 index 00000000000..336769ebb6c --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-review-commit-rejected.json @@ -0,0 +1,84 @@ +{ + "operation": "source-control.review-git-preparation", + "family": "git.review-preparation", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "01bab795ab1e": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "recorded message", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "465d78c22406": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": "connection lost", + "ok": false + } + }, + "7c923ba16626": { + "committed": { + "error": "connection lost", + "ok": false + }, + "status": "unread" + }, + "e9c816eee026": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"recorded message\"}}" + } + }, + "recording": { + "scenario": "sc-review-commit-rejected", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["01bab795ab1e"], + "payloads": ["e9c816eee026"], + "settlements": { + "commit": "465d78c22406" + }, + "state": "7c923ba16626", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-review-commit.json b/mobile/rpc-foundation/goldens/sc-review-commit.json new file mode 100644 index 00000000000..86d07d748e2 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-review-commit.json @@ -0,0 +1,85 @@ +{ + "operation": "source-control.review-git-preparation", + "family": "git.review-preparation", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "17bb401abe83": { + "committed": { + "ok": true + }, + "status": "unread" + }, + "3553e2d27023": { + "name": "git.commit#1", + "args": [ + { + "name": "method", + "value": "git.commit" + }, + { + "name": "params", + "value": { + "message": "recorded message", + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "commit": "abc1234", + "success": true + } + } + } + }, + "e9c816eee026": { + "name": "git.commit#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.commit\",\"params\":{\"worktree\":\"id:repo42::/p\",\"message\":\"recorded message\"}}" + }, + "fbc958e4d46e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true + } + } + }, + "recording": { + "scenario": "sc-review-commit", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["3553e2d27023"], + "payloads": ["e9c816eee026"], + "settlements": { + "commit": "fbc958e4d46e" + }, + "state": "17bb401abe83", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-review-status-entries-not-array.json b/mobile/rpc-foundation/goldens/sc-review-status-entries-not-array.json new file mode 100644 index 00000000000..0203f9b7787 --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-review-status-entries-not-array.json @@ -0,0 +1,90 @@ +{ + "operation": "source-control.review-git-preparation", + "family": "git.review-preparation", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "6cfd467eb392": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": "nope" + } + } + } + }, + "6decf368b25a": { + "committed": "uncommitted", + "status": { + "ok": true, + "status": { + "$rpc": "null" + } + } + }, + "da676cfabd9b": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true, + "status": { + "$rpc": "null" + } + } + } + }, + "recording": { + "scenario": "sc-review-status-entries-not-array", + "checkpoints": [ + { + "id": "settled", + "observation": { + "sender": ["6cfd467eb392"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "da676cfabd9b" + }, + "state": "6decf368b25a", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/sc-review-status-normalized.json b/mobile/rpc-foundation/goldens/sc-review-status-normalized.json new file mode 100644 index 00000000000..b0797df544e --- /dev/null +++ b/mobile/rpc-foundation/goldens/sc-review-status-normalized.json @@ -0,0 +1,280 @@ +{ + "operation": "source-control.review-git-preparation", + "family": "git.review-preparation", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0278e0f0d6cf": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "302b94359544": { + "name": "git.status#1", + "args": [ + { + "name": "method", + "value": "git.status" + }, + { + "name": "params", + "value": { + "worktree": "id:repo42::/p" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "branch": "feature", + "entries": [ + { + "area": "staged", + "path": "src/app.ts", + "status": "modified" + }, + { + "area": "untracked", + "path": "src/new.ts", + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + } + }, + "5e330d49c396": { + "name": "git.status#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"git.status\",\"params\":{\"worktree\":\"id:repo42::/p\"}}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "95c2e5ca74fc": { + "committed": "uncommitted", + "status": { + "ok": true, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + }, + "ac07554f62ad": { + "committed": "uncommitted", + "status": "unread" + }, + "c7ee072b3a0f": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "ok": true, + "status": { + "branch": "feature", + "conflictOperation": "unknown", + "entries": [ + { + "added": { + "$rpc": "undefined" + }, + "area": "staged", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/app.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "modified" + }, + { + "added": { + "$rpc": "undefined" + }, + "area": "untracked", + "conflictKind": { + "$rpc": "undefined" + }, + "conflictStatus": { + "$rpc": "undefined" + }, + "conflictStatusSource": { + "$rpc": "undefined" + }, + "oldPath": { + "$rpc": "undefined" + }, + "path": "src/new.ts", + "removed": { + "$rpc": "undefined" + }, + "status": "untracked" + } + ], + "head": "abc1234", + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "behindCommitsArePatchEquivalent": { + "$rpc": "undefined" + }, + "hasConfiguredPushTarget": { + "$rpc": "undefined" + }, + "hasUpstream": true, + "upstreamName": { + "$rpc": "undefined" + } + } + } + } + } + }, + "recording": { + "scenario": "sc-review-status-normalized", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["0278e0f0d6cf"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "9270aeb7d9c6" + }, + "state": "ac07554f62ad", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["302b94359544"], + "payloads": ["5e330d49c396"], + "settlements": { + "status": "c7ee072b3a0f" + }, + "state": "95c2e5ca74fc", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/schedules-b3.json b/mobile/rpc-foundation/goldens/schedules-b3.json new file mode 100644 index 00000000000..7ae2b532e89 --- /dev/null +++ b/mobile/rpc-foundation/goldens/schedules-b3.json @@ -0,0 +1,742 @@ +{ + "operation": "linear.issue-detail", + "family": "linear-detail-barrier", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "034a83431f03": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "issue refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "1474fb688cbe": { + "name": "detailError", + "value": "RPC interrupted by connection migration" + }, + "1696f2f90218": { + "name": "detailError", + "value": "comments transport error" + }, + "210ccd4fdd98": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: linear.getIssue", + "isRpcDeliveryUnknown": true + } + } + }, + "24f3de063dfd": { + "error": "linear.issueComments#1 rejected", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "38c4607fc51a": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "3b01c25bcd45": { + "name": "detailError", + "value": "" + }, + "3cb9a384ce0e": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "42903545f0f8": { + "error": "comments transport error", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "49b0ba2659b8": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: linear.issueComments", + "isRpcDeliveryUnknown": true + } + } + }, + "4e7c4654b51d": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "comments transport error", + "isRpcDeliveryUnknown": true + } + } + }, + "538ca4176a52": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "58b60616b373": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "71339c38458c": { + "name": "detailError", + "value": "Request timed out: linear.getIssue" + }, + "780aaf1d97be": { + "error": "", + "loading": true, + "payload": { + "$rpc": "null" + } + }, + "7d21147e56c1": { + "name": "detailLoading", + "value": true + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "88573133f7d5": { + "error": "RPC interrupted by connection migration", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "91a1c8142e23": { + "name": "detailLoading", + "value": false + }, + "99253302972b": { + "name": "detailError", + "value": "linear.getIssue#1 rejected" + }, + "a778223fed77": { + "error": "linear.getIssue#1 rejected", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "bb215a1eb59b": { + "name": "linear.getIssue#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"linear.getIssue\",\"params\":{\"id\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "c5688e7e3b01": { + "name": "linear.issueComments#1", + "args": [ + { + "name": "method", + "value": "linear.issueComments" + }, + { + "name": "params", + "value": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "linear.issueComments#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "cc1d7d1a2a81": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "linear.getIssue#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "d0761d28e078": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "d40dd5c93d21": { + "error": "Connection lost", + "loading": false, + "payload": { + "$rpc": "null" + } + }, + "dbf8961c1dc1": { + "name": "detailError", + "value": "linear.issueComments#1 rejected" + }, + "e7f73629d075": { + "name": "linear.issueComments#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.issueComments\",\"params\":{\"issueId\":\"issue-1\",\"workspaceId\":\"linear-workspace\"}}" + }, + "ea91918fd5a8": { + "name": "detailError", + "value": "Connection lost" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "fc4ce176400a": { + "name": "linear.getIssue#1", + "args": [ + { + "name": "method", + "value": "linear.getIssue" + }, + { + "name": "params", + "value": { + "id": "issue-1", + "workspaceId": "linear-workspace" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "fc6d55bc97ed": { + "error": "Request timed out: linear.getIssue", + "loading": false, + "payload": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "schedules-b3", + "checkpoints": [ + { + "id": "b3.forward:sibling-pending", + "observation": { + "sender": ["034a83431f03", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "780aaf1d97be", + "effects": ["7d341b2cb946", "3b01c25bcd45", "7d21147e56c1"] + } + }, + { + "id": "b3.forward:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.reverse:sibling-pending", + "observation": { + "sender": ["fc4ce176400a", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.reverse:settled", + "observation": { + "sender": ["034a83431f03", "4e7c4654b51d"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "42903545f0f8", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1696f2f90218", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.both-reject-forward:sibling-pending", + "observation": { + "sender": ["cc1d7d1a2a81", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "a778223fed77", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "99253302972b", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.both-reject-forward:settled", + "observation": { + "sender": ["cc1d7d1a2a81", "c5688e7e3b01"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "a778223fed77", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "99253302972b", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.both-reject-reverse:sibling-pending", + "observation": { + "sender": ["fc4ce176400a", "c5688e7e3b01"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "24f3de063dfd", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "dbf8961c1dc1", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.both-reject-reverse:settled", + "observation": { + "sender": ["cc1d7d1a2a81", "c5688e7e3b01"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "24f3de063dfd", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "dbf8961c1dc1", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.reject-peer-pending:sibling-pending", + "observation": { + "sender": ["cc1d7d1a2a81", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "a778223fed77", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "99253302972b", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.reject-peer-pending:settled", + "observation": { + "sender": ["cc1d7d1a2a81", "3cb9a384ce0e"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "a778223fed77", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "99253302972b", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.timeout:settled", + "observation": { + "sender": ["210ccd4fdd98", "49b0ba2659b8"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "fc6d55bc97ed", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "71339c38458c", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.disconnect:settled", + "observation": { + "sender": ["538ca4176a52", "58b60616b373"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "disconnect": "eb79a9b3682a" + }, + "state": "d40dd5c93d21", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "ea91918fd5a8", + "91a1c8142e23" + ] + } + }, + { + "id": "b3.client-cutover:settled", + "observation": { + "sender": ["d0761d28e078", "38c4607fc51a"], + "payloads": ["bb215a1eb59b", "e7f73629d075"], + "settlements": { + "mount": "eb79a9b3682a", + "cutover": "eb79a9b3682a" + }, + "state": "88573133f7d5", + "effects": [ + "7d341b2cb946", + "3b01c25bcd45", + "7d21147e56c1", + "1474fb688cbe", + "91a1c8142e23" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/schedules-settings-home-providers-fulfilled.json b/mobile/rpc-foundation/goldens/schedules-settings-home-providers-fulfilled.json new file mode 100644 index 00000000000..dc48a1055db --- /dev/null +++ b/mobile/rpc-foundation/goldens/schedules-settings-home-providers-fulfilled.json @@ -0,0 +1,746 @@ +{ + "operation": "settings.home-providers", + "family": "settings.home-providers", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "1081ce76cc68": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: linear.status", + "isRpcDeliveryUnknown": true + } + } + }, + "1bd19e364296": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "24054d93a95f": { + "name": "providers", + "value": { + "host-1": ["github"] + } + }, + "27e92f99be15": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "349f2cb31004": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "35e8371ce4fb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "39bd7fcad0c4": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "preflight.check#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "42701bb4f394": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "44136fa355b3": {}, + "569aea0064f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "66bc794cca63": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "79b8c1b0d1d1": { + "host-1": ["github"] + }, + "7dadf370725c": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "a3c30fa6fdda": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "a6413e8380e3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "a670b07e746e": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: settings.get", + "isRpcDeliveryUnknown": true + } + } + }, + "b19b64f388f3": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "c66ef8a30d8e": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: preflight.check", + "isRpcDeliveryUnknown": true + } + } + }, + "da2c3b49481f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e9ec9196aad8": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ed19b8675a80": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "f2c5b522b90a": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings.get#1 rejected", + "isRpcDeliveryUnknown": true + } + } + } + }, + "recording": { + "scenario": "schedules-settings-home-providers-fulfilled", + "checkpoints": [ + { + "id": "settings-home-providers-fulfilled.forward:sibling-pending", + "observation": { + "sender": ["7dadf370725c", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-home-providers-fulfilled.forward:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.reverse:sibling-pending", + "observation": { + "sender": ["da2c3b49481f", "349f2cb31004", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-home-providers-fulfilled.reverse:settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.both-reject-forward:sibling-pending", + "observation": { + "sender": ["f2c5b522b90a", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.both-reject-forward:settled", + "observation": { + "sender": ["f2c5b522b90a", "39bd7fcad0c4", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.both-reject-reverse:sibling-pending", + "observation": { + "sender": ["da2c3b49481f", "39bd7fcad0c4", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.both-reject-reverse:settled", + "observation": { + "sender": ["f2c5b522b90a", "39bd7fcad0c4", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.reject-peer-pending:sibling-pending", + "observation": { + "sender": ["f2c5b522b90a", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.reject-peer-pending:settled", + "observation": { + "sender": ["f2c5b522b90a", "66bc794cca63", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.timeout:settled", + "observation": { + "sender": ["a670b07e746e", "c66ef8a30d8e", "1081ce76cc68"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.disconnect:settled", + "observation": { + "sender": ["b19b64f388f3", "1bd19e364296", "a6413e8380e3"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a", + "disconnect": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "settings-home-providers-fulfilled.client-cutover:settled", + "observation": { + "sender": ["35e8371ce4fb", "e9ec9196aad8", "ed19b8675a80"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a", + "cutover": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/schedules-settings-new-tab-ssh.json b/mobile/rpc-foundation/goldens/schedules-settings-new-tab-ssh.json new file mode 100644 index 00000000000..a0596c4ed5b --- /dev/null +++ b/mobile/rpc-foundation/goldens/schedules-settings-new-tab-ssh.json @@ -0,0 +1,686 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "06eff8247d02": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "27b09a2898b9": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "430eff79721f": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "preflight.detectRemoteAgents#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "44136fa355b3": {}, + "554718767f5a": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": [] + } + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "6d0209806267": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + }, + "7e9a4c0e6082": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings.get#1 rejected", + "isRpcDeliveryUnknown": true + } + }, + "7fc945a92540": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: settings.get", + "isRpcDeliveryUnknown": true + } + } + }, + "8277c8a13a15": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: settings.get", + "isRpcDeliveryUnknown": true + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9c4be43625f0": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": ["codex", "claude"] + } + } + }, + "af6903aed166": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "b27c85677730": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": [ + { + "agent": "codex", + "label": "Codex" + }, + { + "agent": "claude", + "label": "Claude" + } + ] + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "c9c9e154c7a4": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: preflight.detectRemoteAgents", + "isRpcDeliveryUnknown": true + } + } + }, + "d041d5155ed5": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings.get#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "d0ea965edca4": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "d58a51553d50": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + }, + "e465a7e0746d": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "preflight.detectRemoteAgents#1 rejected", + "isRpcDeliveryUnknown": true + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f03117831a8e": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "schedules-settings-new-tab-ssh", + "checkpoints": [ + { + "id": "settings-new-tab-ssh.forward:sibling-pending", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "f03117831a8e"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.forward:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b27c85677730" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.reverse:sibling-pending", + "observation": { + "sender": ["bae1ab4f96f9", "090c88478661", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.reverse:settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b27c85677730" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.both-reject-forward:sibling-pending", + "observation": { + "sender": ["bae1ab4f96f9", "d041d5155ed5", "f03117831a8e"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "7e9a4c0e6082" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.both-reject-forward:settled", + "observation": { + "sender": ["bae1ab4f96f9", "d041d5155ed5", "430eff79721f"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "7e9a4c0e6082" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.both-reject-reverse:sibling-pending", + "observation": { + "sender": ["bae1ab4f96f9", "090c88478661", "430eff79721f"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "e465a7e0746d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.both-reject-reverse:settled", + "observation": { + "sender": ["bae1ab4f96f9", "d041d5155ed5", "430eff79721f"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "e465a7e0746d" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.reject-peer-pending:sibling-pending", + "observation": { + "sender": ["bae1ab4f96f9", "d041d5155ed5", "f03117831a8e"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "7e9a4c0e6082" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.reject-peer-pending:settled", + "observation": { + "sender": ["bae1ab4f96f9", "d041d5155ed5", "f03117831a8e"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "7e9a4c0e6082" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.timeout:settled", + "observation": { + "sender": ["bae1ab4f96f9", "7fc945a92540", "c9c9e154c7a4"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "8277c8a13a15" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.disconnect:settled", + "observation": { + "sender": ["bae1ab4f96f9", "af6903aed166", "27b09a2898b9"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "6d0209806267", + "disconnect": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-new-tab-ssh.client-cutover:settled", + "observation": { + "sender": ["bae1ab4f96f9", "06eff8247d02", "d0ea965edca4"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "d58a51553d50", + "cutover": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/schedules-settings-repo-metadata-fulfilled.json b/mobile/rpc-foundation/goldens/schedules-settings-repo-metadata-fulfilled.json new file mode 100644 index 00000000000..057b688d8a1 --- /dev/null +++ b/mobile/rpc-foundation/goldens/schedules-settings-repo-metadata-fulfilled.json @@ -0,0 +1,881 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "06eff8247d02": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "0728e73758d7": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: host.platform", + "isRpcDeliveryUnknown": true + } + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "1ae9065ebcdf": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "host.platform#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "1de50f3b4aac": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": { + "$rpc": "null" + }, + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "1e048843e9d3": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "7fc945a92540": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: settings.get", + "isRpcDeliveryUnknown": true + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9acf4d7a0ba1": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a7ffdd83bc7d": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "af6903aed166": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "c7f150c7a054": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 30000, + "value": { + "$rpc": "undefined" + } + }, + "d041d5155ed5": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings.get#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "e24ce14b72e9": { + "name": "hostPlatform", + "value": { + "$rpc": "null" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + } + }, + "recording": { + "scenario": "schedules-settings-repo-metadata-fulfilled", + "checkpoints": [ + { + "id": "settings-repo-metadata-fulfilled.forward:sibling-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.forward:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.reverse:sibling-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.reverse:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.both-reject-forward:sibling-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "d041d5155ed5", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.both-reject-forward:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "d041d5155ed5", "1ae9065ebcdf"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.both-reject-reverse:sibling-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "1ae9065ebcdf"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.both-reject-reverse:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "d041d5155ed5", "1ae9065ebcdf"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.reject-peer-pending:sibling-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "d041d5155ed5", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.reject-peer-pending:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "d041d5155ed5", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settings-repo-metadata-fulfilled.reject-peer-pending:cleanup", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "d041d5155ed5", "9acf4d7a0ba1"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "6134b73f18d0", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.timeout:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "7fc945a92540", "0728e73758d7"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "c7f150c7a054" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.disconnect:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "af6903aed166", "1e048843e9d3"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a", + "disconnect": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + }, + { + "id": "settings-repo-metadata-fulfilled.client-cutover:settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "06eff8247d02", "a7ffdd83bc7d"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a", + "cutover": "eb79a9b3682a" + }, + "state": "1de50f3b4aac", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "e24ce14b72e9" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/schedules-settings-resume-metadata-fulfilled.json b/mobile/rpc-foundation/goldens/schedules-settings-resume-metadata-fulfilled.json new file mode 100644 index 00000000000..a840f5cf913 --- /dev/null +++ b/mobile/rpc-foundation/goldens/schedules-settings-resume-metadata-fulfilled.json @@ -0,0 +1,896 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0447fbb835ad": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "06854b6b4cde": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: worktree.ps", + "isRpcDeliveryUnknown": true + } + } + }, + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "18d27f5a5ff4": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3c70da5d6d8e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "worktrees": [] + } + }, + "3f2c65bf0ed7": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: settings.get", + "isRpcDeliveryUnknown": true + } + } + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "4b6b81dc7f0f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "4f5070e045c9": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "worktree.ps#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6b08ce6b4d6b": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "6f9cdbcc6cd1": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "a1dcd0e4691a": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings.get#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "b5f966ccb50c": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 30000, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "$rpc": "null" + }, + "worktrees": { + "$rpc": "null" + } + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "d1d9a1ad6fcf": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "$rpc": "null" + }, + "worktrees": { + "$rpc": "null" + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + } + }, + "recording": { + "scenario": "schedules-settings-resume-metadata-fulfilled", + "checkpoints": [ + { + "id": "settings-resume-metadata-fulfilled.forward:sibling-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.forward:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.reverse:sibling-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.reverse:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.both-reject-forward:sibling-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "a1dcd0e4691a", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.both-reject-forward:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "a1dcd0e4691a", + "4f5070e045c9" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "d1d9a1ad6fcf" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.both-reject-reverse:sibling-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "4f5070e045c9" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.both-reject-reverse:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "a1dcd0e4691a", + "4f5070e045c9" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "d1d9a1ad6fcf" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.reject-peer-pending:sibling-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "a1dcd0e4691a", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.reject-peer-pending:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "a1dcd0e4691a", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.timeout:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f2c65bf0ed7", + "06854b6b4cde" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "b5f966ccb50c" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.disconnect:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "4b6b81dc7f0f", + "6b08ce6b4d6b" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "d1d9a1ad6fcf", + "disconnect": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settings-resume-metadata-fulfilled.client-cutover:settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "0447fbb835ad", + "6f9cdbcc6cd1" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "d1d9a1ad6fcf", + "cutover": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/schedules-settings-task-hydration-fulfilled.json b/mobile/rpc-foundation/goldens/schedules-settings-task-hydration-fulfilled.json new file mode 100644 index 00000000000..417c0067e98 --- /dev/null +++ b/mobile/rpc-foundation/goldens/schedules-settings-task-hydration-fulfilled.json @@ -0,0 +1,1995 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "06eff8247d02": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "149b4ddbd6c6": { + "name": "error", + "value": "RPC interrupted by connection migration" + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "47d40c6fb90c": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "5851c3d3d9e0": { + "name": "error", + "value": "ui.get#1 rejected" + }, + "586159bf259e": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "58c52d8b7c76": { + "hydrated": true, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "68aa55411b15": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "70c65c0f7a8e": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: ui.get", + "isRpcDeliveryUnknown": true + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "7fc945a92540": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: settings.get", + "isRpcDeliveryUnknown": true + } + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "8f30512a5135": { + "name": "error", + "value": "Request timed out: settings.get" + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "a1b99265507f": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "ae1d901c204f": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "af6903aed166": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "ba4739591371": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: linear.status", + "isRpcDeliveryUnknown": true + } + } + }, + "baafd23158c8": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: preflight.check", + "isRpcDeliveryUnknown": true + } + } + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "cdeb94d60934": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d041d5155ed5": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings.get#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "d36257ed8dd7": { + "name": "error", + "value": "settings.get#1 rejected" + }, + "d42b1a5610cf": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "ui.get#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "d705fce957e8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fa7ce9018e50": { + "name": "error", + "value": "Connection lost" + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "schedules-settings-task-hydration-fulfilled", + "checkpoints": [ + { + "id": "settings-task-hydration-fulfilled.forward:sibling-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.forward:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.reverse:sibling-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "1f7d21cec906", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.reverse:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.both-reject-forward:sibling-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d041d5155ed5", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "d36257ed8dd7", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.both-reject-forward:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d041d5155ed5", + "d42b1a5610cf", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "d36257ed8dd7", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.both-reject-reverse:sibling-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "d42b1a5610cf", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "5851c3d3d9e0", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.both-reject-reverse:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d041d5155ed5", + "d42b1a5610cf", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "5851c3d3d9e0", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.reject-peer-pending:sibling-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d041d5155ed5", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "d36257ed8dd7", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.reject-peer-pending:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d041d5155ed5", + "5fbdd64c75bc", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "d36257ed8dd7", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.timeout:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "7fc945a92540", + "70c65c0f7a8e", + "baafd23158c8", + "ba4739591371" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "8f30512a5135", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.disconnect:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "af6903aed166", + "68aa55411b15", + "586159bf259e", + "ae1d901c204f" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "disconnect": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "fa7ce9018e50", + "bbbd4bc0a4ef" + ] + } + }, + { + "id": "settings-task-hydration-fulfilled.client-cutover:settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "06eff8247d02", + "a1b99265507f", + "47d40c6fb90c", + "cdeb94d60934" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a", + "cutover": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "149b4ddbd6c6", + "bbbd4bc0a4ef" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/schedules-settings-workspace-context-fulfilled.json b/mobile/rpc-foundation/goldens/schedules-settings-workspace-context-fulfilled.json new file mode 100644 index 00000000000..c94c51bc451 --- /dev/null +++ b/mobile/rpc-foundation/goldens/schedules-settings-workspace-context-fulfilled.json @@ -0,0 +1,921 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "06eff8247d02": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2a7485a88169": { + "providers": ["github"], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "3a834cb85dd8": { + "providers": ["github"], + "settings": { + "$rpc": "null" + }, + "trust": {} + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "47d40c6fb90c": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "586159bf259e": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "68aa55411b15": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "70c65c0f7a8e": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: ui.get", + "isRpcDeliveryUnknown": true + } + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "7fc945a92540": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: settings.get", + "isRpcDeliveryUnknown": true + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "a1b99265507f": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "ae1d901c204f": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "af6903aed166": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "Connection lost", + "isRpcDeliveryUnknown": true + } + } + }, + "ba4739591371": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: linear.status", + "isRpcDeliveryUnknown": true + } + } + }, + "baafd23158c8": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 30000, + "error": { + "category": "Error", + "message": "Request timed out: preflight.check", + "isRpcDeliveryUnknown": true + } + } + }, + "cdeb94d60934": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "LogicalClientCutoverError", + "message": "RPC interrupted by connection migration", + "isRpcDeliveryUnknown": true, + "cause": { + "category": "Error", + "message": "Connection closed", + "isRpcDeliveryUnknown": true + } + } + } + }, + "d041d5155ed5": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings.get#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "d42b1a5610cf": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "ui.get#1 rejected", + "isRpcDeliveryUnknown": true + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + } + }, + "recording": { + "scenario": "schedules-settings-workspace-context-fulfilled", + "checkpoints": [ + { + "id": "settings-workspace-context-fulfilled.forward:sibling-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "822040616fbb", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.forward:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.reverse:sibling-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.reverse:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.both-reject-forward:sibling-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "d041d5155ed5", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.both-reject-forward:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "d041d5155ed5", "d42b1a5610cf"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.both-reject-reverse:sibling-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "d42b1a5610cf"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.both-reject-reverse:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "d041d5155ed5", "d42b1a5610cf"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.reject-peer-pending:sibling-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "d041d5155ed5", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.reject-peer-pending:settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "d041d5155ed5", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.timeout:settled", + "observation": { + "sender": ["baafd23158c8", "ba4739591371", "7fc945a92540", "70c65c0f7a8e"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.disconnect:settled", + "observation": { + "sender": ["586159bf259e", "ae1d901c204f", "af6903aed166", "68aa55411b15"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "disconnect": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + }, + { + "id": "settings-workspace-context-fulfilled.client-cutover:settled", + "observation": { + "sender": ["47d40c6fb90c", "cdeb94d60934", "06eff8247d02", "a1b99265507f"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a", + "cutover": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-bot-overrides-fulfilled.json b/mobile/rpc-foundation/goldens/settings-bot-overrides-fulfilled.json new file mode 100644 index 00000000000..b09ca2cf30d --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-bot-overrides-fulfilled.json @@ -0,0 +1,122 @@ +{ + "operation": "settings.bot-overrides", + "family": "settings.bot-overrides", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "4f53cda18c2b": [], + "7ca23c4c946b": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "d52c8e96e222": ["bot-user"], + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-bot-overrides-fulfilled", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-bot-overrides-refresh-refused.json b/mobile/rpc-foundation/goldens/settings-bot-overrides-refresh-refused.json new file mode 100644 index 00000000000..998b1f243de --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-bot-overrides-refresh-refused.json @@ -0,0 +1,211 @@ +{ + "operation": "settings.bot-overrides", + "family": "settings.bot-overrides", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "466ddfe469f9": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "Settings refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "4f53cda18c2b": [], + "7ad8a0996352": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "7ca23c4c946b": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "8f6fe9452bda": { + "name": "settings.get#2", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "d52c8e96e222": ["bot-user"], + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-bot-overrides-refresh-refused", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + }, + { + "id": "refresh-pending", + "observation": { + "sender": ["7ca23c4c946b", "7ad8a0996352"], + "payloads": ["7ddcb1852b39", "8f6fe9452bda"], + "settlements": { + "mount": "eb79a9b3682a", + "refresh": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + }, + { + "id": "refused-retains-overrides", + "observation": { + "sender": ["7ca23c4c946b", "466ddfe469f9"], + "payloads": ["7ddcb1852b39", "8f6fe9452bda"], + "settlements": { + "mount": "eb79a9b3682a", + "refresh": "eb79a9b3682a" + }, + "state": "d52c8e96e222", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-bot-overrides-refused.json b/mobile/rpc-foundation/goldens/settings-bot-overrides-refused.json new file mode 100644 index 00000000000..948f3d3a3e5 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-bot-overrides-refused.json @@ -0,0 +1,116 @@ +{ + "operation": "settings.bot-overrides", + "family": "settings.bot-overrides", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "4f53cda18c2b": [], + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "d6140b218abd": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-bot-overrides-refused", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["d6140b218abd"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-bot-overrides-transport-error.json b/mobile/rpc-foundation/goldens/settings-bot-overrides-transport-error.json new file mode 100644 index 00000000000..14c653fbd73 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-bot-overrides-transport-error.json @@ -0,0 +1,113 @@ +{ + "operation": "settings.bot-overrides", + "family": "settings.bot-overrides", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "10aeb294c268": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "4f53cda18c2b": [], + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-bot-overrides-transport-error", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["10aeb294c268"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "4f53cda18c2b", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-home-coalesced.json b/mobile/rpc-foundation/goldens/settings-home-coalesced.json new file mode 100644 index 00000000000..25a79b32d1d --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-home-coalesced.json @@ -0,0 +1,614 @@ +{ + "operation": "settings.home-providers", + "family": "settings.home-providers", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "0241b27b279c": { + "name": "settings.get#3", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "03f34ede1161": { + "name": "linear.status#3", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "078b082b9b55": { + "name": "linear.status#2", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "13028e692551": { + "name": "preflight.check#2", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "24054d93a95f": { + "name": "providers", + "value": { + "host-1": ["github"] + } + }, + "27e92f99be15": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "349f2cb31004": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "42701bb4f394": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "44136fa355b3": {}, + "4449b6ee7004": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "4b0d092afb83": { + "name": "preflight.check#3", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "569aea0064f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "66bc794cca63": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6e5114787f24": { + "name": "preflight.check#2", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "79b8c1b0d1d1": { + "host-1": ["github"] + }, + "7aff9e987a6a": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "7dadf370725c": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "847430ffa968": { + "name": "linear.status#2", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "86bdff55323d": { + "name": "preflight.check#3", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "a3c30fa6fdda": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "cdaf45e54941": { + "name": "linear.status#2", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "d6ea1d4a146a": { + "name": "preflight.check#2", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "da2c3b49481f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e2311f932df2": { + "name": "settings.get#2", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ec73eca27964": { + "name": "settings.get#3", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f196a3b238ee": { + "name": "linear.status#3", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + } + }, + "recording": { + "scenario": "settings-home-coalesced", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["da2c3b49481f", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a", + "overlapping-load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "7dadf370725c", + "349f2cb31004", + "a3c30fa6fdda", + "7aff9e987a6a", + "6e5114787f24", + "cdaf45e54941" + ], + "payloads": [ + "7ddcb1852b39", + "42701bb4f394", + "27e92f99be15", + "e2311f932df2", + "13028e692551", + "847430ffa968" + ], + "settlements": { + "load": "eb79a9b3682a", + "overlapping-load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "follow-up-settled", + "observation": { + "sender": [ + "7dadf370725c", + "349f2cb31004", + "a3c30fa6fdda", + "4449b6ee7004", + "d6ea1d4a146a", + "078b082b9b55" + ], + "payloads": [ + "7ddcb1852b39", + "42701bb4f394", + "27e92f99be15", + "e2311f932df2", + "13028e692551", + "847430ffa968" + ], + "settlements": { + "load": "eb79a9b3682a", + "overlapping-load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f", "24054d93a95f"] + } + }, + { + "id": "third-query", + "observation": { + "sender": [ + "7dadf370725c", + "349f2cb31004", + "a3c30fa6fdda", + "4449b6ee7004", + "d6ea1d4a146a", + "078b082b9b55", + "0241b27b279c", + "4b0d092afb83", + "03f34ede1161" + ], + "payloads": [ + "7ddcb1852b39", + "42701bb4f394", + "27e92f99be15", + "e2311f932df2", + "13028e692551", + "847430ffa968", + "ec73eca27964", + "86bdff55323d", + "f196a3b238ee" + ], + "settlements": { + "load": "eb79a9b3682a", + "overlapping-load": "eb79a9b3682a", + "third-load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f", "24054d93a95f"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-home-providers-fulfilled.json b/mobile/rpc-foundation/goldens/settings-home-providers-fulfilled.json new file mode 100644 index 00000000000..78875f4d390 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-home-providers-fulfilled.json @@ -0,0 +1,256 @@ +{ + "operation": "settings.home-providers", + "family": "settings.home-providers", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "24054d93a95f": { + "name": "providers", + "value": { + "host-1": ["github"] + } + }, + "27e92f99be15": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "349f2cb31004": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "42701bb4f394": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "44136fa355b3": {}, + "569aea0064f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "66bc794cca63": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "79b8c1b0d1d1": { + "host-1": ["github"] + }, + "7dadf370725c": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "a3c30fa6fdda": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "da2c3b49481f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-home-providers-fulfilled", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["da2c3b49481f", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-home-providers-refuse-after-data.json b/mobile/rpc-foundation/goldens/settings-home-providers-refuse-after-data.json new file mode 100644 index 00000000000..338286ccbf7 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-home-providers-refuse-after-data.json @@ -0,0 +1,511 @@ +{ + "operation": "settings.home-providers", + "family": "settings.home-providers", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "078b082b9b55": { + "name": "linear.status#2", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "13028e692551": { + "name": "preflight.check#2", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "24054d93a95f": { + "name": "providers", + "value": { + "host-1": ["github"] + } + }, + "27e92f99be15": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "349f2cb31004": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "40379a0cf3dd": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-4", + "ok": false + } + } + }, + "42701bb4f394": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "44136fa355b3": {}, + "569aea0064f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "66bc794cca63": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6e5114787f24": { + "name": "preflight.check#2", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "79b8c1b0d1d1": { + "host-1": ["github"] + }, + "7aff9e987a6a": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "7dadf370725c": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "847430ffa968": { + "name": "linear.status#2", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "a3c30fa6fdda": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "cdaf45e54941": { + "name": "linear.status#2", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "d6ea1d4a146a": { + "name": "preflight.check#2", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "da2c3b49481f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "e2311f932df2": { + "name": "settings.get#2", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-home-providers-refuse-after-data", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["da2c3b49481f", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "data-present", + "observation": { + "sender": ["7dadf370725c", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "refresh-pending", + "observation": { + "sender": [ + "7dadf370725c", + "349f2cb31004", + "a3c30fa6fdda", + "7aff9e987a6a", + "6e5114787f24", + "cdaf45e54941" + ], + "payloads": [ + "7ddcb1852b39", + "42701bb4f394", + "27e92f99be15", + "e2311f932df2", + "13028e692551", + "847430ffa968" + ], + "settlements": { + "load": "eb79a9b3682a", + "reload": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + }, + { + "id": "refused-after-data", + "observation": { + "sender": [ + "7dadf370725c", + "349f2cb31004", + "a3c30fa6fdda", + "40379a0cf3dd", + "d6ea1d4a146a", + "078b082b9b55" + ], + "payloads": [ + "7ddcb1852b39", + "42701bb4f394", + "27e92f99be15", + "e2311f932df2", + "13028e692551", + "847430ffa968" + ], + "settlements": { + "load": "eb79a9b3682a", + "reload": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f", "24054d93a95f"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-home-providers-refused.json b/mobile/rpc-foundation/goldens/settings-home-providers-refused.json new file mode 100644 index 00000000000..b09870dddbb --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-home-providers-refused.json @@ -0,0 +1,251 @@ +{ + "operation": "settings.home-providers", + "family": "settings.home-providers", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "24054d93a95f": { + "name": "providers", + "value": { + "host-1": ["github"] + } + }, + "27e92f99be15": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "2f02be854c04": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "349f2cb31004": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "42701bb4f394": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "44136fa355b3": {}, + "569aea0064f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "66bc794cca63": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "79b8c1b0d1d1": { + "host-1": ["github"] + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "a3c30fa6fdda": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "da2c3b49481f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-home-providers-refused", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["da2c3b49481f", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["2f02be854c04", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-home-providers-transport-error.json b/mobile/rpc-foundation/goldens/settings-home-providers-transport-error.json new file mode 100644 index 00000000000..21844890384 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-home-providers-transport-error.json @@ -0,0 +1,248 @@ +{ + "operation": "settings.home-providers", + "family": "settings.home-providers", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "163d57ce469e": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "24054d93a95f": { + "name": "providers", + "value": { + "host-1": ["github"] + } + }, + "27e92f99be15": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "349f2cb31004": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "42701bb4f394": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "44136fa355b3": {}, + "569aea0064f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "66bc794cca63": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "79b8c1b0d1d1": { + "host-1": ["github"] + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "a3c30fa6fdda": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "da2c3b49481f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-home-providers-transport-error", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["da2c3b49481f", "66bc794cca63", "569aea0064f4"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["163d57ce469e", "349f2cb31004", "a3c30fa6fdda"], + "payloads": ["7ddcb1852b39", "42701bb4f394", "27e92f99be15"], + "settlements": { + "load": "eb79a9b3682a" + }, + "state": "79b8c1b0d1d1", + "effects": ["24054d93a95f"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-new-tab-refused.json b/mobile/rpc-foundation/goldens/settings-new-tab-refused.json new file mode 100644 index 00000000000..362c5b957a2 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-new-tab-refused.json @@ -0,0 +1,224 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "68155c1eb584": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9c4be43625f0": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": ["codex", "claude"] + } + } + }, + "b5553341aa32": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings refused", + "isRpcDeliveryUnknown": false + } + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + } + }, + "recording": { + "scenario": "settings-new-tab-refused", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["bae1ab4f96f9", "68155c1eb584", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b5553341aa32" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-new-tab-ssh.json b/mobile/rpc-foundation/goldens/settings-new-tab-ssh.json new file mode 100644 index 00000000000..9f2e02cf282 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-new-tab-ssh.json @@ -0,0 +1,231 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "554718767f5a": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": [] + } + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9c4be43625f0": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": ["codex", "claude"] + } + } + }, + "b27c85677730": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": [ + { + "agent": "codex", + "label": "Codex" + }, + { + "agent": "claude", + "label": "Claude" + } + ] + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + } + }, + "recording": { + "scenario": "settings-new-tab-ssh", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["bae1ab4f96f9", "554718767f5a", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "b27c85677730" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-new-tab-transport-error.json b/mobile/rpc-foundation/goldens/settings-new-tab-transport-error.json new file mode 100644 index 00000000000..0bd5db38fc4 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-new-tab-transport-error.json @@ -0,0 +1,221 @@ +{ + "operation": "settings.new-tab-agents", + "family": "settings-agent-read", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "10aeb294c268": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "26accd69bc48": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "618234017ab2": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "9c4be43625f0": { + "name": "preflight.detectRemoteAgents#1", + "args": [ + { + "name": "method", + "value": "preflight.detectRemoteAgents" + }, + { + "name": "params", + "value": { + "connectionId": "ssh-1" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": ["codex", "claude"] + } + } + }, + "b69a18178af8": { + "name": "preflight.detectRemoteAgents#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.detectRemoteAgents\",\"params\":{\"connectionId\":\"ssh-1\"}}" + }, + "bae1ab4f96f9": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "id": "repo-1" + } + ] + } + } + } + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + } + }, + "recording": { + "scenario": "settings-new-tab-transport-error", + "checkpoints": [ + { + "id": "pending", + "observation": { + "sender": ["26accd69bc48", "090c88478661"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc"], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["bae1ab4f96f9", "10aeb294c268", "9c4be43625f0"], + "payloads": ["6bdbf70bafa2", "eac54552d8bc", "b69a18178af8"], + "settlements": { + "load": "618234017ab2" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-repo-cache-expiry.json b/mobile/rpc-foundation/goldens/settings-repo-cache-expiry.json new file mode 100644 index 00000000000..c59b0444a5a --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-repo-cache-expiry.json @@ -0,0 +1,471 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "25793d7c00a5": { + "name": "repo.list#2", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "ab830a39e448": { + "name": "repo.list#2", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 60000 + } + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "ba8a19e3e2b1": { + "status": "pending", + "startedAt": 60000 + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f43afee17848": { + "status": "fulfilled", + "startedAt": 59000, + "settledAt": 59000, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + } + }, + "recording": { + "scenario": "settings-repo-cache-expiry", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "cache-hit", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a", + "cached-query": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "cache-warm", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a", + "cached-query": "eb79a9b3682a", + "warm-query": "f43afee17848" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "cache-expired", + "observation": { + "sender": [ + "b40605df86b7", + "f7539bb05693", + "822040616fbb", + "7f85f28c922e", + "ab830a39e448" + ], + "payloads": [ + "6bdbf70bafa2", + "2aac570a2011", + "4335d4b6568f", + "df7cbc246ac0", + "25793d7c00a5" + ], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a", + "cached-query": "eb79a9b3682a", + "warm-query": "f43afee17848", + "expired-query": "ba8a19e3e2b1" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-repo-metadata-fulfilled.json b/mobile/rpc-foundation/goldens/settings-repo-metadata-fulfilled.json new file mode 100644 index 00000000000..2ad0d736e54 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-repo-metadata-fulfilled.json @@ -0,0 +1,352 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + } + }, + "recording": { + "scenario": "settings-repo-metadata-fulfilled", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-repo-metadata-refuse-after-data.json b/mobile/rpc-foundation/goldens/settings-repo-metadata-refuse-after-data.json new file mode 100644 index 00000000000..abc8bf40330 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-repo-metadata-refuse-after-data.json @@ -0,0 +1,642 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "02f9384f5305": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-7", + "ok": false + } + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "25793d7c00a5": { + "name": "repo.list#2", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "3fc2a1b54e13": { + "name": "settings.get#2", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6441235a1b38": { + "name": "ssh.listTargetSummaries#2", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7b3a5fc49e55": { + "name": "host.platform#2", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "940445cd9bd1": { + "name": "repo.list#2", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "a2a51f870c81": { + "name": "host.platform#2", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "c6d210e4939c": { + "name": "repo.list#2", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + }, + "f81341806cd3": { + "name": "ssh.listTargetSummaries#2", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + } + }, + "recording": { + "scenario": "settings-repo-metadata-refuse-after-data", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "data-present", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "822040616fbb", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "refresh-pending", + "observation": { + "sender": [ + "b40605df86b7", + "f7539bb05693", + "822040616fbb", + "7f85f28c922e", + "c6d210e4939c" + ], + "payloads": [ + "6bdbf70bafa2", + "2aac570a2011", + "4335d4b6568f", + "df7cbc246ac0", + "25793d7c00a5" + ], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a", + "reload": "9270aeb7d9c6" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + }, + { + "id": "refused-after-data", + "observation": { + "sender": [ + "b40605df86b7", + "f7539bb05693", + "822040616fbb", + "7f85f28c922e", + "940445cd9bd1", + "6441235a1b38", + "02f9384f5305", + "a2a51f870c81" + ], + "payloads": [ + "6bdbf70bafa2", + "2aac570a2011", + "4335d4b6568f", + "df7cbc246ac0", + "25793d7c00a5", + "f81341806cd3", + "3fc2a1b54e13", + "7b3a5fc49e55" + ], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a", + "reload": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f", + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-repo-metadata-refused.json b/mobile/rpc-foundation/goldens/settings-repo-metadata-refused.json new file mode 100644 index 00000000000..c98c25b2a45 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-repo-metadata-refused.json @@ -0,0 +1,347 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "c4360222a04e": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + } + }, + "recording": { + "scenario": "settings-repo-metadata-refused", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "c4360222a04e", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-repo-metadata-single-host.json b/mobile/rpc-foundation/goldens/settings-repo-metadata-single-host.json new file mode 100644 index 00000000000..2e01d9e1fbe --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-repo-metadata-single-host.json @@ -0,0 +1,129 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "2bd489a9fa29": { + "repoColorsByName": [ + ["Remote", "#f97316"], + ["Remote folder", "#ec4899"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "ssh:ssh-1"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Remote", "repo-1"], + ["Remote folder", "repo-2"] + ] + }, + "330bbbce8c90": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "ssh:ssh-1"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "63fc2c031079": { + "name": "repoIdsByName", + "value": [ + ["Remote", "repo-1"], + ["Remote folder", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "6c85f114767d": { + "name": "repoColorsByName", + "value": [ + ["Remote", "#f97316"], + ["Remote folder", "#ec4899"] + ] + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f4531cb1cb86": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote folder", + "id": "repo-2" + } + ] + } + } + } + } + }, + "recording": { + "scenario": "settings-repo-metadata-single-host", + "checkpoints": [ + { + "id": "single-host-without-label-lookups", + "observation": { + "sender": ["f4531cb1cb86"], + "payloads": ["6bdbf70bafa2"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "2bd489a9fa29", + "effects": ["6c85f114767d", "d228b095cad2", "63fc2c031079", "330bbbce8c90"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-repo-metadata-transport-error.json b/mobile/rpc-foundation/goldens/settings-repo-metadata-transport-error.json new file mode 100644 index 00000000000..f609f422ddc --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-repo-metadata-transport-error.json @@ -0,0 +1,344 @@ +{ + "operation": "settings.repo-metadata", + "family": "settings.repo-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02449e890487": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "071880b671a1": { + "hostLabelById": [["ssh:ssh-1", "SSH"]], + "hostPlatform": "linux", + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "10aeb294c268": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "2aac570a2011": { + "name": "ssh.listTargetSummaries#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"ssh.listTargetSummaries\"}" + }, + "388d7275af5f": { + "name": "hostPlatform", + "value": "linux" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "6134b73f18d0": { + "repoColorsByName": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ], + "repoHostIdByRepoId": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ], + "repoIconsByName": [], + "repoIdsByName": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "7d956f17cf24": { + "name": "repoColorsByName", + "value": [ + ["Local", "#6366f1"], + ["Remote", "#f97316"] + ] + }, + "7f85f28c922e": { + "name": "host.platform#1", + "args": [ + { + "name": "method", + "value": "host.platform" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "platform": "linux" + } + } + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "a4830eb5b420": { + "name": "hostLabelById", + "value": [["ssh:ssh-1", "SSH"]] + }, + "a95587e993a9": { + "name": "repoIdsByName", + "value": [ + ["Local", "repo-1"], + ["Remote", "repo-2"] + ] + }, + "b40605df86b7": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [ + { + "connectionId": { + "$rpc": "null" + }, + "displayName": "Local", + "id": "repo-1" + }, + { + "connectionId": "ssh-1", + "displayName": "Remote", + "id": "repo-2" + } + ] + } + } + } + }, + "d228b095cad2": { + "name": "repoIconsByName", + "value": [] + }, + "d6a308f7b0ff": { + "name": "repoHostIdByRepoId", + "value": [ + ["repo-1", "local"], + ["repo-2", "ssh:ssh-1"] + ] + }, + "df7cbc246ac0": { + "name": "host.platform#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"host.platform\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f7539bb05693": { + "name": "ssh.listTargetSummaries#1", + "args": [ + { + "name": "method", + "value": "ssh.listTargetSummaries" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + } + } + }, + "recording": { + "scenario": "settings-repo-metadata-transport-error", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "090c88478661", "02449e890487"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "9270aeb7d9c6" + }, + "state": "6134b73f18d0", + "effects": ["7d956f17cf24", "d228b095cad2", "a95587e993a9", "d6a308f7b0ff"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["b40605df86b7", "f7539bb05693", "10aeb294c268", "7f85f28c922e"], + "payloads": ["6bdbf70bafa2", "2aac570a2011", "4335d4b6568f", "df7cbc246ac0"], + "settlements": { + "mount": "eb79a9b3682a", + "load": "eb79a9b3682a" + }, + "state": "071880b671a1", + "effects": [ + "7d956f17cf24", + "d228b095cad2", + "a95587e993a9", + "d6a308f7b0ff", + "a4830eb5b420", + "388d7275af5f" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-resume-metadata-fulfilled.json b/mobile/rpc-foundation/goldens/settings-resume-metadata-fulfilled.json new file mode 100644 index 00000000000..f759c38ef00 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-resume-metadata-fulfilled.json @@ -0,0 +1,332 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "18d27f5a5ff4": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3c70da5d6d8e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "worktrees": [] + } + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + } + }, + "recording": { + "scenario": "settings-resume-metadata-fulfilled", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-resume-metadata-refuse-after-data.json b/mobile/rpc-foundation/goldens/settings-resume-metadata-refuse-after-data.json new file mode 100644 index 00000000000..f821dbfcbd9 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-resume-metadata-refuse-after-data.json @@ -0,0 +1,751 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "18d27f5a5ff4": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "230ea0045228": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "31a53ec32efa": { + "name": "projectGroup.list#2", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3c70da5d6d8e": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "worktrees": [] + } + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "46ecd49b2abe": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-9", + "ok": false + } + } + }, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "50c2305ef0d9": { + "name": "worktree.ps#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "50e357f2ca93": { + "name": "settings.get#2", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "59db06c656b6": { + "name": "repo.list#2", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6966c081ddb0": { + "name": "folderWorkspace.list#2", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-7", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "798651b41a43": { + "name": "repo.list#2", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "8c960b5b9772": { + "name": "folderWorkspace.list#2", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "92b727c611a8": { + "name": "worktree.ps#2", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "99bcc4a14ae3": { + "name": "repo.list#2", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "9a41b0dc52e4": { + "name": "projectGroup.list#2", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "aeee13be426f": { + "name": "projectGroup.list#2", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "b82176ce4d53": { + "name": "worktree.ps#2", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "worktrees": [] + } + } + } + }, + "bef8ec25072d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "$rpc": "null" + }, + "worktrees": [] + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + }, + "fd056a696c48": { + "name": "folderWorkspace.list#2", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + } + }, + "recording": { + "scenario": "settings-resume-metadata-refuse-after-data", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "data-present", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "3c70da5d6d8e" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "refresh-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504", + "99bcc4a14ae3", + "fd056a696c48", + "9a41b0dc52e4", + "230ea0045228", + "92b727c611a8" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096", + "798651b41a43", + "8c960b5b9772", + "aeee13be426f", + "50e357f2ca93", + "50c2305ef0d9" + ], + "settlements": { + "load": "3c70da5d6d8e", + "reload": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "refused-after-data", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "18d27f5a5ff4", + "f11be1e3e504", + "59db06c656b6", + "6966c081ddb0", + "31a53ec32efa", + "46ecd49b2abe", + "b82176ce4d53" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096", + "798651b41a43", + "8c960b5b9772", + "aeee13be426f", + "50e357f2ca93", + "50c2305ef0d9" + ], + "settlements": { + "load": "3c70da5d6d8e", + "reload": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-resume-metadata-refused.json b/mobile/rpc-foundation/goldens/settings-resume-metadata-refused.json new file mode 100644 index 00000000000..33f1ab3a526 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-resume-metadata-refused.json @@ -0,0 +1,323 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "bef8ec25072d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "$rpc": "null" + }, + "worktrees": [] + } + }, + "bfa9008c3994": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-4", + "ok": false + } + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + } + }, + "recording": { + "scenario": "settings-resume-metadata-refused", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "bfa9008c3994", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-resume-metadata-transport-error.json b/mobile/rpc-foundation/goldens/settings-resume-metadata-transport-error.json new file mode 100644 index 00000000000..a1a288f7ed4 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-resume-metadata-transport-error.json @@ -0,0 +1,320 @@ +{ + "operation": "settings.resume-metadata", + "family": "settings.resume-metadata", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "14a657727096": { + "name": "worktree.ps#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"worktree.ps\",\"params\":{\"limit\":10000,\"supportsWorktreeVisibilitySourceDefaults\":true}}" + }, + "1e08ef8dfeae": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "37aefcdc3665": { + "name": "folderWorkspace.list#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"folderWorkspace.list\"}" + }, + "3f303df2ad9f": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "44136fa355b3": {}, + "49b164f9bbd1": { + "name": "projectGroup.list#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"projectGroup.list\"}" + }, + "658e0bc6b0fc": { + "name": "folderWorkspace.list#1", + "args": [ + { + "name": "method", + "value": "folderWorkspace.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + } + }, + "6bdbf70bafa2": { + "name": "repo.list#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"repo.list\"}" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "96b29793602c": { + "name": "projectGroup.list#1", + "args": [ + { + "name": "method", + "value": "projectGroup.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "groups": [] + } + } + } + }, + "bef8ec25072d": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "folderWorkspaces": [], + "projectGroups": [], + "repos": [], + "settings": { + "$rpc": "null" + }, + "worktrees": [] + } + }, + "c0d3de96d82a": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "cde27afd4f31": { + "name": "repo.list#1", + "args": [ + { + "name": "method", + "value": "repo.list" + }, + { + "name": "params", + "value": { + "$rpc": "undefined" + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "repos": [] + } + } + } + }, + "e4b1a04958da": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "f11be1e3e504": { + "name": "worktree.ps#1", + "args": [ + { + "name": "method", + "value": "worktree.ps" + }, + { + "name": "params", + "value": { + "limit": 10000 + } + }, + { + "name": "options", + "value": { + "timeoutMs": 30000 + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "worktrees": [] + } + } + } + } + }, + "recording": { + "scenario": "settings-resume-metadata-transport-error", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "3f303df2ad9f", + "1e08ef8dfeae" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "9270aeb7d9c6" + }, + "state": "44136fa355b3", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "cde27afd4f31", + "658e0bc6b0fc", + "96b29793602c", + "c0d3de96d82a", + "f11be1e3e504" + ], + "payloads": [ + "6bdbf70bafa2", + "37aefcdc3665", + "49b164f9bbd1", + "e4b1a04958da", + "14a657727096" + ], + "settlements": { + "load": "bef8ec25072d" + }, + "state": "44136fa355b3", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-task-hydration-fulfilled.json b/mobile/rpc-foundation/goldens/settings-task-hydration-fulfilled.json new file mode 100644 index 00000000000..66fe1ba3511 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-task-hydration-fulfilled.json @@ -0,0 +1,767 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "58c52d8b7c76": { + "hydrated": true, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "d705fce957e8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "settings-task-hydration-fulfilled", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-task-hydration-refuse-after-data.json b/mobile/rpc-foundation/goldens/settings-task-hydration-refuse-after-data.json new file mode 100644 index 00000000000..0884fd84580 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-task-hydration-refuse-after-data.json @@ -0,0 +1,1361 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "02f9384f5305": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-7", + "ok": false + } + } + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "12ff4d4f8fc0": { + "name": "linear.status#2", + "json": "{\"id\":\"frame-10\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "1825a87a7ca8": { + "hydrated": false, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3986390fc039": { + "name": "linear.status#2", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-10", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "3f6cb9f1d075": { + "name": "status.get#2", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "3fc2a1b54e13": { + "name": "settings.get#2", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "58c52d8b7c76": { + "hydrated": true, + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "70c1fe53348e": { + "name": "status.get#2", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "7126d29ddcda": { + "name": "ui.get#2", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "84b10f34b617": { + "name": "ui.get#2", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "963a91c532c8": { + "hydrated": true, + "settings": {} + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "b9ce3caa927f": { + "name": "preflight.check#2", + "json": "{\"id\":\"frame-9\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "c9012709cb6f": { + "name": "preflight.check#2", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-9", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "c9c0513fdcb9": { + "name": "status.get#2", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "d705fce957e8": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "dae7907f03cc": { + "name": "runtimeTaskSettings", + "value": {} + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "settings-task-hydration-refuse-after-data", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "data-present", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "58c52d8b7c76", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + }, + { + "id": "refresh-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "c9c0513fdcb9" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e" + ], + "settlements": { + "mount": "eb79a9b3682a", + "revisit": "eb79a9b3682a" + }, + "state": "1825a87a7ca8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2" + ] + } + }, + { + "id": "refused-after-data", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "d705fce957e8", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314", + "3f6cb9f1d075", + "02f9384f5305", + "7126d29ddcda", + "c9012709cb6f", + "3986390fc039" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb", + "70c1fe53348e", + "3fc2a1b54e13", + "84b10f34b617", + "b9ce3caa927f", + "12ff4d4f8fc0" + ], + "settlements": { + "mount": "eb79a9b3682a", + "revisit": "eb79a9b3682a" + }, + "state": "963a91c532c8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "326e3f8f7e0b", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125", + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "dae7907f03cc", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-task-hydration-refused.json b/mobile/rpc-foundation/goldens/settings-task-hydration-refused.json new file mode 100644 index 00000000000..87a0cc045cb --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-task-hydration-refused.json @@ -0,0 +1,750 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "02d5832df83d": { + "name": "query", + "value": "is:issue is:open" + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1410db92f7e5": { + "name": "linearTeams", + "value": [] + }, + "16f398d67267": { + "name": "linearConnected", + "value": false + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "45d50e768fcc": { + "name": "githubPreset", + "value": "issues" + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "4cc1535f7ccf": { + "name": "githubProjectHiddenFieldIdsByView", + "value": {} + }, + "4efedb5c24f1": { + "name": "selectedLinearWorkspaceId", + "value": { + "$rpc": "null" + } + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "52bdddbac50f": { + "name": "trustedOrcaHooks", + "value": {} + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5731a23b16cd": { + "name": "selectedLinearTeamIds", + "value": [] + }, + "57da83afd125": { + "name": "taskStateHydrated", + "value": true + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "68155c1eb584": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-2", + "ok": false + } + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "74a4162f39f8": { + "name": "githubKind", + "value": "issues" + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8372342e5a51": { + "name": "linearFilter", + "value": "all" + }, + "888c93f6f346": { + "name": "appliedQuery", + "value": "is:issue is:open" + }, + "8f287f21cfc4": { + "name": "defaultGitHubPreset", + "value": "issues" + }, + "963a91c532c8": { + "hydrated": true, + "settings": {} + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "9a0f810232ef": { + "name": "provider", + "value": "github" + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "a67d16a13986": { + "name": "githubMode", + "value": "items" + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b66eccd2062e": { + "name": "linearWorkspaces", + "value": [] + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "bfd6af371d88": { + "name": "githubProjectSettings", + "value": { + "activeProject": { + "$rpc": "null" + }, + "lastViewByProject": {}, + "pinned": [], + "recent": [] + } + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "dae7907f03cc": { + "name": "runtimeTaskSettings", + "value": {} + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eafaa34ddedb": { + "name": "visibleProviders", + "value": ["github", "linear"] + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "settings-task-hydration-refused", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "68155c1eb584", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "963a91c532c8", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "dae7907f03cc", + "52bdddbac50f", + "4cc1535f7ccf", + "16f398d67267", + "b66eccd2062e", + "1410db92f7e5", + "5731a23b16cd", + "4efedb5c24f1", + "eafaa34ddedb", + "9a0f810232ef", + "a67d16a13986", + "8f287f21cfc4", + "45d50e768fcc", + "74a4162f39f8", + "8372342e5a51", + "bfd6af371d88", + "02d5832df83d", + "888c93f6f346", + "57da83afd125" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-task-hydration-transport-error.json b/mobile/rpc-foundation/goldens/settings-task-hydration-transport-error.json new file mode 100644 index 00000000000..690c83c62c9 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-task-hydration-transport-error.json @@ -0,0 +1,645 @@ +{ + "operation": "settings.task-hydration", + "family": "settings.task-hydration", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "002ad269dd44": { + "name": "showLinearConnect", + "value": false + }, + "03f32b62aa80": { + "name": "showGitHubProjectViewPicker", + "value": false + }, + "068f4fd0ad0c": { + "name": "showRepoPicker", + "value": false + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "10aeb294c268": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "12388aa75326": { + "name": "projectRowItem", + "value": { + "$rpc": "null" + } + }, + "1b3fd2de141f": { + "name": "showLinearOrderPicker", + "value": false + }, + "1e5b32902af7": { + "name": "status.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"status.get\"}" + }, + "1f7d21cec906": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "1f96a2f943c0": { + "name": "showGitLabViewPicker", + "value": false + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "321a59c40cce": { + "name": "showProviderPicker", + "value": false + }, + "347cc433c473": { + "name": "projectRowDetail", + "value": { + "$rpc": "null" + } + }, + "367b8fc27ba4": { + "name": "showLinearViewPicker", + "value": false + }, + "38721e31cbb4": { + "name": "showGitHubProjectSortPicker", + "value": false + }, + "3e610f908f29": { + "name": "showCreateTask", + "value": false + }, + "3e9fac4d6c32": { + "name": "showLinearTeamPicker", + "value": false + }, + "42d2e0167dad": { + "name": "pendingGitHubProjectViewSelection", + "value": { + "$rpc": "null" + } + }, + "4a435aea04b4": { + "name": "showLinearFilterPicker", + "value": false + }, + "5093ceeca936": { + "name": "showGitHubPagePicker", + "value": false + }, + "54ea1a00a461": { + "name": "showGitHubProjectFieldsPicker", + "value": false + }, + "5b1145eb3832": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "supported" + } + }, + "5fb094097bdb": { + "name": "error", + "value": "settings disconnected" + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "6f30f8b6f3d7": { + "name": "status.get#1", + "args": [ + { + "name": "method", + "value": "status.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + } + }, + "740d91a30846": { + "name": "pendingHostedStateChange", + "value": { + "$rpc": "null" + } + }, + "7d341b2cb946": { + "name": "detailPayload", + "value": { + "$rpc": "null" + } + }, + "7f2e001f13e7": { + "name": "projectRepoNotInOrca", + "value": { + "$rpc": "null" + } + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "977e1de1ac2f": { + "name": "mergeMethodTaskItem", + "value": { + "$rpc": "null" + } + }, + "991081048cc2": { + "name": "reset-workspace", + "value": { + "$rpc": "null" + } + }, + "a211e64f0900": { + "name": "showLinearGroupPicker", + "value": false + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "aa624b10c314": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "aba4413b55bb": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "ac9996319e05": { + "name": "actionItem", + "value": { + "$rpc": "null" + } + }, + "afdf1ac21a92": { + "name": "showCreateTargetPicker", + "value": false + }, + "b7c9b524edd4": { + "name": "pendingHostedMerge", + "value": { + "$rpc": "null" + } + }, + "b80be68cd059": { + "name": "showGitHubKindPicker", + "value": false + }, + "b82f9e80bd6a": { + "name": "showGitHubPresetPicker", + "value": false + }, + "b8ca6ac0e3ec": { + "name": "showLinearWorkspacePicker", + "value": false + }, + "bbbd4bc0a4ef": { + "name": "taskStateHydrated", + "value": false + }, + "bc6d9aaa835c": { + "name": "showLinearDisplayPicker", + "value": false + }, + "c6178e6a0f4e": { + "hydrated": false, + "settings": {} + }, + "c78894b47bfd": { + "name": "mergeMethodProjectRow", + "value": { + "$rpc": "null" + } + }, + "ce5f2125a8c4": { + "name": "tasksSupportState", + "value": { + "client": "logical-client", + "kind": "unknown" + } + }, + "d47b67d8f357": { + "name": "showGitHubIssueSourcePicker", + "value": false + }, + "e23c248f269a": { + "name": "showSortPicker", + "value": false + }, + "e542d7c9af9f": { + "name": "showGitHubProjectPicker", + "value": false + }, + "e5662efa8968": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "e60346521f80": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "eac54552d8bc": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "ee444fb637a3": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "f19db62f49cd": { + "name": "showGitLabFilterPicker", + "value": false + }, + "f7c5ddb715d7": { + "name": "pendingProjectGitHubMerge", + "value": { + "$rpc": "null" + } + }, + "fb70d4271ae2": { + "name": "linearStatusPickerItem", + "value": { + "$rpc": "null" + } + } + }, + "recording": { + "scenario": "settings-task-hydration-transport-error", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "090c88478661", + "5fbdd64c75bc", + "234fabe27913", + "a4760ef5a9f4" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8" + ] + } + }, + { + "id": "settled", + "observation": { + "sender": [ + "6f30f8b6f3d7", + "10aeb294c268", + "1f7d21cec906", + "e5662efa8968", + "aa624b10c314" + ], + "payloads": [ + "1e5b32902af7", + "eac54552d8bc", + "e60346521f80", + "ee444fb637a3", + "aba4413b55bb" + ], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "c6178e6a0f4e", + "effects": [ + "bbbd4bc0a4ef", + "ce5f2125a8c4", + "b8ca6ac0e3ec", + "3e9fac4d6c32", + "367b8fc27ba4", + "a211e64f0900", + "1b3fd2de141f", + "bc6d9aaa835c", + "002ad269dd44", + "321a59c40cce", + "b80be68cd059", + "b82f9e80bd6a", + "1f96a2f943c0", + "f19db62f49cd", + "4a435aea04b4", + "e23c248f269a", + "068f4fd0ad0c", + "d47b67d8f357", + "5093ceeca936", + "e542d7c9af9f", + "03f32b62aa80", + "38721e31cbb4", + "54ea1a00a461", + "42d2e0167dad", + "ac9996319e05", + "12388aa75326", + "7f2e001f13e7", + "7d341b2cb946", + "347cc433c473", + "3e610f908f29", + "afdf1ac21a92", + "fb70d4271ae2", + "b7c9b524edd4", + "f7c5ddb715d7", + "740d91a30846", + "977e1de1ac2f", + "c78894b47bfd", + "991081048cc2", + "5b1145eb3832", + "82cd71d524c8", + "5fb094097bdb", + "bbbd4bc0a4ef" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-task-workspace-fulfilled.json b/mobile/rpc-foundation/goldens/settings-task-workspace-fulfilled.json new file mode 100644 index 00000000000..fa1e27c96f4 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-task-workspace-fulfilled.json @@ -0,0 +1,190 @@ +{ + "operation": "settings.task-workspace", + "family": "settings.task-workspace", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "326e3f8f7e0b": { + "name": "runtimeTaskSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "3405a06dce84": { + "name": "error", + "value": "Selected agent is disabled. Choose an enabled agent before creating." + }, + "3f453dd79b03": { + "name": "workspaceAgent", + "value": "codex" + }, + "730f92993963": { + "name": "creatingKey", + "value": "linear:1" + }, + "7abdfe20af50": { + "creating": "linear:1", + "error": "", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "7ca23c4c946b": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "8b8197eed660": { + "creating": { + "$rpc": "null" + }, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "c9cb32059b8d": { + "name": "creatingKey", + "value": { + "$rpc": "null" + } + }, + "ea709e13f0f0": { + "name": "workspaceAgentOverridden", + "value": false + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-task-workspace-fulfilled", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "7abdfe20af50", + "effects": ["730f92993963", "82cd71d524c8"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "8b8197eed660", + "effects": [ + "730f92993963", + "82cd71d524c8", + "326e3f8f7e0b", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-task-workspace-refused.json b/mobile/rpc-foundation/goldens/settings-task-workspace-refused.json new file mode 100644 index 00000000000..6a1fb0525ed --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-task-workspace-refused.json @@ -0,0 +1,170 @@ +{ + "operation": "settings.task-workspace", + "family": "settings.task-workspace", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "3405a06dce84": { + "name": "error", + "value": "Selected agent is disabled. Choose an enabled agent before creating." + }, + "3f453dd79b03": { + "name": "workspaceAgent", + "value": "codex" + }, + "730f92993963": { + "name": "creatingKey", + "value": "linear:1" + }, + "7abdfe20af50": { + "creating": "linear:1", + "error": "", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "c9cb32059b8d": { + "name": "creatingKey", + "value": { + "$rpc": "null" + } + }, + "d5df3f6b123a": { + "creating": { + "$rpc": "null" + }, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "d6140b218abd": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "ea709e13f0f0": { + "name": "workspaceAgentOverridden", + "value": false + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-task-workspace-refused", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "7abdfe20af50", + "effects": ["730f92993963", "82cd71d524c8"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["d6140b218abd"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "d5df3f6b123a", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-task-workspace-transport-error.json b/mobile/rpc-foundation/goldens/settings-task-workspace-transport-error.json new file mode 100644 index 00000000000..4b9c5290912 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-task-workspace-transport-error.json @@ -0,0 +1,167 @@ +{ + "operation": "settings.task-workspace", + "family": "settings.task-workspace", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "10aeb294c268": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "3405a06dce84": { + "name": "error", + "value": "Selected agent is disabled. Choose an enabled agent before creating." + }, + "3f453dd79b03": { + "name": "workspaceAgent", + "value": "codex" + }, + "730f92993963": { + "name": "creatingKey", + "value": "linear:1" + }, + "7abdfe20af50": { + "creating": "linear:1", + "error": "", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "c9cb32059b8d": { + "name": "creatingKey", + "value": { + "$rpc": "null" + } + }, + "d5df3f6b123a": { + "creating": { + "$rpc": "null" + }, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "ea709e13f0f0": { + "name": "workspaceAgentOverridden", + "value": false + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-task-workspace-transport-error", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "7abdfe20af50", + "effects": ["730f92993963", "82cd71d524c8"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["10aeb294c268"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "d5df3f6b123a", + "effects": [ + "730f92993963", + "82cd71d524c8", + "3f453dd79b03", + "ea709e13f0f0", + "3405a06dce84", + "c9cb32059b8d" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-task-write.json b/mobile/rpc-foundation/goldens/settings-task-write.json new file mode 100644 index 00000000000..97b0ac7936f --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-task-write.json @@ -0,0 +1,121 @@ +{ + "operation": "settings.task-preferences", + "family": "settings-best-effort", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "2369258c9999": { + "name": "settings.update#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.update\",\"params\":{\"defaultTaskViewPreset\":\"assigned\"}}" + }, + "4a8219d725de": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "write disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "5db909d58c6f": { + "preset": "assigned" + }, + "74827568abb0": { + "name": "settings.update#1", + "args": [ + { + "name": "method", + "value": "settings.update" + }, + { + "name": "params", + "value": { + "defaultTaskViewPreset": "assigned" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b2897d5daa49": { + "name": "defaultGitHubPreset", + "value": "assigned" + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-task-write", + "checkpoints": [ + { + "id": "optimistic", + "observation": { + "sender": ["74827568abb0"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["4a8219d725de"], + "payloads": ["2369258c9999"], + "settlements": { + "mount": "eb79a9b3682a", + "write": "eb79a9b3682a" + }, + "state": "5db909d58c6f", + "effects": ["b2897d5daa49"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-workspace-context-fulfilled.json b/mobile/rpc-foundation/goldens/settings-workspace-context-fulfilled.json new file mode 100644 index 00000000000..639330f0aa7 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-workspace-context-fulfilled.json @@ -0,0 +1,326 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2a7485a88169": { + "providers": ["github"], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + } + }, + "recording": { + "scenario": "settings-workspace-context-fulfilled", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-workspace-context-refuse-after-data.json b/mobile/rpc-foundation/goldens/settings-workspace-context-refuse-after-data.json new file mode 100644 index 00000000000..8b03d8f17ff --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-workspace-context-refuse-after-data.json @@ -0,0 +1,653 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "02f9384f5305": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-7", + "ok": false + } + } + }, + "06425d8da2e6": { + "name": "linear.status#2", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "13028e692551": { + "name": "preflight.check#2", + "json": "{\"id\":\"frame-5\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "2a7485a88169": { + "providers": ["github"], + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + }, + "trust": {} + }, + "39bfd36b44ed": { + "name": "ui.get#2", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "3fc2a1b54e13": { + "name": "settings.get#2", + "json": "{\"id\":\"frame-7\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "7126d29ddcda": { + "name": "ui.get#2", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-8", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "7ad8a0996352": { + "name": "settings.get#2", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "822040616fbb": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-3", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "847430ffa968": { + "name": "linear.status#2", + "json": "{\"id\":\"frame-6\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "84b10f34b617": { + "name": "ui.get#2", + "json": "{\"id\":\"frame-8\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "b6adb83e8ae3": { + "name": "preflight.check#2", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-5", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "c114925e9c68": { + "name": "preflight.check#2", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "c6b50afb206d": { + "name": "linear.status#2", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-6", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + } + }, + "recording": { + "scenario": "settings-workspace-context-refuse-after-data", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "data-present", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "822040616fbb", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "refresh-pending", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "c114925e9c68", + "06425d8da2e6", + "7ad8a0996352", + "39bfd36b44ed" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "blur": "eb79a9b3682a", + "revisit": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + }, + { + "id": "refused-after-data", + "observation": { + "sender": [ + "563e4c82b345", + "789980530ae3", + "822040616fbb", + "4938921744c6", + "b6adb83e8ae3", + "c6b50afb206d", + "02f9384f5305", + "7126d29ddcda" + ], + "payloads": [ + "0fb6ff3590e2", + "76de732c569f", + "4335d4b6568f", + "82ff8123c1fe", + "13028e692551", + "847430ffa968", + "3fc2a1b54e13", + "84b10f34b617" + ], + "settlements": { + "mount": "eb79a9b3682a", + "blur": "eb79a9b3682a", + "revisit": "eb79a9b3682a" + }, + "state": "2a7485a88169", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-workspace-context-refused.json b/mobile/rpc-foundation/goldens/settings-workspace-context-refused.json new file mode 100644 index 00000000000..4f4031319f6 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-workspace-context-refused.json @@ -0,0 +1,317 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "3a834cb85dd8": { + "providers": ["github"], + "settings": { + "$rpc": "null" + }, + "trust": {} + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "c4360222a04e": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-3", + "ok": false + } + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + } + }, + "recording": { + "scenario": "settings-workspace-context-refused", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "c4360222a04e", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-workspace-context-transport-error.json b/mobile/rpc-foundation/goldens/settings-workspace-context-transport-error.json new file mode 100644 index 00000000000..4a83c6a3f5c --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-workspace-context-transport-error.json @@ -0,0 +1,314 @@ +{ + "operation": "settings.workspace-context", + "family": "settings.workspace-context", + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "0fb6ff3590e2": { + "name": "preflight.check#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"preflight.check\"}" + }, + "10aeb294c268": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "234fabe27913": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "3a834cb85dd8": { + "providers": ["github"], + "settings": { + "$rpc": "null" + }, + "trust": {} + }, + "4335d4b6568f": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-3\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "4938921744c6": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-4", + "ok": true, + "result": { + "ui": {} + } + } + } + }, + "563e4c82b345": { + "name": "preflight.check#1", + "args": [ + { + "name": "method", + "value": "preflight.check" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + } + }, + "5fbdd64c75bc": { + "name": "ui.get#1", + "args": [ + { + "name": "method", + "value": "ui.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "76de732c569f": { + "name": "linear.status#1", + "json": "{\"id\":\"frame-2\",\"deviceToken\":\"recording-device\",\"method\":\"linear.status\"}" + }, + "789980530ae3": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-2", + "ok": true, + "result": { + "connected": false + } + } + } + }, + "82ff8123c1fe": { + "name": "ui.get#1", + "json": "{\"id\":\"frame-4\",\"deviceToken\":\"recording-device\",\"method\":\"ui.get\"}" + }, + "a4760ef5a9f4": { + "name": "linear.status#1", + "args": [ + { + "name": "method", + "value": "linear.status" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + }, + "f6a09f8c5b85": { + "providers": [], + "settings": { + "$rpc": "null" + }, + "trust": {} + } + }, + "recording": { + "scenario": "settings-workspace-context-transport-error", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["234fabe27913", "a4760ef5a9f4", "090c88478661", "5fbdd64c75bc"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "f6a09f8c5b85", + "effects": [] + } + }, + { + "id": "settled", + "observation": { + "sender": ["563e4c82b345", "789980530ae3", "10aeb294c268", "4938921744c6"], + "payloads": ["0fb6ff3590e2", "76de732c569f", "4335d4b6568f", "82ff8123c1fe"], + "settlements": { + "mount": "eb79a9b3682a" + }, + "state": "3a834cb85dd8", + "effects": [] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-workspace-submit-fulfilled.json b/mobile/rpc-foundation/goldens/settings-workspace-submit-fulfilled.json new file mode 100644 index 00000000000..1e4586b37ee --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-workspace-submit-fulfilled.json @@ -0,0 +1,179 @@ +{ + "operation": "settings.workspace-submit", + "family": "settings.workspace-submit", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "13c996e4ec2b": { + "creating": true, + "error": "", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "3405a06dce84": { + "name": "error", + "value": "Selected agent is disabled. Choose an enabled agent before creating." + }, + "5efbd884ea5a": { + "creating": false, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "6c2789ab0e4b": { + "name": "runtimeSettings", + "value": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + }, + "7ca23c4c946b": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "id": "frame-1", + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": ["claude"], + "hostSettingOverrides": {}, + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"] + } + } + } + } + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "ae291b5dba88": { + "name": "agentOverridden", + "value": false + }, + "eb6f7a9c5bf1": { + "name": "selectedAgent", + "value": { + "id": "codex", + "label": "Codex" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-workspace-submit-fulfilled", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "13c996e4ec2b", + "effects": ["82cd71d524c8"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["7ca23c4c946b"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "5efbd884ea5a", + "effects": [ + "82cd71d524c8", + "6c2789ab0e4b", + "eb6f7a9c5bf1", + "ae291b5dba88", + "3405a06dce84" + ] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-workspace-submit-refused.json b/mobile/rpc-foundation/goldens/settings-workspace-submit-refused.json new file mode 100644 index 00000000000..64245dead80 --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-workspace-submit-refused.json @@ -0,0 +1,154 @@ +{ + "operation": "settings.workspace-submit", + "family": "settings.workspace-submit", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "13c996e4ec2b": { + "creating": true, + "error": "", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "2e8e352c8dd1": { + "creating": false, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "3405a06dce84": { + "name": "error", + "value": "Selected agent is disabled. Choose an enabled agent before creating." + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "ae291b5dba88": { + "name": "agentOverridden", + "value": false + }, + "d6140b218abd": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "error": { + "code": "refused", + "message": "settings refused" + }, + "id": "frame-1", + "ok": false + } + } + }, + "eb6f7a9c5bf1": { + "name": "selectedAgent", + "value": { + "id": "codex", + "label": "Codex" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-workspace-submit-refused", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "13c996e4ec2b", + "effects": ["82cd71d524c8"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["d6140b218abd"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2e8e352c8dd1", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/goldens/settings-workspace-submit-transport-error.json b/mobile/rpc-foundation/goldens/settings-workspace-submit-transport-error.json new file mode 100644 index 00000000000..ff6f1d3b8fc --- /dev/null +++ b/mobile/rpc-foundation/goldens/settings-workspace-submit-transport-error.json @@ -0,0 +1,151 @@ +{ + "operation": "settings.workspace-submit", + "family": "settings.workspace-submit", + "namedDeltas": [], + "runnerVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "lockfileSha256": "788c1234b38a61fc882fca292341fce6690deee9cc6695673b0575cf2c4cf571", + "recorderSha256": "6a12160a87ceab04e74198f6dd35b8cf9125794222ee95cf6ca1872f29849960", + "platform": "darwin", + "scenarioVersion": 1, + "projectionVersion": 2, + "goldenFormatVersion": 3, + "values": { + "090c88478661": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "pending", + "startedAt": 0 + } + }, + "10aeb294c268": { + "name": "settings.get#1", + "args": [ + { + "name": "method", + "value": "settings.get" + }, + { + "name": "params", + "value": { + "$rpc": "absent" + } + }, + { + "name": "options", + "value": { + "$rpc": "absent" + } + } + ], + "settlement": { + "status": "rejected", + "startedAt": 0, + "settledAt": 0, + "error": { + "category": "Error", + "message": "settings disconnected", + "isRpcDeliveryUnknown": true + } + } + }, + "13c996e4ec2b": { + "creating": true, + "error": "", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "2e8e352c8dd1": { + "creating": false, + "error": "Selected agent is disabled. Choose an enabled agent before creating.", + "settings": { + "disabledTuiAgents": ["claude"] + } + }, + "3405a06dce84": { + "name": "error", + "value": "Selected agent is disabled. Choose an enabled agent before creating." + }, + "7ddcb1852b39": { + "name": "settings.get#1", + "json": "{\"id\":\"frame-1\",\"deviceToken\":\"recording-device\",\"method\":\"settings.get\"}" + }, + "82cd71d524c8": { + "name": "error", + "value": "" + }, + "9270aeb7d9c6": { + "status": "pending", + "startedAt": 0 + }, + "ae291b5dba88": { + "name": "agentOverridden", + "value": false + }, + "eb6f7a9c5bf1": { + "name": "selectedAgent", + "value": { + "id": "codex", + "label": "Codex" + } + }, + "eb79a9b3682a": { + "status": "fulfilled", + "startedAt": 0, + "settledAt": 0, + "value": { + "$rpc": "undefined" + } + } + }, + "recording": { + "scenario": "settings-workspace-submit-transport-error", + "checkpoints": [ + { + "id": "settings-pending", + "observation": { + "sender": ["090c88478661"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "9270aeb7d9c6" + }, + "state": "13c996e4ec2b", + "effects": ["82cd71d524c8"] + } + }, + { + "id": "settled", + "observation": { + "sender": ["10aeb294c268"], + "payloads": ["7ddcb1852b39"], + "settlements": { + "mount": "eb79a9b3682a", + "submit": "eb79a9b3682a" + }, + "state": "2e8e352c8dd1", + "effects": ["82cd71d524c8", "eb6f7a9c5bf1", "ae291b5dba88", "3405a06dce84"] + } + } + ] + } +} diff --git a/mobile/rpc-foundation/live-probe/mock-desktop-settings-reply-modes.patch b/mobile/rpc-foundation/live-probe/mock-desktop-settings-reply-modes.patch new file mode 100644 index 00000000000..1964b4bc9f1 --- /dev/null +++ b/mobile/rpc-foundation/live-probe/mock-desktop-settings-reply-modes.patch @@ -0,0 +1,52 @@ +diff --git a/mobile/scripts/mock-server-rpc-handlers.ts b/mobile/scripts/mock-server-rpc-handlers.ts +index f67db5bc2f2..5049bd9d143 100644 +--- a/mobile/scripts/mock-server-rpc-handlers.ts ++++ b/mobile/scripts/mock-server-rpc-handlers.ts +@@ -165,17 +165,37 @@ export function handleRequest( + respond(success(request.id, { repos: FAKE_REPOS })) + break + +- case 'settings.get': +- respond( +- success(request.id, { +- settings: { +- defaultTuiAgent: 'codex', +- disabledTuiAgents: [], +- agentCmdOverrides: {} +- } +- }) +- ) ++ case 'settings.get': { ++ // MOCK_SETTINGS_GET_MODE drives runtime validation of the refusal/null/absent branches. ++ const mode = process.env.MOCK_SETTINGS_GET_MODE ?? 'ok' ++ if (mode === 'refused') { ++ respond(error(request.id, 'refused', 'settings refused')) ++ } else if (mode === 'method-not-found') { ++ respond(error(request.id, 'method_not_found', 'Unknown method')) ++ } else if (mode === 'null-result') { ++ respond(success(request.id, null)) ++ } else if (mode === 'absent-result') { ++ const resp = success(request.id, undefined) ++ delete (resp as { result?: unknown }).result ++ respond(resp) ++ } else if (mode === 'absent-settings') { ++ respond(success(request.id, {})) ++ } else if (mode === 'drop') { ++ // Mid-request disconnect: never answer, then close the socket. ++ setTimeout(() => ws.close(), 50) ++ } else { ++ respond( ++ success(request.id, { ++ settings: { ++ defaultTuiAgent: 'codex', ++ disabledTuiAgents: [], ++ agentCmdOverrides: {} ++ } ++ }) ++ ) ++ } + break ++ } + + case 'settings.getTerminalQuickCommands': + respond(success(request.id, { terminalQuickCommands: fakeQuickCommands })) diff --git a/mobile/rpc-foundation/live-probe/settings-get-reply-probe.mts b/mobile/rpc-foundation/live-probe/settings-get-reply-probe.mts new file mode 100644 index 00000000000..081ec7d07cf --- /dev/null +++ b/mobile/rpc-foundation/live-probe/settings-get-reply-probe.mts @@ -0,0 +1,130 @@ +// Runtime probe: real mock-desktop settings.get replies through the migrated acceptance layer. +import WebSocket from 'ws' +import nacl from 'tweetnacl' +import { readFileSync } from 'node:fs' +import { deriveSharedKey, e2eeDecrypt, e2eeEncrypt } from '../../scripts/mock-server-encryption.ts' +import { + botOverridesRead, + newTabSettingsRead, + optionalSettingsRead, + settingsRead +} from '../../src/transport/settings-read-operations.ts' + +const PORT = Number(process.env.PORT) || 6768 +const KEY_FILE = process.env.MOCK_SERVER_KEY_FILE! +const serverPublic = nacl.box.keyPair.fromSecretKey( + Uint8Array.from(Buffer.from(readFileSync(KEY_FILE, 'utf-8').trim(), 'base64')) +).publicKey + +function rawReply(): Promise { + const kp = nacl.box.keyPair() + const key = deriveSharedKey(kp.secretKey, serverPublic) + const ws = new WebSocket(`ws://127.0.0.1:${PORT}`) + return new Promise((resolve, reject) => { + let settled = false + const finish = (value: unknown) => { + if (!settled) { + settled = true + try { + ws.close() + } catch {} + resolve(value) + } + } + const timer = setTimeout(() => finish({ __outcome: 'no-reply-timeout' }), 5000) + ws.on('open', () => + ws.send( + JSON.stringify({ + type: 'e2ee_hello', + publicKeyB64: Buffer.from(kp.publicKey).toString('base64') + }) + ) + ) + ws.on('close', () => { + clearTimeout(timer) + finish({ __outcome: 'socket-closed-before-reply' }) + }) + ws.on('error', (e) => { + clearTimeout(timer) + if (!settled) { + settled = true + reject(e) + } + }) + ws.on('message', (data) => { + const text = data.toString('utf-8') + if (text.startsWith('{"type":"e2ee_ready"')) { + ws.send( + e2eeEncrypt(JSON.stringify({ type: 'e2ee_auth', deviceToken: 'mock-device-token' }), key) + ) + return + } + const plain = e2eeDecrypt(text, key) + if (plain === null) { + return + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the probe prints whatever the host sent, so the frame is read as a bag of fields. + const frame = JSON.parse(plain) as { type?: string; id?: string } + if (frame.type === 'e2ee_authenticated') { + ws.send( + e2eeEncrypt( + JSON.stringify({ id: 'probe-1', method: 'settings.get', token: 'mock-device-token' }), + key + ) + ) + return + } + if (frame.id === 'probe-1') { + clearTimeout(timer) + finish(frame) + } + }) + }) +} + +function describe(label: string, run: () => unknown): string { + try { + const value = run() + return `${label}=${JSON.stringify(value)}` + } catch (error) { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a thrown value is not an Error by type; only its constructor name and message are printed. + return `${label}=THREW ${(error as Error).constructor.name}: ${(error as Error).message}` + } +} + +// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the probe substitutes one recorded reply for the whole client surface. +const reply = (await rawReply()) as Record +// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the probe substitutes one recorded reply for the whole client surface. +const client = { + sendRequest: async () => reply +} as unknown as Parameters[0] + +const lines: string[] = [`mode=${process.env.MOCK_SETTINGS_GET_MODE ?? 'ok'}`] +lines.push(`wireReply=${JSON.stringify(reply)}`) +if (reply.__outcome) { + lines.push('interpret=skipped (no reply frame)') +} else { + for (const [name, op] of [ + ['settingsRead', settingsRead], + ['optionalSettingsRead', optionalSettingsRead], + ['botOverridesRead', botOverridesRead], + ['newTabSettingsRead', newTabSettingsRead] + ] as const) { + const response = await op.request(client) + lines.push( + describe(name, () => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: each operation is driven through its own declared reply type in turn. + const outcome = op.interpret(response as never) as + | (() => unknown) + | { accepted?: boolean; value?: unknown } + // new-tab acceptance returns a deferred reader, not an accept envelope. + if (typeof outcome === 'function') { + return { deferred: outcome() } + } + const value = typeof outcome?.value === 'function' ? outcome.value() : outcome?.value + return outcome?.accepted === undefined ? value : { accepted: outcome.accepted, value } + }) + ) + } +} +process.stdout.write(lines.join('\n') + '\n') diff --git a/mobile/rpc-foundation/pilot-scenarios.json b/mobile/rpc-foundation/pilot-scenarios.json new file mode 100644 index 00000000000..216da99ca16 --- /dev/null +++ b/mobile/rpc-foundation/pilot-scenarios.json @@ -0,0 +1,5142 @@ +{ + "schemaVersion": 1, + "baseline": "16d1ab81d3fd08e342b2f0ac0cc6f9e4aea4aaee", + "scenarios": [ + { + "id": "b1", + "operation": "workspace.file-inventory", + "version": 1, + "family": "legacy-inventory", + "sites": ["mobile/src/session/use-mobile-native-chat-file-search.ts"], + "schedules": ["a-b-a", "stale-inflight-cleanup"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "query", + "id": "old", + "args": { + "query": "old" + } + }, + { + "advance": 120 + }, + { + "complete": "files.searchPaths#1", + "params": { + "worktree": "id:A", + "query": "old", + "limit": 16 + }, + "reply": { + "ok": false, + "error": { + "code": "method_not_found", + "message": "Unknown method" + } + } + }, + { + "bind": "old-inventory", + "request": "files.list#1", + "params": { + "worktree": "id:A" + } + }, + { + "checkpoint": "old-pending" + }, + { + "action": "select", + "id": "select-b", + "args": { + "workspace": "B" + } + }, + { + "action": "select", + "id": "reset-a", + "args": { + "workspace": "A" + } + }, + { + "action": "query", + "id": "fresh", + "args": { + "query": "fresh" + } + }, + { + "advance": 120 + }, + { + "complete": "files.searchPaths#2", + "params": { + "worktree": "id:A", + "query": "fresh", + "limit": 16 + }, + "reply": { + "ok": false, + "error": { + "code": "method_not_found", + "message": "Unknown method" + } + } + }, + { + "bind": "fresh-inventory", + "request": "files.list#2", + "params": { + "worktree": "id:A" + } + }, + { + "complete": "old-inventory", + "params": { + "worktree": "id:A" + }, + "reply": { + "ok": true, + "result": { + "files": [ + { + "relativePath": "old.ts" + } + ] + } + } + }, + { + "checkpoint": "stale-arrived-fresh-pending" + }, + { + "action": "query", + "id": "third", + "args": { + "query": "third" + } + }, + { + "advance": 120 + }, + { + "checkpoint": "third-query" + }, + { + "complete": "fresh-inventory", + "params": { + "worktree": "id:A" + }, + "reply": { + "ok": true, + "result": { + "files": [ + { + "relativePath": "fresh.ts" + }, + { + "relativePath": "third.ts" + } + ] + } + } + }, + { + "checkpoint": "fresh-arrived" + } + ] + }, + { + "id": "b2", + "operation": "project.update-metadata", + "version": 1, + "family": "project-explicit-false", + "sites": ["mobile/src/tasks/use-mobile-tasks-project-metadata-actions.tsx"], + "schedules": [], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "submit", + "id": "submit" + }, + { + "checkpoint": "pending" + }, + { + "complete": "github.project.updateIssueBySlug#1", + "params": { + "owner": "owner", + "repo": "repo", + "host": "github.enterprise.test", + "number": 1, + "updates": { + "addLabels": ["recorded"] + } + }, + "reply": { + "ok": true, + "result": null + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "b3", + "operation": "linear.issue-detail", + "version": 1, + "family": "linear-detail-barrier", + "sites": ["mobile/src/tasks/use-mobile-tasks-item-detail-loading.tsx"], + "schedules": ["issue-first", "peer-pending"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "checkpoint": "pending" + }, + { + "complete": "linear.getIssue#1", + "params": { + "id": "issue-1", + "workspaceId": "linear-workspace" + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "issue refused" + } + } + }, + { + "checkpoint": "issue-refused-comments-pending" + }, + { + "complete": "linear.issueComments#1", + "params": { + "issueId": "issue-1", + "workspaceId": "linear-workspace" + }, + "reject": { + "message": "comments transport error", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-new-tab-ssh", + "operation": "settings.new-tab-agents", + "version": 1, + "family": "settings-agent-read", + "sites": ["mobile/src/session/mobile-new-tab-agent-loader.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "pending" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "defaultTuiAgent": "codex", + "disabledTuiAgents": [] + } + } + } + }, + { + "complete": "preflight.detectRemoteAgents#1", + "params": { + "connectionId": "ssh-1" + }, + "reply": { + "ok": true, + "result": ["codex", "claude"] + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-task-write", + "operation": "settings.task-preferences", + "version": 1, + "family": "settings-best-effort", + "sites": ["mobile/src/tasks/use-mobile-tasks-client-settings-actions.tsx"], + "schedules": [], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "write", + "id": "write", + "args": { + "preset": "assigned" + } + }, + { + "checkpoint": "optimistic" + }, + { + "complete": "settings.update#1", + "params": { + "defaultTaskViewPreset": "assigned" + }, + "reject": { + "message": "write disconnected", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-bot-overrides-fulfilled", + "operation": "settings.bot-overrides", + "version": 1, + "family": "settings.bot-overrides", + "sites": ["mobile/src/session/use-pr-bot-author-overrides.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-bot-overrides-refused", + "operation": "settings.bot-overrides", + "version": 1, + "family": "settings.bot-overrides", + "sites": ["mobile/src/session/use-pr-bot-author-overrides.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-bot-overrides-transport-error", + "operation": "settings.bot-overrides", + "version": 1, + "family": "settings.bot-overrides", + "sites": ["mobile/src/session/use-pr-bot-author-overrides.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-workspace-context-fulfilled", + "operation": "settings.workspace-context", + "version": 1, + "family": "settings.workspace-context", + "sites": ["mobile/src/components/use-new-workspace-runtime-context.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "ui.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + } + ], + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"] + }, + { + "id": "settings-workspace-context-refused", + "operation": "settings.workspace-context", + "version": 1, + "family": "settings.workspace-context", + "sites": ["mobile/src/components/use-new-workspace-runtime-context.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "ui.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + } + ], + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"] + }, + { + "id": "settings-workspace-context-transport-error", + "operation": "settings.workspace-context", + "version": 1, + "family": "settings.workspace-context", + "sites": ["mobile/src/components/use-new-workspace-runtime-context.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "complete": "ui.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + } + ], + "namedDeltas": ["new-workspace-runtime-context-null-settings-typeerror"] + }, + { + "id": "settings-home-providers-fulfilled", + "operation": "settings.home-providers", + "version": 1, + "family": "settings.home-providers", + "sites": ["mobile/src/home/mobile-home-host-requests.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-home-providers-refused", + "operation": "settings.home-providers", + "version": 1, + "family": "settings.home-providers", + "sites": ["mobile/src/home/mobile-home-host-requests.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-home-providers-transport-error", + "operation": "settings.home-providers", + "version": 1, + "family": "settings.home-providers", + "sites": ["mobile/src/home/mobile-home-host-requests.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-resume-metadata-fulfilled", + "operation": "settings.resume-metadata", + "version": 1, + "family": "settings.resume-metadata", + "sites": ["mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [] + } + } + }, + { + "complete": "folderWorkspace.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + }, + { + "complete": "projectGroup.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "groups": [] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "worktree.ps#1", + "params": { + "limit": 10000, + "supportsWorktreeVisibilitySourceDefaults": true + }, + "reply": { + "ok": true, + "result": { + "worktrees": [] + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-resume-metadata-refused", + "operation": "settings.resume-metadata", + "version": 1, + "family": "settings.resume-metadata", + "sites": ["mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [] + } + } + }, + { + "complete": "folderWorkspace.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + }, + { + "complete": "projectGroup.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "groups": [] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "worktree.ps#1", + "params": { + "limit": 10000, + "supportsWorktreeVisibilitySourceDefaults": true + }, + "reply": { + "ok": true, + "result": { + "worktrees": [] + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-resume-metadata-transport-error", + "operation": "settings.resume-metadata", + "version": 1, + "family": "settings.resume-metadata", + "sites": ["mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [] + } + } + }, + { + "complete": "folderWorkspace.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + }, + { + "complete": "projectGroup.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "groups": [] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "complete": "worktree.ps#1", + "params": { + "limit": 10000, + "supportsWorktreeVisibilitySourceDefaults": true + }, + "reply": { + "ok": true, + "result": { + "worktrees": [] + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-repo-metadata-fulfilled", + "operation": "settings.repo-metadata", + "version": 1, + "family": "settings.repo-metadata", + "sites": ["mobile/src/host-screen/use-host-repo-metadata.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "displayName": "Local", + "connectionId": null + }, + { + "id": "repo-2", + "displayName": "Remote", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "ssh.listTargetSummaries#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "host.platform#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "platform": "linux" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-repo-metadata-refused", + "operation": "settings.repo-metadata", + "version": 1, + "family": "settings.repo-metadata", + "sites": ["mobile/src/host-screen/use-host-repo-metadata.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "displayName": "Local", + "connectionId": null + }, + { + "id": "repo-2", + "displayName": "Remote", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "ssh.listTargetSummaries#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "host.platform#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "platform": "linux" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-repo-metadata-transport-error", + "operation": "settings.repo-metadata", + "version": 1, + "family": "settings.repo-metadata", + "sites": ["mobile/src/host-screen/use-host-repo-metadata.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "displayName": "Local", + "connectionId": null + }, + { + "id": "repo-2", + "displayName": "Remote", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "ssh.listTargetSummaries#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "complete": "host.platform#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "platform": "linux" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-task-hydration-fulfilled", + "operation": "settings.task-hydration", + "version": 1, + "family": "settings.task-hydration", + "sites": ["mobile/src/tasks/use-mobile-tasks-runtime-hydration.tsx"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "complete": "status.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "ui.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-task-hydration-refused", + "operation": "settings.task-hydration", + "version": 1, + "family": "settings.task-hydration", + "sites": ["mobile/src/tasks/use-mobile-tasks-runtime-hydration.tsx"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "complete": "status.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "ui.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-task-hydration-transport-error", + "operation": "settings.task-hydration", + "version": 1, + "family": "settings.task-hydration", + "sites": ["mobile/src/tasks/use-mobile-tasks-runtime-hydration.tsx"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "complete": "status.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "complete": "ui.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-workspace-submit-fulfilled", + "operation": "settings.workspace-submit", + "version": 1, + "family": "settings.workspace-submit", + "sites": ["mobile/src/components/use-new-workspace-create-submit.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "submit", + "id": "submit" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-workspace-submit-refused", + "operation": "settings.workspace-submit", + "version": 1, + "family": "settings.workspace-submit", + "sites": ["mobile/src/components/use-new-workspace-create-submit.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "submit", + "id": "submit" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-workspace-submit-transport-error", + "operation": "settings.workspace-submit", + "version": 1, + "family": "settings.workspace-submit", + "sites": ["mobile/src/components/use-new-workspace-create-submit.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "submit", + "id": "submit" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-task-workspace-fulfilled", + "operation": "settings.task-workspace", + "version": 1, + "family": "settings.task-workspace", + "sites": ["mobile/src/tasks/use-mobile-tasks-workspace-create-actions.tsx"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "submit", + "id": "submit" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-task-workspace-refused", + "operation": "settings.task-workspace", + "version": 1, + "family": "settings.task-workspace", + "sites": ["mobile/src/tasks/use-mobile-tasks-workspace-create-actions.tsx"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "submit", + "id": "submit" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-task-workspace-transport-error", + "operation": "settings.task-workspace", + "version": 1, + "family": "settings.task-workspace", + "sites": ["mobile/src/tasks/use-mobile-tasks-workspace-create-actions.tsx"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "submit", + "id": "submit" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-new-tab-refused", + "operation": "settings.new-tab-agents", + "version": 1, + "family": "settings-agent-read", + "sites": ["mobile/src/session/mobile-new-tab-agent-loader.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "pending" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "preflight.detectRemoteAgents#1", + "params": { + "connectionId": "ssh-1" + }, + "reply": { + "ok": true, + "result": ["codex", "claude"] + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-new-tab-transport-error", + "operation": "settings.new-tab-agents", + "version": 1, + "family": "settings-agent-read", + "sites": ["mobile/src/session/mobile-new-tab-agent-loader.ts"], + "schedules": ["settings-first"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "pending" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "complete": "preflight.detectRemoteAgents#1", + "params": { + "connectionId": "ssh-1" + }, + "reply": { + "ok": true, + "result": ["codex", "claude"] + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "settings-home-coalesced", + "operation": "settings.home-providers", + "version": 1, + "family": "settings.home-providers", + "sites": ["mobile/src/home/mobile-home-host-requests.ts"], + "schedules": ["stale-inflight-cleanup", "follow-up-cache-observation"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "action": "load", + "id": "overlapping-load" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + }, + { + "complete": "settings.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "preflight.check#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "follow-up-settled" + }, + { + "action": "load", + "id": "third-load" + }, + { + "checkpoint": "third-query" + } + ] + }, + { + "id": "settings-repo-cache-expiry", + "operation": "settings.repo-metadata", + "version": 1, + "family": "settings.repo-metadata", + "sites": ["mobile/src/host-screen/use-host-repo-metadata.ts"], + "schedules": ["follow-up-cache-observation", "timer-expiry"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "displayName": "Local", + "connectionId": null + }, + { + "id": "repo-2", + "displayName": "Remote", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "ssh.listTargetSummaries#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "host.platform#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "platform": "linux" + } + } + }, + { + "checkpoint": "settled" + }, + { + "action": "load-cached", + "id": "cached-query" + }, + { + "checkpoint": "cache-hit" + }, + { + "advance": 59000 + }, + { + "action": "load-cached", + "id": "warm-query" + }, + { + "checkpoint": "cache-warm" + }, + { + "advance": 1000 + }, + { + "action": "load-cached", + "id": "expired-query" + }, + { + "checkpoint": "cache-expired" + } + ] + }, + { + "id": "inventory-lifecycle", + "operation": "workspace.file-inventory", + "version": 1, + "family": "legacy-inventory", + "sites": ["mobile/src/session/use-mobile-native-chat-file-search.ts"], + "schedules": ["reset", "unmount-remount", "blur-retained-route"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "query", + "id": "old", + "args": { + "query": "old" + } + }, + { + "advance": 120 + }, + { + "complete": "files.searchPaths#1", + "params": { + "worktree": "id:A", + "query": "old", + "limit": 16 + }, + "reply": { + "ok": false, + "error": { + "code": "method_not_found", + "message": "Unknown method" + } + } + }, + { + "bind": "old-inventory", + "request": "files.list#1", + "params": { + "worktree": "id:A" + } + }, + { + "complete": "old-inventory", + "params": { + "worktree": "id:A" + }, + "reply": { + "ok": true, + "result": { + "files": [ + { + "relativePath": "old.ts" + } + ] + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "inventory-repeat-query", + "operation": "workspace.file-inventory", + "version": 1, + "family": "legacy-inventory", + "sites": ["mobile/src/session/use-mobile-native-chat-file-search.ts"], + "schedules": ["normalized-repeat", "cache-cancels-debounce", "cache-stales-inflight"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "query", + "id": "alpha", + "args": { + "query": " ALPHA " + } + }, + { + "advance": 120 + }, + { + "complete": "files.searchPaths#1", + "params": { + "worktree": "id:A", + "query": "alpha", + "limit": 16 + }, + "reply": { + "ok": true, + "result": { + "files": [ + { + "relativePath": "alpha.ts" + } + ] + } + } + }, + { + "action": "query", + "id": "beta", + "args": { + "query": "beta" + } + }, + { + "advance": 120 + }, + { + "complete": "files.searchPaths#2", + "params": { + "worktree": "id:A", + "query": "beta", + "limit": 16 + }, + "reply": { + "ok": true, + "result": { + "files": [ + { + "relativePath": "beta.ts" + } + ] + } + } + }, + { + "action": "query", + "id": "gamma", + "args": { + "query": "gamma" + } + }, + { + "advance": 120 + }, + { + "bind": "stale-search", + "request": "files.searchPaths#3", + "params": { + "worktree": "id:A", + "query": "gamma", + "limit": 16 + } + }, + { + "action": "query", + "id": "repeat-alpha", + "args": { + "query": "alpha" + } + }, + { + "checkpoint": "cached-alpha" + }, + { + "complete": "stale-search", + "params": { + "worktree": "id:A", + "query": "gamma", + "limit": 16 + }, + "reply": { + "ok": true, + "result": { + "files": [ + { + "relativePath": "gamma.ts" + } + ] + } + } + }, + { + "checkpoint": "stale-search-ignored" + }, + { + "action": "query", + "id": "delta", + "args": { + "query": "delta" + } + }, + { + "action": "query", + "id": "repeat-beta", + "args": { + "query": " BETA " + } + }, + { + "advance": 120 + }, + { + "checkpoint": "cached-beta-cancels-debounce" + } + ] + }, + { + "id": "settings-repo-metadata-single-host", + "operation": "settings.repo-metadata", + "version": 1, + "family": "settings.repo-metadata", + "sites": ["mobile/src/host-screen/use-host-repo-metadata.ts"], + "schedules": ["single-ssh-host"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "displayName": "Remote", + "connectionId": "ssh-1" + }, + { + "id": "repo-2", + "displayName": "Remote folder", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "checkpoint": "single-host-without-label-lookups" + } + ] + }, + { + "id": "settings-bot-overrides-refresh-refused", + "operation": "settings.bot-overrides", + "version": 1, + "family": "settings.bot-overrides", + "sites": ["mobile/src/session/use-pr-bot-author-overrides.ts"], + "schedules": ["success-then-refused"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "checkpoint": "settled" + }, + { + "action": "reset", + "id": "refresh" + }, + { + "checkpoint": "refresh-pending" + }, + { + "complete": "settings.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "Settings refused" + } + } + }, + { + "checkpoint": "refused-retains-overrides" + } + ] + }, + { + "id": "settings-workspace-context-refuse-after-data", + "operation": "settings.workspace-context", + "version": 1, + "family": "settings.workspace-context", + "sites": ["mobile/src/components/use-new-workspace-runtime-context.ts"], + "schedules": ["success-then-refused"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "ui.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + }, + { + "checkpoint": "data-present" + }, + { + "action": "blur", + "id": "blur" + }, + { + "action": "reset", + "id": "revisit" + }, + { + "checkpoint": "refresh-pending" + }, + { + "complete": "settings.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "ui.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "refused-after-data" + } + ] + }, + { + "id": "settings-home-providers-refuse-after-data", + "operation": "settings.home-providers", + "version": 1, + "family": "settings.home-providers", + "sites": ["mobile/src/home/mobile-home-host-requests.ts"], + "schedules": ["success-then-refused"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + }, + { + "checkpoint": "data-present" + }, + { + "action": "load", + "id": "reload" + }, + { + "checkpoint": "refresh-pending" + }, + { + "complete": "settings.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "preflight.check#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "refused-after-data" + } + ] + }, + { + "id": "settings-resume-metadata-refuse-after-data", + "operation": "settings.resume-metadata", + "version": 1, + "family": "settings.resume-metadata", + "sites": ["mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx"], + "schedules": ["success-then-refused"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [] + } + } + }, + { + "complete": "folderWorkspace.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + }, + { + "complete": "projectGroup.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "groups": [] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "worktree.ps#1", + "params": { + "limit": 10000, + "supportsWorktreeVisibilitySourceDefaults": true + }, + "reply": { + "ok": true, + "result": { + "worktrees": [] + } + } + }, + { + "checkpoint": "settled" + }, + { + "checkpoint": "data-present" + }, + { + "action": "load", + "id": "reload" + }, + { + "checkpoint": "refresh-pending" + }, + { + "complete": "repo.list#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [] + } + } + }, + { + "complete": "folderWorkspace.list#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "folderWorkspaces": [] + } + } + }, + { + "complete": "projectGroup.list#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "groups": [] + } + } + }, + { + "complete": "settings.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "worktree.ps#2", + "params": { + "limit": 10000, + "supportsWorktreeVisibilitySourceDefaults": true + }, + "reply": { + "ok": true, + "result": { + "worktrees": [] + } + } + }, + { + "checkpoint": "refused-after-data" + } + ] + }, + { + "id": "settings-repo-metadata-refuse-after-data", + "operation": "settings.repo-metadata", + "version": 1, + "family": "settings.repo-metadata", + "sites": ["mobile/src/host-screen/use-host-repo-metadata.ts"], + "schedules": ["success-then-refused"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "action": "load", + "id": "load" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "displayName": "Local", + "connectionId": null + }, + { + "id": "repo-2", + "displayName": "Remote", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "ssh.listTargetSummaries#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "host.platform#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "platform": "linux" + } + } + }, + { + "checkpoint": "settled" + }, + { + "checkpoint": "data-present" + }, + { + "action": "load", + "id": "reload" + }, + { + "checkpoint": "refresh-pending" + }, + { + "complete": "repo.list#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "displayName": "Local", + "connectionId": null + }, + { + "id": "repo-2", + "displayName": "Remote", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "ssh.listTargetSummaries#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "targets": [ + { + "id": "ssh-1", + "label": "SSH" + } + ] + } + } + }, + { + "complete": "settings.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "host.platform#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "platform": "linux" + } + } + }, + { + "checkpoint": "refused-after-data" + } + ] + }, + { + "id": "settings-task-hydration-refuse-after-data", + "operation": "settings.task-hydration", + "version": 1, + "family": "settings.task-hydration", + "sites": ["mobile/src/tasks/use-mobile-tasks-runtime-hydration.tsx"], + "schedules": ["success-then-refused"], + "steps": [ + { + "action": "mount", + "id": "mount" + }, + { + "complete": "status.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + }, + { + "checkpoint": "settings-pending" + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "settings": { + "disabledTuiAgents": ["claude"], + "defaultTuiAgent": "codex", + "prBotAuthorOverrides": ["bot-user"], + "visibleTaskProviders": ["github", "linear"], + "hostSettingOverrides": {} + } + } + } + }, + { + "complete": "ui.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "settled" + }, + { + "checkpoint": "data-present" + }, + { + "action": "remount", + "id": "revisit" + }, + { + "checkpoint": "refresh-pending" + }, + { + "complete": "status.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "capabilities": ["mobile.tasks.v1"] + } + } + }, + { + "complete": "settings.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "ui.get#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "ui": {} + } + } + }, + { + "complete": "preflight.check#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "glab": { + "installed": false + } + } + } + }, + { + "complete": "linear.status#2", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "connected": false + } + } + }, + { + "checkpoint": "refused-after-data" + } + ] + }, + { + "id": "probe-new-tab-both-refused", + "operation": "settings.new-tab-agents", + "version": 1, + "family": "settings-agent-read", + "sites": ["mobile/src/session/mobile-new-tab-agent-loader.ts"], + "schedules": ["both-refused"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "pending" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "preflight.detectRemoteAgents#1", + "params": { + "connectionId": "ssh-1" + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "agents refused" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "probe-new-tab-refused-sibling-rejects", + "operation": "settings.new-tab-agents", + "version": 1, + "family": "settings-agent-read", + "sites": ["mobile/src/session/mobile-new-tab-agent-loader.ts"], + "schedules": ["refused-sibling-rejects"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "pending" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "settings refused" + } + } + }, + { + "complete": "preflight.detectRemoteAgents#1", + "params": { + "connectionId": "ssh-1" + }, + "reject": { + "message": "agents disconnected", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "probe-new-tab-rejects-sibling-refused", + "operation": "settings.new-tab-agents", + "version": 1, + "family": "settings-agent-read", + "sites": ["mobile/src/session/mobile-new-tab-agent-loader.ts"], + "schedules": ["rejects-sibling-refused"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "pending" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reject": { + "message": "settings disconnected", + "deliveryUnknown": true + } + }, + { + "complete": "preflight.detectRemoteAgents#1", + "params": { + "connectionId": "ssh-1" + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "agents refused" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "probe-new-tab-null-sibling-refused", + "operation": "settings.new-tab-agents", + "version": 1, + "family": "settings-agent-read", + "sites": ["mobile/src/session/mobile-new-tab-agent-loader.ts"], + "schedules": ["null-sibling-refused"], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "pending" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo-1", + "connectionId": "ssh-1" + } + ] + } + } + }, + { + "complete": "settings.get#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": null + } + }, + { + "complete": "preflight.detectRemoteAgents#1", + "params": { + "connectionId": "ssh-1" + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "agents refused" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-base-ref-default", + "operation": "source-control.branch-base-ref", + "version": 1, + "family": "git.base-ref-chain", + "sites": ["mobile/src/source-control/mobile-branch-base-ref.ts"], + "schedules": [], + "steps": [ + { + "action": "resolve", + "id": "resolve" + }, + { + "checkpoint": "requests-pending" + }, + { + "complete": "worktree.show#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "worktree": { + "baseRef": " " + } + } + } + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo42", + "worktreeBaseRef": null + } + ] + } + } + }, + { + "checkpoint": "barrier-settled" + }, + { + "complete": "repo.baseRefDefault#1", + "params": { + "repo": "id:repo42" + }, + "reply": { + "ok": true, + "result": { + "defaultBaseRef": " origin/main " + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-base-ref-worktree-hit", + "operation": "source-control.branch-base-ref", + "version": 1, + "family": "git.base-ref-chain", + "sites": ["mobile/src/source-control/mobile-branch-base-ref.ts"], + "schedules": [], + "steps": [ + { + "action": "resolve", + "id": "resolve" + }, + { + "complete": "worktree.show#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "worktree": { + "baseRef": "origin/dev" + } + } + } + }, + { + "checkpoint": "repo-list-outstanding" + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [] + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-base-ref-repo-fallback", + "operation": "source-control.branch-base-ref", + "version": 1, + "family": "git.base-ref-chain", + "sites": ["mobile/src/source-control/mobile-branch-base-ref.ts"], + "schedules": [], + "steps": [ + { + "action": "resolve", + "id": "resolve" + }, + { + "complete": "worktree.show#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "no worktree" + } + } + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": true, + "result": { + "repos": [ + { + "id": "repo42", + "worktreeBaseRef": " origin/rel " + } + ] + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-base-ref-unavailable", + "operation": "source-control.branch-base-ref", + "version": 1, + "family": "git.base-ref-chain", + "sites": ["mobile/src/source-control/mobile-branch-base-ref.ts"], + "schedules": [], + "steps": [ + { + "action": "resolve", + "id": "resolve" + }, + { + "complete": "worktree.show#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": false, + "error": { + "code": "method_not_found", + "message": "Unknown method" + } + } + }, + { + "complete": "repo.list#1", + "params": { + "$undefined": true + }, + "reply": { + "ok": false, + "error": { + "code": "forbidden", + "message": "nope" + } + } + }, + { + "complete": "repo.baseRefDefault#1", + "params": { + "repo": "id:repo42" + }, + "reply": { + "ok": false, + "error": { + "code": "forbidden", + "message": "git is not available to mobile clients" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-history-loaded", + "operation": "source-control.git-history", + "version": 1, + "family": "git.history-read", + "sites": ["mobile/src/source-control/mobile-git-history.ts"], + "schedules": [], + "steps": [ + { + "action": "load", + "id": "load" + }, + { + "checkpoint": "pending" + }, + { + "complete": "git.history#1", + "params": { + "worktree": "id:repo42::/p", + "limit": 50 + }, + "reply": { + "ok": true, + "result": { + "items": [ + { + "id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "displayId": "aaaaaaa", + "subject": "first", + "author": "dev", + "parentIds": ["bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"], + "timestamp": 1767222000000 + }, + { + "id": "cccccccccccccccccccccccccccccccccccccccc", + "subject": "", + "parentIds": [], + "timestamp": null + } + ] + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-commit-message-generated", + "operation": "source-control.commit-message", + "version": 1, + "family": "git.commit-message-ai", + "sites": ["mobile/src/source-control/mobile-commit-message-ai.ts"], + "schedules": [], + "steps": [ + { + "action": "generate", + "id": "generate" + }, + { + "checkpoint": "pending" + }, + { + "complete": "git.generateCommitMessage#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "success": true, + "message": "feat: recorded" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-commit-message-canceled", + "operation": "source-control.commit-message", + "version": 1, + "family": "git.commit-message-ai", + "sites": ["mobile/src/source-control/mobile-commit-message-ai.ts"], + "schedules": [], + "steps": [ + { + "action": "generate", + "id": "generate" + }, + { + "complete": "git.generateCommitMessage#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "success": false, + "error": "", + "canceled": true + } + } + }, + { + "checkpoint": "generate-settled" + }, + { + "action": "cancel", + "id": "cancel" + }, + { + "complete": "git.cancelGenerateCommitMessage#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": false, + "error": { + "code": "internal", + "message": "late" + } + } + }, + { + "checkpoint": "cancel-settled" + } + ] + }, + { + "id": "sc-commit-message-cancel-rejected", + "operation": "source-control.commit-message", + "version": 1, + "family": "git.commit-message-ai", + "sites": ["mobile/src/source-control/mobile-commit-message-ai.ts"], + "schedules": [], + "steps": [ + { + "action": "cancel", + "id": "cancel" + }, + { + "complete": "git.cancelGenerateCommitMessage#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reject": { + "message": "transport failure", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-pr-link-set", + "operation": "source-control.pr-link", + "version": 1, + "family": "worktree.review-link", + "sites": ["mobile/src/source-control/mobile-pr-link.ts"], + "schedules": [], + "steps": [ + { + "action": "link", + "id": "link" + }, + { + "checkpoint": "pending" + }, + { + "complete": "worktree.set#1", + "params": { + "worktree": "id:repo42::/p", + "linkedPR": 12 + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-pr-link-hosted-review", + "operation": "source-control.pr-link", + "version": 1, + "family": "worktree.review-link", + "sites": ["mobile/src/source-control/mobile-pr-link.ts"], + "schedules": [], + "steps": [ + { + "action": "link-review", + "id": "link-review" + }, + { + "complete": "worktree.set#1", + "params": { + "worktree": "id:repo42::/p", + "baseRef": "origin/release", + "linkedGitLabMR": 12 + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "action": "unlink", + "id": "unlink" + }, + { + "complete": "worktree.set#2", + "params": { + "worktree": "id:repo42::/p", + "linkedPR": null + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-pr-link-read", + "operation": "source-control.pr-link", + "version": 1, + "family": "worktree.review-link", + "sites": ["mobile/src/source-control/mobile-pr-link.ts"], + "schedules": [], + "steps": [ + { + "action": "read", + "id": "read" + }, + { + "complete": "worktree.show#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "worktree": { + "linkedPR": 7 + } + } + } + }, + { + "checkpoint": "read-settled" + }, + { + "action": "read", + "id": "read-again" + }, + { + "complete": "worktree.show#2", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": null + } + }, + { + "checkpoint": "null-result-settled" + } + ] + }, + { + "id": "sc-reveal-first-poll", + "operation": "source-control.session-diff-reveal", + "version": 1, + "family": "session.tab-reveal", + "sites": ["mobile/src/source-control/reveal-mobile-source-control-session-diff.ts"], + "schedules": [], + "steps": [ + { + "action": "reveal", + "id": "reveal" + }, + { + "checkpoint": "list-pending" + }, + { + "complete": "session.tabs.list#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "tabs": [ + { + "id": "tab-term", + "type": "terminal" + }, + { + "id": "tab-other", + "type": "file", + "mode": "diff", + "relativePath": "src/other.ts" + }, + { + "id": "tab-1", + "type": "file", + "mode": "diff", + "relativePath": "src/app.ts", + "diffSource": "unstaged" + } + ] + } + } + }, + { + "checkpoint": "activate-pending" + }, + { + "complete": "session.tabs.activate#1", + "params": { + "worktree": "id:repo42::/p", + "tabId": "tab-1", + "notifyClients": false, + "navigation": "caller", + "intent": "user" + }, + "reply": { + "ok": true, + "result": { + "activeTabId": "tab-1" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-reveal-timeout", + "operation": "source-control.session-diff-reveal", + "version": 1, + "family": "session.tab-reveal", + "sites": ["mobile/src/source-control/reveal-mobile-source-control-session-diff.ts"], + "schedules": [], + "steps": [ + { + "action": "reveal", + "id": "reveal" + }, + { + "complete": "session.tabs.list#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "no tabs" + } + } + }, + { + "advance": 300 + }, + { + "complete": "session.tabs.list#2", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "tabs": [] + } + } + }, + { + "checkpoint": "second-poll-empty" + }, + { + "advance": 600 + }, + { + "complete": "session.tabs.list#3", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "tabs": [ + { + "id": 1 + } + ] + } + } + }, + { + "advance": 900 + }, + { + "complete": "session.tabs.list#4", + "params": { + "worktree": "id:repo42::/p" + }, + "reject": { + "message": "transport failure", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-review-status-normalized", + "operation": "source-control.review-git-preparation", + "version": 1, + "family": "git.review-preparation", + "sites": ["mobile/src/source-control/mobile-hosted-review-git-preparation.ts"], + "schedules": [], + "steps": [ + { + "action": "status", + "id": "status" + }, + { + "checkpoint": "pending" + }, + { + "complete": "git.status#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "branch": "feature", + "head": "abc1234", + "entries": [ + { + "path": "src/app.ts", + "status": "modified", + "area": "staged" + }, + { + "path": "src/new.ts", + "status": "untracked", + "area": "untracked" + } + ], + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-review-status-entries-not-array", + "operation": "source-control.review-git-preparation", + "version": 1, + "family": "git.review-preparation", + "sites": ["mobile/src/source-control/mobile-hosted-review-git-preparation.ts"], + "schedules": [], + "steps": [ + { + "action": "status", + "id": "status" + }, + { + "complete": "git.status#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "entries": "nope", + "branch": "feature" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-review-commit", + "operation": "source-control.review-git-preparation", + "version": 1, + "family": "git.review-preparation", + "sites": ["mobile/src/source-control/mobile-hosted-review-git-preparation.ts"], + "schedules": [], + "steps": [ + { + "action": "commit", + "id": "commit" + }, + { + "complete": "git.commit#1", + "params": { + "worktree": "id:repo42::/p", + "message": "recorded message" + }, + "reply": { + "ok": true, + "result": { + "success": true, + "commit": "abc1234" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-review-commit-inner-failure", + "operation": "source-control.review-git-preparation", + "version": 1, + "family": "git.review-preparation", + "sites": ["mobile/src/source-control/mobile-hosted-review-git-preparation.ts"], + "schedules": [], + "steps": [ + { + "action": "commit", + "id": "commit" + }, + { + "complete": "git.commit#1", + "params": { + "worktree": "id:repo42::/p", + "message": "recorded message" + }, + "reply": { + "ok": true, + "result": { + "success": false, + "error": "nothing staged" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-review-commit-refused-empty-message", + "operation": "source-control.review-git-preparation", + "version": 1, + "family": "git.review-preparation", + "sites": ["mobile/src/source-control/mobile-hosted-review-git-preparation.ts"], + "schedules": [], + "steps": [ + { + "action": "commit", + "id": "commit" + }, + { + "complete": "git.commit#1", + "params": { + "worktree": "id:repo42::/p", + "message": "recorded message" + }, + "reply": { + "ok": false, + "error": { + "code": "internal", + "message": "" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-review-commit-rejected", + "operation": "source-control.review-git-preparation", + "version": 1, + "family": "git.review-preparation", + "sites": ["mobile/src/source-control/mobile-hosted-review-git-preparation.ts"], + "schedules": [], + "steps": [ + { + "action": "commit", + "id": "commit" + }, + { + "complete": "git.commit#1", + "params": { + "worktree": "id:repo42::/p", + "message": "recorded message" + }, + "reject": { + "message": "connection lost", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-prerequisite-push", + "operation": "source-control.remote-prerequisite", + "version": 1, + "family": "git.remote-prerequisite", + "sites": ["mobile/src/source-control/mobile-hosted-review-remote-prerequisite.ts"], + "schedules": [], + "steps": [ + { + "action": "apply", + "id": "apply", + "args": { + "blockedReason": "needs_push" + } + }, + { + "checkpoint": "pending" + }, + { + "complete": "git.push#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-prerequisite-publish", + "operation": "source-control.remote-prerequisite", + "version": 1, + "family": "git.remote-prerequisite", + "sites": ["mobile/src/source-control/mobile-hosted-review-remote-prerequisite.ts"], + "schedules": [], + "steps": [ + { + "action": "apply", + "id": "apply", + "args": { + "blockedReason": "no_upstream" + } + }, + { + "complete": "git.push#1", + "params": { + "worktree": "id:repo42::/p", + "publish": true + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-prerequisite-force-with-lease", + "operation": "source-control.remote-prerequisite", + "version": 1, + "family": "git.remote-prerequisite", + "sites": ["mobile/src/source-control/mobile-hosted-review-remote-prerequisite.ts"], + "schedules": [], + "steps": [ + { + "action": "apply", + "id": "apply", + "args": { + "blockedReason": "needs_sync", + "patchEquivalent": true + } + }, + { + "complete": "git.push#1", + "params": { + "worktree": "id:repo42::/p", + "forceWithLease": true + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-prerequisite-skipped", + "operation": "source-control.remote-prerequisite", + "version": 1, + "family": "git.remote-prerequisite", + "sites": ["mobile/src/source-control/mobile-hosted-review-remote-prerequisite.ts"], + "schedules": [], + "steps": [ + { + "action": "apply", + "id": "apply", + "args": { + "blockedReason": "needs_sync" + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-eligibility-fetched", + "operation": "source-control.hosted-review-eligibility", + "version": 1, + "family": "hostedReview.eligibility", + "sites": ["mobile/src/source-control/mobile-hosted-review-service.ts"], + "schedules": [], + "steps": [ + { + "action": "fetch", + "id": "fetch" + }, + { + "checkpoint": "pending" + }, + { + "complete": "hostedReview.getCreationEligibility#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "branch": "feature", + "base": null, + "linkedGitHubPR": null, + "linkedGitLabMR": null + }, + "reply": { + "ok": true, + "result": { + "provider": "gitlab", + "defaultBaseRef": "main", + "title": "Host title", + "body": "Host body", + "canCreate": true, + "blockedReason": null, + "nextAction": null, + "reviewLookupOutcome": "none" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-prefill-unavailable-on-refusal", + "operation": "source-control.hosted-review-eligibility", + "version": 1, + "family": "hostedReview.eligibility", + "sites": ["mobile/src/source-control/mobile-hosted-review-service.ts"], + "schedules": [], + "steps": [ + { + "action": "prefill", + "id": "prefill" + }, + { + "complete": "hostedReview.getCreationEligibility#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "branch": "feature", + "base": null, + "linkedGitHubPR": null, + "linkedGitLabMR": null + }, + "reply": { + "ok": false, + "error": { + "code": "refused", + "message": "no eligibility" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-prefill-unavailable-on-rejection", + "operation": "source-control.hosted-review-eligibility", + "version": 1, + "family": "hostedReview.eligibility", + "sites": ["mobile/src/source-control/mobile-hosted-review-service.ts"], + "schedules": [], + "steps": [ + { + "action": "prefill", + "id": "prefill" + }, + { + "complete": "hostedReview.getCreationEligibility#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "branch": "feature", + "base": null, + "linkedGitHubPR": null, + "linkedGitLabMR": null + }, + "reject": { + "message": "transport failure", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-create-pushes-then-creates", + "operation": "source-control.hosted-review-create", + "version": 1, + "family": "hostedReview.create-chain", + "sites": [ + "mobile/src/source-control/mobile-hosted-review-service.ts", + "mobile/src/source-control/mobile-pr-link.ts" + ], + "schedules": [], + "steps": [ + { + "action": "create", + "id": "create", + "args": { + "pushBeforeCreate": true + } + }, + { + "checkpoint": "push-pending" + }, + { + "complete": "git.push#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "checkpoint": "create-pending" + }, + { + "complete": "hostedReview.create#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "provider": "github", + "base": "main", + "head": "feature", + "title": "Recorded title", + "body": "Recorded body", + "draft": false + }, + "reply": { + "ok": true, + "result": { + "ok": true, + "number": 5, + "url": "https://review.test/5" + } + } + }, + { + "checkpoint": "link-pending" + }, + { + "complete": "worktree.set#1", + "params": { + "worktree": "id:repo42::/p", + "baseRef": "main", + "linkedPR": 5 + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-create-link-failure-is-non-fatal", + "operation": "source-control.hosted-review-create", + "version": 1, + "family": "hostedReview.create-chain", + "sites": [ + "mobile/src/source-control/mobile-hosted-review-service.ts", + "mobile/src/source-control/mobile-pr-link.ts" + ], + "schedules": [], + "steps": [ + { + "action": "create", + "id": "create", + "args": {} + }, + { + "complete": "hostedReview.create#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "provider": "github", + "base": "main", + "head": "feature", + "title": "Recorded title", + "body": "Recorded body", + "draft": false + }, + "reply": { + "ok": true, + "result": { + "ok": true, + "number": 5, + "url": "https://review.test/5" + } + } + }, + { + "complete": "worktree.set#1", + "params": { + "worktree": "id:repo42::/p", + "baseRef": "main", + "linkedPR": 5 + }, + "reply": { + "ok": false, + "error": { + "code": "internal", + "message": "" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-create-existing-review", + "operation": "source-control.hosted-review-create", + "version": 1, + "family": "hostedReview.create-chain", + "sites": [ + "mobile/src/source-control/mobile-hosted-review-service.ts", + "mobile/src/source-control/mobile-pr-link.ts" + ], + "schedules": [], + "steps": [ + { + "action": "create", + "id": "create", + "args": {} + }, + { + "complete": "hostedReview.create#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "provider": "github", + "base": "main", + "head": "feature", + "title": "Recorded title", + "body": "Recorded body", + "draft": false + }, + "reply": { + "ok": true, + "result": { + "ok": false, + "error": "Create pull request failed: already exists", + "existingReview": { + "number": 9, + "url": "https://review.test/9" + } + } + } + }, + { + "complete": "worktree.set#1", + "params": { + "worktree": "id:repo42::/p", + "baseRef": "main", + "linkedPR": 9 + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-create-refused-empty-message", + "operation": "source-control.hosted-review-create", + "version": 1, + "family": "hostedReview.create-chain", + "sites": [ + "mobile/src/source-control/mobile-hosted-review-service.ts", + "mobile/src/source-control/mobile-pr-link.ts" + ], + "schedules": [], + "steps": [ + { + "action": "create", + "id": "create", + "args": {} + }, + { + "complete": "hostedReview.create#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "provider": "github", + "base": "main", + "head": "feature", + "title": "Recorded title", + "body": "Recorded body", + "draft": false + }, + "reply": { + "ok": false, + "error": { + "code": "internal", + "message": "" + } + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-create-rejected-empty-message", + "operation": "source-control.hosted-review-create", + "version": 1, + "family": "hostedReview.create-chain", + "sites": [ + "mobile/src/source-control/mobile-hosted-review-service.ts", + "mobile/src/source-control/mobile-pr-link.ts" + ], + "schedules": [], + "steps": [ + { + "action": "create", + "id": "create", + "args": {} + }, + { + "complete": "hostedReview.create#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "provider": "github", + "base": "main", + "head": "feature", + "title": "Recorded title", + "body": "Recorded body", + "draft": false + }, + "reject": { + "message": "", + "deliveryUnknown": true + } + }, + { + "checkpoint": "settled" + } + ] + }, + { + "id": "sc-create-intent-stage-commit-push-create", + "operation": "source-control.create-intent", + "version": 1, + "family": "hostedReview.create-intent", + "sites": [ + "mobile/src/source-control/mobile-hosted-review-create-intent-runner.ts", + "mobile/src/source-control/mobile-hosted-review-create-intent.ts" + ], + "schedules": [], + "steps": [ + { + "action": "run", + "id": "run", + "args": {} + }, + { + "checkpoint": "initial-status-pending" + }, + { + "complete": "git.status#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "branch": "feature", + "head": "abc1234", + "entries": [ + { + "path": "src/app.ts", + "status": "modified", + "area": "staged" + }, + { + "path": "src/new.ts", + "status": "untracked", + "area": "untracked" + } + ], + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + }, + { + "checkpoint": "stage-pending" + }, + { + "complete": "git.bulkStage#1", + "params": { + "worktree": "id:repo42::/p", + "filePaths": ["src/new.ts"] + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "complete": "git.status#2", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "branch": "feature", + "head": "abc1234", + "entries": [ + { + "path": "src/app.ts", + "status": "modified", + "area": "staged" + } + ], + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + }, + { + "checkpoint": "generate-message-pending" + }, + { + "complete": "git.generateCommitMessage#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "success": true, + "message": "feat: recorded" + } + } + }, + { + "checkpoint": "commit-pending" + }, + { + "complete": "git.commit#1", + "params": { + "worktree": "id:repo42::/p", + "message": "feat: recorded" + }, + "reply": { + "ok": true, + "result": { + "success": true + } + } + }, + { + "complete": "git.status#3", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "branch": "feature", + "head": "def5678", + "entries": [], + "upstreamStatus": { + "ahead": 1, + "behind": 0, + "hasUpstream": true + } + } + } + }, + { + "checkpoint": "prefill-pending" + }, + { + "complete": "hostedReview.getCreationEligibility#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "branch": "feature", + "base": null, + "hasUncommittedChanges": false, + "hasUpstream": true, + "ahead": 1, + "behind": 0, + "linkedGitHubPR": null, + "linkedGitLabMR": null + }, + "reply": { + "ok": true, + "result": { + "provider": "github", + "defaultBaseRef": "main", + "title": "Host title", + "body": "Host body", + "canCreate": true, + "blockedReason": "needs_push", + "nextAction": null, + "reviewLookupOutcome": "not_found" + } + } + }, + { + "checkpoint": "push-pending" + }, + { + "complete": "git.push#1", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "complete": "git.status#4", + "params": { + "worktree": "id:repo42::/p" + }, + "reply": { + "ok": true, + "result": { + "branch": "feature", + "head": "def5678", + "entries": [], + "upstreamStatus": { + "ahead": 0, + "behind": 0, + "hasUpstream": true + } + } + } + }, + { + "complete": "hostedReview.getCreationEligibility#2", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "branch": "feature", + "base": null, + "hasUncommittedChanges": false, + "hasUpstream": true, + "ahead": 0, + "behind": 0, + "linkedGitHubPR": null, + "linkedGitLabMR": null + }, + "reply": { + "ok": true, + "result": { + "provider": "github", + "defaultBaseRef": "main", + "title": "Host title", + "body": "Host body", + "canCreate": true, + "blockedReason": null, + "nextAction": null, + "reviewLookupOutcome": "not_found" + } + } + }, + { + "checkpoint": "create-pending" + }, + { + "complete": "hostedReview.create#1", + "params": { + "repo": "id:repo42", + "worktree": "id:repo42::/p", + "provider": "github", + "base": "main", + "head": "feature", + "title": "Host title", + "body": "Host body", + "draft": false + }, + "reply": { + "ok": true, + "result": { + "ok": true, + "number": 5, + "url": "https://review.test/5" + } + } + }, + { + "complete": "worktree.set#1", + "params": { + "worktree": "id:repo42::/p", + "baseRef": "main", + "linkedPR": 5 + }, + "reply": { + "ok": true, + "result": { + "ok": true + } + } + }, + { + "checkpoint": "settled" + } + ] + } + ] +} diff --git a/mobile/rpc-foundation/settings-recording-coverage.json b/mobile/rpc-foundation/settings-recording-coverage.json new file mode 100644 index 00000000000..8dca7ab2f61 --- /dev/null +++ b/mobile/rpc-foundation/settings-recording-coverage.json @@ -0,0 +1,124 @@ +{ + "manifestCommit": "1d950ab0e0", + "recordingBaseline": "aac38d698ff75ac4c8658addab48ef5a83617619", + "excludedKinds": ["device-preference"], + "operations": [ + { + "manifestOperation": "main:mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx:loadMobileResumeMetadata:settings.get:387", + "manifestScenarioIds": [ + "main:mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx:loadMobileResumeMetadata:settings.get:387:fulfilled", + "main:mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx:loadMobileResumeMetadata:settings.get:387:refused", + "main:mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx:loadMobileResumeMetadata:settings.get:387:transport-error" + ], + "scenarios": [ + "settings-resume-metadata-fulfilled", + "settings-resume-metadata-refused", + "settings-resume-metadata-transport-error" + ] + }, + { + "manifestOperation": "main:mobile/src/components/use-new-workspace-create-submit.ts:create:settings.get:91", + "manifestScenarioIds": [ + "main:mobile/src/components/use-new-workspace-create-submit.ts:create:settings.get:91:fulfilled", + "main:mobile/src/components/use-new-workspace-create-submit.ts:create:settings.get:91:refused", + "main:mobile/src/components/use-new-workspace-create-submit.ts:create:settings.get:91:transport-error" + ], + "scenarios": [ + "settings-workspace-submit-fulfilled", + "settings-workspace-submit-refused", + "settings-workspace-submit-transport-error" + ] + }, + { + "manifestOperation": "main:mobile/src/components/use-new-workspace-runtime-context.ts:useNewWorkspaceRuntimeContext:settings.get:42", + "manifestScenarioIds": [ + "main:mobile/src/components/use-new-workspace-runtime-context.ts:useNewWorkspaceRuntimeContext:settings.get:42:fulfilled", + "main:mobile/src/components/use-new-workspace-runtime-context.ts:useNewWorkspaceRuntimeContext:settings.get:42:refused", + "main:mobile/src/components/use-new-workspace-runtime-context.ts:useNewWorkspaceRuntimeContext:settings.get:42:transport-error" + ], + "scenarios": [ + "settings-workspace-context-fulfilled", + "settings-workspace-context-refused", + "settings-workspace-context-transport-error" + ] + }, + { + "manifestOperation": "main:mobile/src/home/mobile-home-host-requests.ts:fetchMobileHomeTaskProviders:settings.get:76", + "manifestScenarioIds": [ + "main:mobile/src/home/mobile-home-host-requests.ts:fetchMobileHomeTaskProviders:settings.get:76:fulfilled", + "main:mobile/src/home/mobile-home-host-requests.ts:fetchMobileHomeTaskProviders:settings.get:76:refused", + "main:mobile/src/home/mobile-home-host-requests.ts:fetchMobileHomeTaskProviders:settings.get:76:transport-error" + ], + "scenarios": [ + "settings-home-providers-fulfilled", + "settings-home-providers-refused", + "settings-home-providers-transport-error" + ] + }, + { + "manifestOperation": "main:mobile/src/host-screen/use-host-repo-metadata.ts:fetchRepoMetadata:settings.get:124", + "manifestScenarioIds": [ + "main:mobile/src/host-screen/use-host-repo-metadata.ts:fetchRepoMetadata:settings.get:124:fulfilled", + "main:mobile/src/host-screen/use-host-repo-metadata.ts:fetchRepoMetadata:settings.get:124:refused", + "main:mobile/src/host-screen/use-host-repo-metadata.ts:fetchRepoMetadata:settings.get:124:transport-error" + ], + "scenarios": [ + "settings-repo-metadata-fulfilled", + "settings-repo-metadata-refused", + "settings-repo-metadata-transport-error" + ] + }, + { + "manifestOperation": "main:mobile/src/session/mobile-new-tab-agent-loader.ts:loadMobileNewTabAgentOptions:settings.get:26", + "manifestScenarioIds": [ + "main:mobile/src/session/mobile-new-tab-agent-loader.ts:loadMobileNewTabAgentOptions:settings.get:26:fulfilled", + "main:mobile/src/session/mobile-new-tab-agent-loader.ts:loadMobileNewTabAgentOptions:settings.get:26:refused", + "main:mobile/src/session/mobile-new-tab-agent-loader.ts:loadMobileNewTabAgentOptions:settings.get:26:transport-error" + ], + "scenarios": [ + "settings-new-tab-ssh", + "settings-new-tab-refused", + "settings-new-tab-transport-error" + ] + }, + { + "manifestOperation": "main:mobile/src/session/use-pr-bot-author-overrides.ts:usePRBotAuthorOverrides:settings.get:35", + "manifestScenarioIds": [ + "main:mobile/src/session/use-pr-bot-author-overrides.ts:usePRBotAuthorOverrides:settings.get:35:fulfilled", + "main:mobile/src/session/use-pr-bot-author-overrides.ts:usePRBotAuthorOverrides:settings.get:35:refused", + "main:mobile/src/session/use-pr-bot-author-overrides.ts:usePRBotAuthorOverrides:settings.get:35:transport-error" + ], + "scenarios": [ + "settings-bot-overrides-fulfilled", + "settings-bot-overrides-refused", + "settings-bot-overrides-transport-error" + ] + }, + { + "manifestOperation": "main:mobile/src/tasks/use-mobile-tasks-runtime-hydration.tsx:hydrateTaskState:settings.get:253", + "manifestScenarioIds": [ + "main:mobile/src/tasks/use-mobile-tasks-runtime-hydration.tsx:hydrateTaskState:settings.get:253:fulfilled", + "main:mobile/src/tasks/use-mobile-tasks-runtime-hydration.tsx:hydrateTaskState:settings.get:253:refused", + "main:mobile/src/tasks/use-mobile-tasks-runtime-hydration.tsx:hydrateTaskState:settings.get:253:transport-error" + ], + "scenarios": [ + "settings-task-hydration-fulfilled", + "settings-task-hydration-refused", + "settings-task-hydration-transport-error" + ] + }, + { + "manifestOperation": "main:mobile/src/tasks/use-mobile-tasks-workspace-create-actions.tsx:createWorkspace:settings.get:75", + "manifestScenarioIds": [ + "main:mobile/src/tasks/use-mobile-tasks-workspace-create-actions.tsx:createWorkspace:settings.get:75:fulfilled", + "main:mobile/src/tasks/use-mobile-tasks-workspace-create-actions.tsx:createWorkspace:settings.get:75:refused", + "main:mobile/src/tasks/use-mobile-tasks-workspace-create-actions.tsx:createWorkspace:settings.get:75:transport-error" + ], + "scenarios": [ + "settings-task-workspace-fulfilled", + "settings-task-workspace-refused", + "settings-task-workspace-transport-error" + ] + } + ] +} diff --git a/mobile/scripts/rpc-recording.mts b/mobile/scripts/rpc-recording.mts new file mode 100644 index 00000000000..392a086e621 --- /dev/null +++ b/mobile/scripts/rpc-recording.mts @@ -0,0 +1,70 @@ +import { createRequire } from 'node:module' +import { resolve } from 'node:path' +import { runProcess } from '../../src/shared/child-process/run-process.ts' +import { readScenarios } from '../src/test-support/rpc-recording/scenario-input.ts' + +if (process.argv[2] !== '--record' || process.env.RPC_FOUNDATION_RECORD !== '1') { + throw new Error('Recording requires --record and RPC_FOUNDATION_RECORD=1') +} +const root = resolve(import.meta.dirname, '../..') +const input = readScenarios(resolve(root, 'mobile/rpc-foundation/pilot-scenarios.json')) +const baseline = await runProcess({ + program: 'git', + args: [ + 'diff', + '--quiet', + input.baseline, + '--', + 'mobile/src', + 'src/shared', + 'mobile/pnpm-lock.yaml', + // Only the recorder is exempt, and every golden pins `recorderSha256` over it instead. + ':!mobile/src/test-support/rpc-recording' + ], + cwd: root +}) +if (baseline.code !== 0) { + throw new Error('Product sources or lockfile differ from the pinned main baseline') +} +// Why a second check: `git diff` only sees tracked paths, so an untracked module under the +// guarded trees can change resolution while the baseline check still passes — the golden would +// then carry a pinned baseline header it did not actually record against. +const untracked = await runProcess({ + program: 'git', + args: [ + 'ls-files', + '--others', + '--exclude-standard', + '--', + 'mobile/src', + 'src/shared', + ':!mobile/src/test-support/rpc-recording' + ], + cwd: root +}) +if (untracked.code !== 0) { + throw new Error(`Could not enumerate untracked product sources: ${untracked.stderr}`) +} +if (untracked.stdout.trim() !== '') { + throw new Error( + `Untracked product sources would not be pinned by the baseline:\n${untracked.stdout.trim()}` + ) +} +const require = createRequire(resolve(root, 'mobile/package.json')) +const result = await runProcess({ + program: process.execPath, + args: [ + resolve(require.resolve('vitest/package.json'), '../vitest.mjs'), + 'run', + 'src/test-support/rpc-recording/pilot-recordings.test.ts', + 'src/test-support/rpc-recording/family-recordings.test.ts' + ], + cwd: resolve(root, 'mobile'), + timeoutMs: 120_000, + env: { ...process.env, ORCA_BACKGROUND_LAUNCH: '1', RPC_FOUNDATION_MODE: '--record' } +}) +process.stdout.write(result.stdout) +process.stderr.write(result.stderr) +if (result.code !== 0) { + process.exitCode = 1 +} diff --git a/mobile/src/session/MobileNativeChatSessionOptionRows.test.ts b/mobile/src/session/MobileNativeChatSessionOptionRows.test.ts new file mode 100644 index 00000000000..241b1a6434c --- /dev/null +++ b/mobile/src/session/MobileNativeChatSessionOptionRows.test.ts @@ -0,0 +1,100 @@ +import { createElement } from 'react' +import { act, create, type ReactTestRenderer } from 'react-test-renderer' +import { describe, expect, it, vi } from 'vitest' +import type { SessionOptionDescriptor } from '../../../src/shared/native-chat-session-options' +import { DescriptorRows } from './MobileNativeChatSessionOptionRows' + +vi.mock('react-native', () => ({ + Pressable: 'Pressable', + StyleSheet: { create: (styles: unknown) => styles, hairlineWidth: 1 }, + Switch: 'Switch', + Text: 'Text', + View: 'View' +})) +vi.mock('lucide-react-native', () => ({ + Check: 'Check', + ChevronDown: 'ChevronDown', + ChevronRight: 'ChevronRight' +})) + +const FAST: SessionOptionDescriptor = { + id: 'fastMode', + label: 'Fast mode', + category: 'mode', + kind: { type: 'boolean', currentValue: false }, + valueSource: 'reported', + transport: 'catalog', + settable: true +} + +function renderRows(descriptor: SessionOptionDescriptor): ReactTestRenderer { + let renderer: ReactTestRenderer | null = null + act(() => { + renderer = create( + createElement(DescriptorRows, { + descriptor, + disabled: false, + onSetOption: vi.fn(), + onInvokeAction: vi.fn() + }) + ) + }) + if (!renderer) { + throw new Error('renderer did not mount') + } + return renderer +} + +const textOf = (renderer: ReactTestRenderer): string[] => + renderer.root.findAllByType('Text').flatMap((node) => { + const children = node.props.children + return typeof children === 'string' ? [children] : [] + }) + +describe('DescriptorRows boolean', () => { + it('renders one switch and no unknown-value caption', () => { + const renderer = renderRows({ ...FAST, valueSource: 'unknown' }) + expect(renderer.root.findAllByType('Switch')).toHaveLength(1) + expect(textOf(renderer)).not.toContain('Current value unknown') + }) + + // Both arms: `default` and `unreported` make opposite claims, and only + // `unreported` is reachable in the structured lane, so one arm proves nothing. + it.each([ + { + name: 'a live unreported boolean is never labelled a default', + valueSource: 'unknown', + transport: 'agent-session', + shown: 'Not reported', + hidden: 'Default' + }, + { + name: 'a draft catalog default says so', + valueSource: 'default', + transport: 'catalog', + shown: 'Default', + hidden: 'Not reported' + } + ] as const)('$name', ({ valueSource, transport, shown, hidden }) => { + const renderer = renderRows({ ...FAST, valueSource, transport }) + expect(textOf(renderer)).toContain(shown) + expect(textOf(renderer)).not.toContain(hidden) + // The marker qualifies the value; it must not become part of the control's name. + expect(renderer.root.findByType('Switch').props.accessibilityLabel).toBe('Fast mode') + }) + + it('drops the marker once something has picked the value', () => { + const labels = textOf(renderRows(FAST)) + expect(labels).not.toContain('Default') + expect(labels).not.toContain('Not reported') + }) + + it('shows the resolved value on the switch itself', () => { + const renderer = renderRows({ + ...FAST, + kind: { type: 'boolean', currentValue: true }, + valueSource: 'unknown' + }) + expect(renderer.root.findByType('Switch').props.value).toBe(true) + }) +}) diff --git a/mobile/src/session/MobileNativeChatSessionOptionRows.tsx b/mobile/src/session/MobileNativeChatSessionOptionRows.tsx index 468403b7304..c4994113a33 100644 --- a/mobile/src/session/MobileNativeChatSessionOptionRows.tsx +++ b/mobile/src/session/MobileNativeChatSessionOptionRows.tsx @@ -1,12 +1,14 @@ // The pill and choice-row primitives the session-option card is built from, kept // beside it so the card file stays about layout and apply wiring. -import { Pressable, StyleSheet, Text, View } from 'react-native' +import { Pressable, StyleSheet, Switch, Text, View } from 'react-native' import { Check, ChevronDown, ChevronRight } from 'lucide-react-native' import { colors, radii, spacing, typography } from '../theme/mobile-theme' -import type { - SessionOptionDescriptor, - SessionOptionValue +import { + sessionOptionValueMarker, + type SessionOptionDescriptor, + type SessionOptionValueMarker, + type SessionOptionValue } from '../../../src/shared/native-chat-session-options' /** Muted one-liner above a group — dispatch state, or why a row is locked. */ @@ -93,6 +95,42 @@ function ChoiceRow({ ) } +function ToggleRow({ + label, + checked, + marker, + disabled, + grouped, + onToggle +}: { + label: string + checked: boolean + /** Where the rendered value came from, or null once something picked it. */ + marker: SessionOptionValueMarker | null + disabled: boolean + grouped: boolean + onToggle: (next: boolean) => void +}): React.JSX.Element { + return ( + + + {label} + + {marker ? ( + {marker === 'default' ? 'Default' : 'Not reported'} + ) : null} + + + ) +} + function ActionRow({ label, disabled, @@ -191,31 +229,19 @@ export function DescriptorRows({ /> ) } - // Unknown booleans leave both radios unselected instead of inventing truth. + // One switch, not an On/Off pair: the option is binary. The value always + // renders; the marker is what keeps an unpicked one from reading as confirmed, + // since the switch itself cannot say "nobody said". if (descriptor.kind.type === 'boolean') { - const current = descriptor.kind.currentValue return ( - <> - {current === undefined ? ( - Current value unknown — pick On or Off - ) : null} - onSetOption(true)} - /> - onSetOption(false)} - /> - + onSetOption(next)} + /> ) } const { currentValue, choices } = descriptor.kind @@ -269,6 +295,10 @@ const styles = StyleSheet.create({ paddingHorizontal: spacing.md, paddingBottom: spacing.xs }, + rowMarker: { + color: colors.textMuted, + fontSize: typography.metaSize + }, row: { flexDirection: 'row', gap: spacing.sm, diff --git a/mobile/src/session/mobile-native-chat-session-option-labels.ts b/mobile/src/session/mobile-native-chat-session-option-labels.ts index 85d1cc3ea49..ab5c28b8973 100644 --- a/mobile/src/session/mobile-native-chat-session-option-labels.ts +++ b/mobile/src/session/mobile-native-chat-session-option-labels.ts @@ -43,17 +43,16 @@ export function mobileModelPillLabel(descriptor: SessionOptionDescriptor): strin } export function mobileSessionOptionSummaryValue(descriptor: SessionOptionDescriptor): string { + // A boolean always has a value, so the summary states it and lets the sheet's + // marker say whether anything confirmed it. Reading "Not set" here while the + // sheet showed the switch on made the two screens disagree. + if (descriptor.kind.type === 'boolean') { + return descriptor.kind.currentValue ? 'On' : 'Off' + } if (descriptor.valueSource === 'unknown') { return 'Not set' } - if (descriptor.kind.type === 'select') { - return selectedChoiceLabel(descriptor) ?? 'Not set' - } - return descriptor.kind.currentValue === undefined - ? 'Not set' - : descriptor.kind.currentValue - ? 'On' - : 'Off' + return selectedChoiceLabel(descriptor) ?? 'Not set' } export function mobileOptionsPillLabel(descriptors: readonly SessionOptionDescriptor[]): string { diff --git a/mobile/src/session/mobile-session-route-parity.test.ts b/mobile/src/session/mobile-session-route-parity.test.ts index 76435561664..7d0c5c6de46 100644 --- a/mobile/src/session/mobile-session-route-parity.test.ts +++ b/mobile/src/session/mobile-session-route-parity.test.ts @@ -62,11 +62,11 @@ const HOST_COMPONENT_NAMES = new Set([ 'View' ]) -const HEAD_MAIN_HOOK_SHA256 = 'c3e33699e3e3fa7e24408f3d4946fcc451e9b9419442d985c4ccde01782e5114' -const HEAD_HOOK_BINDING_SHA256 = '7f907e028893721d662eeee0aa9002ad1e00359948f39fb148d274596cd9b3c0' +const HEAD_MAIN_HOOK_SHA256 = '11cd92aec686a6e47b23114ec31da86152a850b064821578b165fabfbce53b27' +const HEAD_HOOK_BINDING_SHA256 = 'f8bce7101a26b4d794bb58dee54702424a4965cc81dec5c758ca56cd5a6f4ce8' const HEAD_CALLBACK_IDENTITY_SHA256 = '2a9e4825df007f6ef53b81aa5004991d6318eee7507b44d625c07e630be432eb' -const HEAD_CALLBACK_BODY_SHA256 = 'af7f3c62954250d4be7ee432ecd10dc2689792aad8230fed2d1d68bbc892d776' +const HEAD_CALLBACK_BODY_SHA256 = '85c4f4605e66c45e2b6bc7de739cb3493d9e2d0db9c9242c379db8ed34a8cefe' const HEAD_EFFECT_SHA256 = 'd9ebfaabc1e79773cdada7ab370b20459ed972f1f8edce1652199f4d0391cd13' const HEAD_CONTENT_HOOK_SHA256 = '9c3b612fef3f370d66873aefdbe1d701f20cb64ded31fef5cc45fde6f8189581' const HEAD_NESTED_FUNCTION_SHA256 = @@ -472,7 +472,7 @@ describe('mobile session route extraction parity', () => { const contentBindings = CONTENT_COMPONENT_NAMES.flatMap( (name) => readHookFacts(name, definitions).bindings ) - expect(main.hooks).toHaveLength(267) + expect(main.hooks).toHaveLength(268) expect(hash(main.hooks)).toBe(HEAD_MAIN_HOOK_SHA256) expect(hash(main.bindings)).toBe(HEAD_HOOK_BINDING_SHA256) expect(main.callbacks).toHaveLength(77) diff --git a/mobile/src/session/use-mobile-session-accessory-selection.ts b/mobile/src/session/use-mobile-session-accessory-selection.ts index 356bf11952d..ad0116cb9c6 100644 --- a/mobile/src/session/use-mobile-session-accessory-selection.ts +++ b/mobile/src/session/use-mobile-session-accessory-selection.ts @@ -14,6 +14,8 @@ import type { } from '../terminal/terminal-webview-contract' import type { createTerminalLiveAccessoryInput } from '../terminal/terminal-live-accessory-input' import { clearTerminalLiveInputFocusTimer } from '../terminal/terminal-live-input' +import { stripTerminalSelectionGutter } from '../../../src/shared/terminal-selection-gutter' +import { useTerminalCopyTrimsGutter } from '../terminal/terminal-copy-gutter-preference' import { getRepoIdFromMobileWorktreeId } from './mobile-session-route-helpers' import type { RuntimeRepoSummary } from './mobile-session-route-types' import type { MobileSessionTerminalInputModel } from './use-mobile-session-terminal-input' @@ -23,6 +25,7 @@ export function useMobileSessionAccessorySelection(scope: MobileSessionTerminalI worktreeId, isFloatingWorkspaceRoute, client, + connState, setTerminalKeyboardMetrics, setSelectModeActive, setCanPaste, @@ -41,6 +44,7 @@ export function useMobileSessionAccessorySelection(scope: MobileSessionTerminalI handleAccessoryKey, clearSessionTabActionSheetKeyboardListener } = scope + const trimsGutterRef = useTerminalCopyTrimsGutter(client, connState) // Why: hold-to-repeat matches iOS cadence (400ms then 45ms); non-repeatable keys fire once (holding is destructive). const repeatTimeoutRef = useRef | null>(null) const repeatIntervalRef = useRef | null>(null) @@ -115,7 +119,9 @@ export function useMobileSessionAccessorySelection(scope: MobileSessionTerminalI return } try { - await Clipboard.setStringAsync(text) + await Clipboard.setStringAsync( + trimsGutterRef.current ? stripTerminalSelectionGutter(text) : text + ) triggerSuccess() // Why: Android 13+ shows its own system copy toast; iOS shows none, so only iOS needs our in-app toast. if (Platform.OS === 'ios') { diff --git a/mobile/src/session/use-mobile-structured-agent-options.test.ts b/mobile/src/session/use-mobile-structured-agent-options.test.ts new file mode 100644 index 00000000000..5658cc01839 --- /dev/null +++ b/mobile/src/session/use-mobile-structured-agent-options.test.ts @@ -0,0 +1,398 @@ +import { createElement } from 'react' +import { act, create, type ReactTestRenderer } from 'react-test-renderer' +import { describe, expect, it, vi } from 'vitest' +import type { + AgentSessionOptionResult, + AgentSessionOptionsResult +} from '../../../src/shared/agent-session-wire' +import type { SessionOptionDescriptor } from '../../../src/shared/native-chat-session-options' +import type { RpcClient } from '../transport/rpc-client' +import type { + StructuredAgentSessionMutate, + StructuredAgentSessionMutationResult +} from './mobile-structured-agent-session-rpc' +import { useMobileStructuredAgentOptions } from './use-mobile-structured-agent-options' + +const OPTIONS: AgentSessionOptionsResult = { + models: [ + { + id: 'gpt-live', + label: 'GPT Live', + isDefault: true, + defaultEffort: 'medium', + efforts: [ + { value: 'medium', label: 'Medium' }, + { value: 'high', label: 'High' } + ] + }, + { + id: 'gpt-fast', + label: 'GPT Fast', + isDefault: false, + defaultEffort: 'low', + efforts: [ + { value: 'low', label: 'Low' }, + { value: 'medium', label: 'Medium' } + ] + } + ], + current: { model: 'gpt-live', effort: 'medium' } +} + +/** Session support and the provider catalog both say yes, which is the only shape + * that earns a Fast row. */ +const FAST_OPTIONS: AgentSessionOptionsResult = { + ...OPTIONS, + models: OPTIONS.models.map((model) => ({ ...model, supportsFastMode: true })), + fastModeSupport: { supported: true }, + current: { ...OPTIONS.current, fastMode: false, confirmed: ['fastMode'] } +} + +const FAST_OPTIONS_ON: AgentSessionOptionsResult = { + ...FAST_OPTIONS, + current: { ...FAST_OPTIONS.current, fastMode: true } +} + +function deferred() { + let resolve!: (value: T) => void + const promise = new Promise((accept) => { + resolve = accept + }) + return { promise, resolve } +} + +function rpcSuccess(result: unknown) { + return { id: 'rpc-1', ok: true as const, result, _meta: { runtimeId: 'runtime-1' } } +} + +type SentRequest = { method: string; params: unknown } + +/** `reads` yields what each successive `agentSession.options` call resolves to, so a test can + * make the post-write refresh disagree with the first read. */ +function optionsClient(reads: () => Promise) { + const sent: SentRequest[] = [] + const client: RpcClient = { + sendRequest: async (method: string, params?: unknown) => { + sent.push({ method, params }) + return rpcSuccess(method === 'agentSession.options' ? await reads() : {}) + }, + subscribe: () => () => {}, + updateTerminalSubscriptionViewport: () => {}, + getState: () => 'connected', + getReconnectAttempt: () => 0, + getLastConnectedAt: () => null, + onStateChange: () => () => {}, + notifyForeground: () => {}, + close: () => {} + } + const methods = (name: string) => sent.filter((entry) => entry.method === name) + return { client, sent, methods, optionReads: () => methods('agentSession.options').length } +} + +/** Resolves the queue in order and repeats the last entry, so a refresh read that a test did not + * script still answers instead of hanging. */ +function queuedReads(...results: AgentSessionOptionsResult[]) { + let index = 0 + return () => Promise.resolve(results[Math.min(index++, results.length - 1)]!) +} + +type MutateCall = { method: string; fields: Record } + +/** `next` answers the nth write. An untyped `vi.fn` is what satisfies the generic mutate + * signature: a concrete fixture cannot produce the caller's `TValue` on its own. */ +function recordingMutate( + next: (call: number) => Promise> +) { + const calls: MutateCall[] = [] + const mock = vi.fn() + mock.mockImplementation( + (method: string, _fingerprintMethod: string, fields: Record) => { + calls.push({ method, fields }) + return next(calls.length - 1) + } + ) + const mutate: StructuredAgentSessionMutate = mock + return { calls, mutate } +} + +function accepted( + value: AgentSessionOptionResult, + sameFence: boolean +): StructuredAgentSessionMutationResult { + return { status: 'accepted', value, sameFence } +} + +type Controller = ReturnType + +type ProbeProps = { + agent: string | null + client: RpcClient | null + sessionId: string | null + fence: number | null + mutate: StructuredAgentSessionMutate + onRender: (controller: Controller) => void +} + +function Probe(props: ProbeProps): null { + props.onRender( + useMobileStructuredAgentOptions({ + agent: props.agent, + client: props.client, + sessionId: props.sessionId, + enabled: true, + fence: props.fence, + mutate: props.mutate + }) + ) + return null +} + +async function settle() { + await act(async () => { + await Promise.resolve() + await Promise.resolve() + }) +} + +async function mountOptions(props: Omit) { + let rendered: Controller | null = null + const onRender = (controller: Controller) => { + rendered = controller + } + let renderer: ReactTestRenderer | null = null + await act(async () => { + renderer = create(createElement(Probe, { ...props, onRender })) + }) + await settle() + const current = (): Controller => { + if (!rendered) { + throw new Error('probe never rendered') + } + return rendered + } + return { + current, + rerender: async (next: Partial>) => { + await act(async () => { + renderer?.update(createElement(Probe, { ...props, ...next, onRender })) + }) + await settle() + }, + unmount: async () => { + await act(async () => renderer?.unmount()) + } + } +} + +function descriptorFor( + snapshot: readonly SessionOptionDescriptor[], + id: string +): SessionOptionDescriptor | undefined { + return snapshot.find((entry) => entry.id === id) +} + +function currentValueOf(snapshot: readonly SessionOptionDescriptor[], id: string) { + const kind = descriptorFor(snapshot, id)?.kind + return kind && 'currentValue' in kind ? kind.currentValue : undefined +} + +const BASE = { agent: 'codex', sessionId: 'session-1', fence: 1 } as const + +describe('useMobileStructuredAgentOptions fast mode', () => { + it('round-trips a boolean fastMode pick as the wire string and remembers the decoded pick', async () => { + const client = optionsClient(queuedReads(FAST_OPTIONS, FAST_OPTIONS_ON)) + const { calls, mutate } = recordingMutate(async () => + accepted( + { key: 'fastMode', value: 'true', options: { model: 'gpt-live', fastMode: 'true' } }, + true + ) + ) + const harness = await mountOptions({ ...BASE, client: client.client, mutate }) + + expect(currentValueOf(harness.current().optionSnapshot, 'fastMode')).toBe(false) + + let outcome: boolean | null = null + await act(async () => { + outcome = await harness.current().setStructuredOption('fastMode', true) + }) + await settle() + + expect(outcome).toBe(true) + // The crux of the provider-aware fast mode change: a boolean reaches the wire encoded. + expect(calls).toEqual([ + { method: 'agentSession.setOption', fields: { key: 'fastMode', value: 'true' } } + ]) + expect(currentValueOf(harness.current().optionSnapshot, 'fastMode')).toBe(true) + + const persisted = client.methods('settings.mutateNativeChatSessionOptions') + expect(persisted).toHaveLength(1) + expect(persisted[0]?.params).toMatchObject({ + type: 'apply-picks', + agent: 'codex', + // Decoded back to a boolean: the pick a later launch seeds from must not be the string. + picks: expect.arrayContaining([{ modelId: 'gpt-live', optionId: 'fastMode', value: true }]) + }) + await harness.unmount() + }) + + it('offers no Fast row when the provider catalog never claimed support', async () => { + const client = optionsClient(queuedReads(OPTIONS)) + const { calls, mutate } = recordingMutate(async () => + accepted({ key: 'fastMode', value: 'true' }, true) + ) + const harness = await mountOptions({ ...BASE, client: client.client, mutate }) + + expect(descriptorFor(harness.current().optionSnapshot, 'model')).toBeDefined() + expect(descriptorFor(harness.current().optionSnapshot, 'fastMode')).toBeUndefined() + + let outcome: boolean | null = null + await act(async () => { + outcome = await harness.current().setStructuredOption('fastMode', true) + }) + expect(outcome).toBe(false) + expect(calls).toEqual([]) + await harness.unmount() + }) + + it('offers no Fast row when the session reports fast mode unsupported', async () => { + const client = optionsClient( + queuedReads({ ...FAST_OPTIONS, fastModeSupport: { supported: false, reason: 'account' } }) + ) + const { mutate } = recordingMutate(async () => ({ status: 'rejected' })) + const harness = await mountOptions({ ...BASE, client: client.client, mutate }) + + expect(descriptorFor(harness.current().optionSnapshot, 'fastMode')).toBeUndefined() + await harness.unmount() + }) + + it('offers no Fast row when the model capability is unknown', async () => { + const client = optionsClient( + queuedReads({ + ...FAST_OPTIONS, + // Absent `supportsFastMode` means the host could not determine support, never "yes". + models: OPTIONS.models + }) + ) + const { mutate } = recordingMutate(async () => ({ status: 'rejected' })) + const harness = await mountOptions({ ...BASE, client: client.client, mutate }) + + expect(descriptorFor(harness.current().optionSnapshot, 'fastMode')).toBeUndefined() + await harness.unmount() + }) +}) + +describe('useMobileStructuredAgentOptions post-write refresh', () => { + it('reads options back after an accepted same-fence write and applies the refreshed value', async () => { + const client = optionsClient(queuedReads(FAST_OPTIONS, FAST_OPTIONS_ON)) + // `options: {}` commits nothing optimistically, so only the refresh can move the value. + const { mutate } = recordingMutate(async () => + accepted({ key: 'fastMode', value: 'true', options: {} }, true) + ) + const harness = await mountOptions({ ...BASE, client: client.client, mutate }) + + expect(client.optionReads()).toBe(1) + expect(currentValueOf(harness.current().optionSnapshot, 'fastMode')).toBe(false) + + await act(async () => { + await harness.current().setStructuredOption('fastMode', true) + }) + await settle() + + expect(client.optionReads()).toBe(2) + expect(currentValueOf(harness.current().optionSnapshot, 'fastMode')).toBe(true) + await harness.unmount() + }) + + it('skips the refresh when the write landed against a different fence', async () => { + const client = optionsClient(queuedReads(FAST_OPTIONS, FAST_OPTIONS_ON)) + const { mutate } = recordingMutate(async () => + accepted({ key: 'fastMode', value: 'true', options: {} }, false) + ) + const harness = await mountOptions({ ...BASE, client: client.client, mutate }) + + await act(async () => { + await harness.current().setStructuredOption('fastMode', true) + }) + await settle() + + expect(client.optionReads()).toBe(1) + expect(currentValueOf(harness.current().optionSnapshot, 'fastMode')).toBe(false) + await harness.unmount() + }) +}) + +describe('useMobileStructuredAgentOptions generation fencing', () => { + it('drops an options read a later write superseded', async () => { + const stale = deferred() + const first = optionsClient(queuedReads(FAST_OPTIONS)) + // A reconnect hands the hook a new client, so only the read effect re-runs: the record + // survives and the in-flight read is not marked stale. Generation is the only guard left. + const reconnected = optionsClient(() => stale.promise) + const { mutate } = recordingMutate(async () => ({ status: 'unknown' })) + const harness = await mountOptions({ ...BASE, client: first.client, mutate }) + + expect(currentValueOf(harness.current().optionSnapshot, 'model')).toBe('gpt-live') + await harness.rerender({ client: reconnected.client }) + expect(reconnected.optionReads()).toBe(1) + + let outcome: boolean | null = null + await act(async () => { + outcome = await harness.current().setStructuredOption('model', 'gpt-fast') + }) + await settle() + expect(outcome).toBe(true) + expect(currentValueOf(harness.current().optionSnapshot, 'model')).toBe('gpt-fast') + + await act(async () => { + stale.resolve({ ...FAST_OPTIONS, conversationCommands: ['compact'] }) + }) + await settle() + + expect(currentValueOf(harness.current().optionSnapshot, 'model')).toBe('gpt-fast') + expect(harness.current().conversationCommands).toEqual([]) + await harness.unmount() + }) +}) + +describe('useMobileStructuredAgentOptions pending guard', () => { + it('refuses an overlapping write and releases the guard once the first one settles', async () => { + const client = optionsClient(queuedReads(FAST_OPTIONS, FAST_OPTIONS_ON)) + const inFlight = deferred>() + const { calls, mutate } = recordingMutate(async (call) => + call === 0 ? inFlight.promise : accepted({ key: 'fastMode', value: 'true' }, false) + ) + const harness = await mountOptions({ ...BASE, client: client.client, mutate }) + + let firstWrite: Promise | null = null + await act(async () => { + firstWrite = harness.current().setStructuredOption('effort', 'high') + }) + expect(calls).toHaveLength(1) + expect(harness.current().pendingOptionId).toBe('effort') + + let overlapping: boolean | null = null + await act(async () => { + overlapping = await harness.current().setStructuredOption('fastMode', true) + }) + expect(overlapping).toBe(false) + expect(calls).toHaveLength(1) + + await act(async () => { + inFlight.resolve(accepted({ key: 'effort', value: 'high' }, false)) + await firstWrite + }) + await settle() + expect(await firstWrite).toBe(true) + expect(harness.current().pendingOptionId).toBeNull() + + // The guard is a ref, so a write that never clears it wedges every later pick. + let later: boolean | null = null + await act(async () => { + later = await harness.current().setStructuredOption('fastMode', true) + }) + await settle() + expect(later).toBe(true) + expect(calls).toHaveLength(2) + await harness.unmount() + }) +}) diff --git a/mobile/src/session/use-mobile-structured-agent-options.ts b/mobile/src/session/use-mobile-structured-agent-options.ts index 2588c5f335d..54d14fd2a8a 100644 --- a/mobile/src/session/use-mobile-structured-agent-options.ts +++ b/mobile/src/session/use-mobile-structured-agent-options.ts @@ -17,7 +17,8 @@ import { commitStructuredAgentSessionOptionValues, createStructuredAgentSessionOptionState, structuredAgentSessionOptionPicks, - structuredAgentSessionOptionSnapshot + structuredAgentSessionOptionSnapshot, + type StructuredAgentSessionOptionState } from '../../../src/shared/structured-agent-session-options' import type { RpcClient } from '../transport/rpc-client' import { @@ -25,6 +26,7 @@ import { type StructuredAgentSessionMutate } from './mobile-structured-agent-session-rpc' import { persistMobileStructuredOptionPicks } from './mobile-native-chat-session-option-persistence' +import { encodeStructuredAgentSessionOptionValue } from '../../../src/shared/structured-agent-session-option-codec' type StructuredOptionsController = { optionPickerRequest: { id: string; sequence: number } | null @@ -48,7 +50,18 @@ export function useMobileStructuredAgentOptions(args: { const [optionState, setOptionState] = useState(() => createStructuredAgentSessionOptionState(agent ?? 'codex') ) + const optionStateRef = useRef(optionState) const activeOptionRecordRef = useRef(optionState.record) + const pendingOptionRef = useRef(null) + const optionMutationGeneration = useRef(0) + const updateOptionState = useCallback( + (update: (current: StructuredAgentSessionOptionState) => StructuredAgentSessionOptionState) => { + const next = update(optionStateRef.current) + optionStateRef.current = next + setOptionState(next) + }, + [] + ) const [optionPickerRequest, setOptionPickerRequest] = useState<{ id: string sequence: number @@ -64,6 +77,9 @@ export function useMobileStructuredAgentOptions(args: { useEffect(() => { const next = createStructuredAgentSessionOptionState(agent ?? 'codex') + optionMutationGeneration.current += 1 + pendingOptionRef.current = null + optionStateRef.current = next activeOptionRecordRef.current = next.record setOptionState(next) }, [agent, enabled, fence, sessionId]) @@ -73,11 +89,12 @@ export function useMobileStructuredAgentOptions(args: { return } let stale = false + const readGeneration = optionMutationGeneration.current void callAgentSession(client, 'agentSession.options', { sessionId }) .then((result) => { - if (!stale) { + if (!stale && optionMutationGeneration.current === readGeneration) { setConversationSupport({ sessionId, commands: result.conversationCommands ?? [] }) - setOptionState((current) => + updateOptionState((current) => current.record === activeOptionRecordRef.current ? applyStructuredAgentSessionOptions(current, optionCatalog, result) : current @@ -88,7 +105,7 @@ export function useMobileStructuredAgentOptions(args: { return () => { stale = true } - }, [client, enabled, optionCatalog, sessionId, fence]) + }, [client, enabled, optionCatalog, sessionId, fence, updateOptionState]) const optionSnapshot = useMemo( () => structuredAgentSessionOptionSnapshot(optionState), @@ -97,26 +114,37 @@ export function useMobileStructuredAgentOptions(args: { const setStructuredOption = useCallback( async (id: string, value: SessionOptionValue): Promise => { + const currentState = optionStateRef.current + const encoded = encodeStructuredAgentSessionOptionValue(id, value) if ( - !canSetStructuredAgentSessionOption(optionState, id, value) || - typeof value !== 'string' + pendingOptionRef.current !== null || + !client || + !sessionId || + !optionCatalog || + encoded === null || + !canSetStructuredAgentSessionOption(currentState, id, value) ) { return false } - const targetRecord = optionState.record - setOptionState((current) => ({ ...current, pendingId: id })) + const targetRecord = currentState.record + const mutationGeneration = ++optionMutationGeneration.current + pendingOptionRef.current = id + updateOptionState((current) => ({ ...current, pendingId: id })) try { const result = await mutate( 'agentSession.setOption', 'agentSession.setOption', - { key: id, value } + { key: id, value: encoded } ) - if (activeOptionRecordRef.current !== targetRecord) { + if ( + activeOptionRecordRef.current !== targetRecord || + optionMutationGeneration.current !== mutationGeneration + ) { return result.status !== 'rejected' } if (result.status === 'accepted') { - const committed = result.value.options ?? { [id]: value } - setOptionState((current) => + const committed = result.value.options ?? { [id]: encoded } + updateOptionState((current) => current.record === targetRecord && result.sameFence ? commitStructuredAgentSessionOptionValues(current, committed) : current @@ -128,29 +156,53 @@ export function useMobileStructuredAgentOptions(args: { void persistMobileStructuredOptionPicks({ client, agent, - picks: structuredAgentSessionOptionPicks(optionState, committed) + picks: structuredAgentSessionOptionPicks(currentState, committed) }) } + if (result.sameFence) { + void callAgentSession(client, 'agentSession.options', { + sessionId + }) + .then((refreshed) => { + if ( + activeOptionRecordRef.current === targetRecord && + optionMutationGeneration.current === mutationGeneration + ) { + updateOptionState((latest) => + latest.record === targetRecord + ? applyStructuredAgentSessionOptions(latest, optionCatalog, refreshed) + : latest + ) + } + }) + .catch(() => undefined) + } return true } if (result.status === 'unknown') { - setOptionState((current) => + updateOptionState((current) => current.record === targetRecord - ? commitStructuredAgentSessionOption(current, id, value) + ? commitStructuredAgentSessionOption(current, id, encoded) : current ) return true } return false } finally { - setOptionState((current) => - current.record === targetRecord && current.pendingId === id - ? { ...current, pendingId: null } - : current - ) + if ( + activeOptionRecordRef.current === targetRecord && + optionMutationGeneration.current === mutationGeneration + ) { + pendingOptionRef.current = null + updateOptionState((current) => + current.record === targetRecord && current.pendingId === id + ? { ...current, pendingId: null } + : current + ) + } } }, - [agent, client, mutate, optionState] + [agent, client, mutate, optionCatalog, sessionId, updateOptionState] ) const invokeStructuredOption = useCallback( @@ -167,9 +219,9 @@ export function useMobileStructuredAgentOptions(args: { const setOption = useCallback( async (id: string, value: SessionOptionValue) => { await setStructuredOption(id, value) - return { snapshot: optionSnapshot } + return { snapshot: structuredAgentSessionOptionSnapshot(optionStateRef.current) } }, - [optionSnapshot, setStructuredOption] + [setStructuredOption] ) const optionSurface = useMemo( diff --git a/mobile/src/source-control/MobileGitHistoryList.tsx b/mobile/src/source-control/MobileGitHistoryList.tsx index 457f0580156..babc4401b36 100644 --- a/mobile/src/source-control/MobileGitHistoryList.tsx +++ b/mobile/src/source-control/MobileGitHistoryList.tsx @@ -2,9 +2,10 @@ import { memo, useCallback, useEffect, useState } from 'react' import { ActivityIndicator, FlatList, Pressable, StyleSheet, Text, View } from 'react-native' import { ChevronDown, ChevronRight } from 'lucide-react-native' import { colors, radii, spacing, typography } from '../theme/mobile-theme' -import type { ConnectionState, RpcSuccess } from '../transport/types' +import type { ConnectionState } from '../transport/types' import type { RpcClient } from '../transport/rpc-client' import { useForceReconnect } from '../transport/client-context' +import { gitCommitCompareRead } from './mobile-git-read-operations' import { fetchMobileGitHistory, mapMobileCommitRows, @@ -105,12 +106,12 @@ export const MobileGitHistoryList = memo(function MobileGitHistoryList({ const commitId = expanded let stale = false setFilesById((prev) => (prev[commitId] ? prev : { ...prev, [commitId]: 'loading' })) - void client - .sendRequest('git.commitCompare', { worktree: `id:${worktreeId}`, commitId }) - .then((response) => { - const entries = response.ok - ? ((response as RpcSuccess).result as { entries: GitBranchChangeEntry[] }).entries - : [] + void gitCommitCompareRead + .request(client, { worktree: `id:${worktreeId}`, commitId }) + .then((reply) => { + const compared = gitCommitCompareRead.interpret(reply) + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Preserve the established response shape at this boundary. + const entries = compared.accepted ? (compared.value as GitBranchChangeEntry[]) : [] if (!stale) { setFilesById((prev) => ({ ...prev, [commitId]: entries })) } diff --git a/mobile/src/source-control/mobile-branch-base-ref.ts b/mobile/src/source-control/mobile-branch-base-ref.ts index dbe33a43de3..4daa111c3d2 100644 --- a/mobile/src/source-control/mobile-branch-base-ref.ts +++ b/mobile/src/source-control/mobile-branch-base-ref.ts @@ -1,60 +1,16 @@ -import type { RpcClient } from '../transport/rpc-client' -import { isMobileGitUnavailable } from './mobile-git-status' - -type RuntimeRepoSummary = { - id: string - worktreeBaseRef?: string | null -} - -type RuntimeWorktreeSummary = { - baseRef?: string | null -} - -function isRecord(value: unknown): value is Record { - return typeof value === 'object' && value !== null -} +import { refusedRpcMessageOrFallback } from '../transport/rpc-refusal-message' +import { isMobileGitUnavailableReply } from './mobile-git-status' +import { repoBaseRefListRead, repoDefaultBaseRefRead } from './mobile-repo-base-ref-operations' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' +import { worktreeSummaryRead } from './mobile-worktree-metadata-operations' function getRepoIdFromMobileWorktreeId(id: string): string { const separatorIdx = id.indexOf('::') return separatorIdx === -1 ? id : id.slice(0, separatorIdx) } -function readRepoSummaries(value: unknown): RuntimeRepoSummary[] { - if (!isRecord(value) || !Array.isArray(value.repos)) { - return [] - } - return value.repos.flatMap((candidate): RuntimeRepoSummary[] => { - if (!isRecord(candidate) || typeof candidate.id !== 'string') { - return [] - } - return [ - { - id: candidate.id, - worktreeBaseRef: - typeof candidate.worktreeBaseRef === 'string' ? candidate.worktreeBaseRef : null - } - ] - }) -} - -function readDefaultBaseRef(value: unknown): string | null { - if (!isRecord(value)) { - return null - } - return typeof value.defaultBaseRef === 'string' ? value.defaultBaseRef.trim() || null : null -} - -function readWorktreeSummary(value: unknown): RuntimeWorktreeSummary | null { - if (!isRecord(value) || !isRecord(value.worktree)) { - return null - } - return { - baseRef: typeof value.worktree.baseRef === 'string' ? value.worktree.baseRef : null - } -} - export async function resolveMobileBranchCompareBaseRef( - client: RpcClient, + client: MobileSourceControlRpcSender, worktreeId: string ): Promise { const repoId = getRepoIdFromMobileWorktreeId(worktreeId) @@ -62,31 +18,36 @@ export async function resolveMobileBranchCompareBaseRef( return null } - const [worktreeResponse, repoResponse] = await Promise.all([ - client.sendRequest('worktree.show', { worktree: `id:${worktreeId}` }).catch(() => null), - client.sendRequest('repo.list').catch(() => null) + const [worktreeReply, repoReply] = await Promise.all([ + worktreeSummaryRead.request(client, { worktree: `id:${worktreeId}` }).catch(() => null), + repoBaseRefListRead.request(client).catch(() => null) ]) - if (worktreeResponse?.ok) { - const worktreeBaseRef = readWorktreeSummary(worktreeResponse.result)?.baseRef?.trim() || null + const worktreeSummary = worktreeReply && worktreeSummaryRead.interpret(worktreeReply) + if (worktreeSummary?.accepted) { + const worktreeBaseRef = worktreeSummary.value?.baseRef?.trim() || null if (worktreeBaseRef) { return worktreeBaseRef } } - if (repoResponse?.ok) { - const repo = readRepoSummaries(repoResponse.result).find((candidate) => candidate.id === repoId) + const repos = repoReply && repoBaseRefListRead.interpret(repoReply) + if (repos?.accepted) { + const repo = repos.value.find((candidate) => candidate.id === repoId) const repoBaseRef = repo?.worktreeBaseRef?.trim() || null if (repoBaseRef) { return repoBaseRef } } - const defaultResponse = await client.sendRequest('repo.baseRefDefault', { repo: `id:${repoId}` }) - if (!defaultResponse.ok) { - if (isMobileGitUnavailable(defaultResponse.error?.code, defaultResponse.error?.message)) { - return null - } - throw new Error(defaultResponse.error?.message || 'Unable to resolve branch base') + const defaultReply = await repoDefaultBaseRefRead.request(client, { repo: `id:${repoId}` }) + // Why the raw refusal: a host that does not offer git to mobile is a capability gap to degrade + // on, not an error to surface, and no acceptance policy carries the code and message through. + if (isMobileGitUnavailableReply(defaultReply)) { + return null + } + try { + return repoDefaultBaseRefRead.interpret(defaultReply) + } catch (error) { + throw new Error(refusedRpcMessageOrFallback(error, 'Unable to resolve branch base')) } - return readDefaultBaseRef(defaultResponse.result) } diff --git a/mobile/src/source-control/mobile-commit-message-ai.ts b/mobile/src/source-control/mobile-commit-message-ai.ts index 6f85ebba442..17bcce4bab1 100644 --- a/mobile/src/source-control/mobile-commit-message-ai.ts +++ b/mobile/src/source-control/mobile-commit-message-ai.ts @@ -1,48 +1,38 @@ -import type { RpcClient } from '../transport/rpc-client' -import type { RpcSuccess } from '../transport/types' +import { refusedRpcMessageOrFallback } from '../transport/rpc-refusal-message' +import { + gitCancelGenerateCommitMessageRun, + gitGenerateCommitMessageRun, + type MobileGenerateCommitMessageResult +} from './mobile-git-mutation-operations' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' -// Mirrors the host GenerateCommitMessageResult (src/main/text-generation/ -// commit-message-text-generation.ts) — a single resolved result, not a stream. -export type MobileGenerateCommitMessageResult = - | { success: true; message: string } - | { success: false; error: string; canceled?: boolean } +export type { MobileGenerateCommitMessageResult } -// Normalizes the git.generateCommitMessage RPC into a discriminated result the -// UI can switch on. RPC transport failures and malformed payloads collapse to -// { success:false } so the caller never has to special-case them. +// A refusal or a malformed payload collapses to { success:false } so the caller never has to +// special-case either; the operation's reader owns the payload half of that. export async function requestMobileCommitMessage( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string ): Promise { - const response = await client.sendRequest('git.generateCommitMessage', { + const reply = await gitGenerateCommitMessageRun.request(client, { worktree: `id:${worktreeId}` }) - if (!response.ok) { - return { success: false, error: response.error?.message || 'Failed to generate commit message' } - } - const result = (response as RpcSuccess).result as MobileGenerateCommitMessageResult | undefined - if (!result || typeof result !== 'object') { - return { success: false, error: 'Failed to generate commit message' } - } - if (result.success === true && typeof result.message === 'string' && result.message.length > 0) { - return { success: true, message: result.message } - } - // Why: a malformed `{ success:false }` payload could leave error undefined, - // breaking the result contract — always coerce to a non-empty string. - const hostError = - result.success === false && typeof result.error === 'string' && result.error.length > 0 - ? result.error - : 'No commit message generated' - return { - success: false, - error: hostError, - ...(result.success === false && result.canceled ? { canceled: true } : {}) + try { + return gitGenerateCommitMessageRun.interpret(reply) + } catch (error) { + return { + success: false, + error: refusedRpcMessageOrFallback(error, 'Failed to generate commit message') + } } } export async function cancelMobileCommitMessage( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string ): Promise { - await client.sendRequest('git.cancelGenerateCommitMessage', { worktree: `id:${worktreeId}` }) + const reply = await gitCancelGenerateCommitMessageRun.request(client, { + worktree: `id:${worktreeId}` + }) + gitCancelGenerateCommitMessageRun.interpret(reply) } diff --git a/mobile/src/source-control/mobile-git-history.ts b/mobile/src/source-control/mobile-git-history.ts index d0d42929ade..7a9c0479a58 100644 --- a/mobile/src/source-control/mobile-git-history.ts +++ b/mobile/src/source-control/mobile-git-history.ts @@ -1,6 +1,7 @@ import type { GitHistoryItem, GitHistoryResult } from '../../../src/shared/git-history-types' -import type { RpcClient } from '../transport/rpc-client' -import type { RpcSuccess } from '../transport/types' +import { refusedRpcMessageOrFallback } from '../transport/rpc-refusal-message' +import { gitHistoryRead } from './mobile-git-read-operations' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' export type MobileCommitRow = { id: string @@ -57,16 +58,16 @@ export function mapMobileCommitRows(result: GitHistoryResult, nowMs: number): Mo } export async function fetchMobileGitHistory( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, limit = 50 ): Promise { - const response = await client.sendRequest('git.history', { - worktree: `id:${worktreeId}`, - limit - }) - if (!response.ok) { - throw new Error(response.error?.message || 'Failed to load commit history') + // Not inside the try: a transport rejection must reach the caller as the original error object. + const reply = await gitHistoryRead.request(client, { worktree: `id:${worktreeId}`, limit }) + try { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Preserve the established response shape at this boundary. + return gitHistoryRead.interpret(reply) as GitHistoryResult + } catch (error) { + throw new Error(refusedRpcMessageOrFallback(error, 'Failed to load commit history')) } - return (response as RpcSuccess).result as GitHistoryResult } diff --git a/mobile/src/source-control/mobile-git-mutation-operations.ts b/mobile/src/source-control/mobile-git-mutation-operations.ts new file mode 100644 index 00000000000..be5a11720f8 --- /dev/null +++ b/mobile/src/source-control/mobile-git-mutation-operations.ts @@ -0,0 +1,108 @@ +import { bindDeferredRpcOperation, defineRpcOperation } from '../transport/rpc-operation' +import type { RpcCompatibleReader } from '../transport/rpc-operation-contract' +import { rpcReadUnchecked, rpcUncheckedPayloadReader } from '../transport/rpc-reader-payload' + +// Mirrors the host GenerateCommitMessageResult (src/main/text-generation/ +// commit-message-text-generation.ts) — a single resolved result, not a stream. +export type MobileGenerateCommitMessageResult = + | { success: true; message: string } + | { success: false; error: string; canceled?: boolean } + +// Host-state changes. A lost reply here is unknown, never failed: none of these operations +// interprets a transport rejection, so the delivery-unknown marker reaches the caller intact. + +/** Exactly `result?.key`, so a null or absent commit payload reads as absent, not as a throw. */ +function optionalPayloadMember(raw: unknown, key: string): unknown { + return raw == null ? undefined : Object(raw)[key] +} + +const gitCommitOutcomeReader: RpcCompatibleReader< + unknown, + 'commit-outcome', + { success: unknown; error: unknown } +> = (raw) => + rpcReadUnchecked('commit-outcome', { + success: optionalPayloadMember(raw, 'success'), + error: optionalPayloadMember(raw, 'error') + }) + +/** git.commit answers in-band: an accepted reply can still carry `success: false`. */ +export const gitCommitRun = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.commit-staged', + method: 'git.commit', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: gitCommitOutcomeReader + }) +) + +/** Publish, push and force-with-lease are one operation; only the params differ. */ +export const gitPushRun = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.push-branch', + method: 'git.push', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('push-accepted') + }) +) + +export const gitBulkStageRun = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.bulk-stage', + method: 'git.bulkStage', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('stage-accepted') + }) +) + +const GENERATE_FAILED = 'Failed to generate commit message' + +// Normalizes the host GenerateCommitMessageResult into the discriminated result the UI switches +// on. A malformed `{ success:false }` could leave `error` undefined, which breaks that contract, +// so the message is always coerced to a non-empty string. +const generatedCommitMessageReader: RpcCompatibleReader< + unknown, + 'generated-commit-message', + MobileGenerateCommitMessageResult +> = (raw) => { + if (!raw || typeof raw !== 'object') { + return rpcReadUnchecked('generated-commit-message', { success: false, error: GENERATE_FAILED }) + } + const result: { success?: unknown; message?: unknown; error?: unknown; canceled?: unknown } = raw + if (result.success === true && typeof result.message === 'string' && result.message.length > 0) { + return rpcReadUnchecked('generated-commit-message', { success: true, message: result.message }) + } + const hostError = + result.success === false && typeof result.error === 'string' && result.error.length > 0 + ? result.error + : 'No commit message generated' + return rpcReadUnchecked('generated-commit-message', { + success: false, + error: hostError, + ...(result.success === false && result.canceled ? { canceled: true } : {}) + }) +} + +export const gitGenerateCommitMessageRun = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.generate-commit-message', + method: 'git.generateCommitMessage', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: generatedCommitMessageReader + }) +) + +/** Cancel is advisory: a refusal means the generation already finished, which is not an error. */ +export const gitCancelGenerateCommitMessageRun = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.cancel-generate-commit-message-or-skip', + method: 'git.cancelGenerateCommitMessage', + acceptance: 'success-result-or-skip', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('cancel-accepted') + }) +) diff --git a/mobile/src/source-control/mobile-git-read-operations.ts b/mobile/src/source-control/mobile-git-read-operations.ts new file mode 100644 index 00000000000..e611abe982c --- /dev/null +++ b/mobile/src/source-control/mobile-git-read-operations.ts @@ -0,0 +1,103 @@ +import { bindDeferredRpcOperation, defineRpcOperation } from '../transport/rpc-operation' +import type { RpcCompatibleReader } from '../transport/rpc-operation-contract' +import { rpcPayloadMember, rpcUncheckedPayloadReader } from '../transport/rpc-reader-payload' +import { readMobileGitStatusResult } from '../session/mobile-diff-review-rpc' +import type { MobileGitStatusResult } from './mobile-git-status' + +// Source-control reads. Every one of these replies used to be re-typed with a cast at the call +// site; the reader below is now the only place that says what the payload is. + +/** + * git.status, first of two readers. The Changes screen publishes the host payload verbatim. + * + * Justification for a second reader on one method: hosted-review preparation has always read the + * normalized projection instead, and the projection is not a superset — it returns null when + * `entries` is not an array and drops entries missing a path or area. Those are replies the + * Changes screen renders today, so sharing the projecting reader would change what it shows. + * Unifying the two is a product decision with its own expectation, not part of this migration. + */ +export const gitStatusHostPayloadRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.status-host-payload', + method: 'git.status', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('host-status-payload') + }) +) + +const gitStatusProjectionReader: RpcCompatibleReader< + unknown, + 'normalized-status', + MobileGitStatusResult | null +> = (raw) => ({ + compatible: true, + variant: 'normalized-status', + value: readMobileGitStatusResult(raw), + salvage: { droppedPaths: [], droppedCount: 0 } +}) + +/** git.status, second reader: the normalized projection hosted-review preparation reads. */ +export const gitStatusProjectionRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.status-normalized', + method: 'git.status', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: gitStatusProjectionReader + }) +) + +export const gitHistoryRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.history-page', + method: 'git.history', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('history-page') + }) +) + +const commitCompareEntriesReader: RpcCompatibleReader< + unknown, + 'commit-compare-entries', + unknown +> = (raw) => ({ + compatible: true, + variant: 'commit-compare-entries', + // Keeps the property-read exception the expanded-commit list already relies on: a null result + // throws inside the load, which is what leaves an already-loaded file list alone. + value: rpcPayloadMember(raw, 'entries'), + salvage: { droppedPaths: [], droppedCount: 0 } +}) + +/** A refused compare leaves the row's file list untouched, so refusal is a skip, not a throw. */ +export const gitCommitCompareRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.commit-compare-entries-or-skip', + method: 'git.commitCompare', + acceptance: 'success-result-or-skip', + barrier: 'after-caller-barrier', + read: commitCompareEntriesReader + }) +) + +export const gitBranchCompareRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.branch-compare', + method: 'git.branchCompare', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('branch-compare') + }) +) + +export const gitBranchDiffRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'git.branch-diff', + method: 'git.branchDiff', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('branch-diff') + }) +) diff --git a/mobile/src/source-control/mobile-git-status.ts b/mobile/src/source-control/mobile-git-status.ts index 9c1f033f8b3..522d4873fc9 100644 --- a/mobile/src/source-control/mobile-git-status.ts +++ b/mobile/src/source-control/mobile-git-status.ts @@ -5,6 +5,7 @@ import type { GitStatusResult, GitUpstreamStatus } from '../../../src/shared/git-status-types' +import type { RpcResponse } from '../transport/types' export type MobileGitFileStatus = GitFileStatus export type MobileGitStagingArea = GitStagingArea @@ -99,6 +100,25 @@ export function canOpenMobileGitStatusEntry(entry: MobileGitStatusEntry): boolea return entry.conflictStatus !== 'unresolved' } +/** + * The refusal behind a reply, or null when the host accepted it. + * + * Four source-control loads route on the refusal itself rather than on acceptance: two degrade to + * a capability-missing screen, one retries a not-yet-visible selector, and one falls back to a + * different method. No acceptance policy carries `code` and `message` through, so those call sites + * read the refusal here — in one place, before they hand the reply to the operation's policy. + */ +export function readMobileGitRefusal( + response: RpcResponse +): { code: string | undefined; message: string | undefined } | null { + return response.ok ? null : { code: response.error?.code, message: response.error?.message } +} + +export function isMobileGitUnavailableReply(response: RpcResponse): boolean { + const refusal = readMobileGitRefusal(response) + return refusal !== null && isMobileGitUnavailable(refusal.code, refusal.message) +} + export function isMobileGitUnavailable(code: string | undefined, message: string | undefined) { return ( code === 'forbidden' || diff --git a/mobile/src/source-control/mobile-hosted-review-create-intent-runner.ts b/mobile/src/source-control/mobile-hosted-review-create-intent-runner.ts index aa38ae78f2f..26087d34541 100644 --- a/mobile/src/source-control/mobile-hosted-review-create-intent-runner.ts +++ b/mobile/src/source-control/mobile-hosted-review-create-intent-runner.ts @@ -1,4 +1,3 @@ -import type { RpcClient } from '../transport/rpc-client' import type { MobileGitStatusResult } from './mobile-git-status' import { createMobilePr, @@ -11,6 +10,7 @@ import { prepareMobileHostedReviewCreateIntent, type MobileHostedReviewCreateIntentProgress } from './mobile-hosted-review-create-intent' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' type RunInput = { branch: string @@ -47,7 +47,7 @@ export function isMobileHostedReviewCommitFailure( } export async function runMobileHostedReviewCreateIntent( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, input: RunInput ): Promise { diff --git a/mobile/src/source-control/mobile-hosted-review-create-intent.ts b/mobile/src/source-control/mobile-hosted-review-create-intent.ts index 884160a347c..f056e1eeaab 100644 --- a/mobile/src/source-control/mobile-hosted-review-create-intent.ts +++ b/mobile/src/source-control/mobile-hosted-review-create-intent.ts @@ -1,4 +1,3 @@ -import type { RpcClient } from '../transport/rpc-client' import { requestMobileCommitMessage } from './mobile-commit-message-ai' import { getStageablePaths, type MobileGitStatusResult } from './mobile-git-status' import { getMobilePrEligibilityReadiness } from './mobile-open-pr-prefill' @@ -7,9 +6,10 @@ import { commitMobileHostedReviewStagedChanges, mobileHostedReviewBranchStillMatches, readMobileHostedReviewGitStatus, - sendMobileHostedReviewGitMutation + stageMobileHostedReviewPaths } from './mobile-hosted-review-git-preparation' import { applyMobileHostedReviewRemotePrerequisite } from './mobile-hosted-review-remote-prerequisite' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' export type MobileHostedReviewCreateIntentProgress = | 'staging' @@ -71,7 +71,7 @@ function hasUnresolvedConflicts(status: MobileGitStatusResult | null): boolean { } async function resolvePrefillFromStatus( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, branch: string, title: string, @@ -85,7 +85,7 @@ async function resolvePrefillFromStatus( } async function ensureLocalChangesCommitted( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, input: PrepareInput, currentStatus: MobileGitStatusResult | null @@ -108,12 +108,7 @@ async function ensureLocalChangesCommitted( const stagePaths = getStageablePaths(currentStatus?.entries ?? []) if (stagePaths.length > 0) { input.onProgress?.('staging') - const staged = await sendMobileHostedReviewGitMutation( - client, - 'git.bulkStage', - { worktree: `id:${worktreeId}`, filePaths: stagePaths }, - 'Failed to stage changes' - ) + const staged = await stageMobileHostedReviewPaths(client, worktreeId, stagePaths) if (!staged.ok) { return staged } @@ -189,7 +184,7 @@ async function ensureLocalChangesCommitted( } export async function prepareMobileHostedReviewCreateIntent( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, input: PrepareInput ): Promise { diff --git a/mobile/src/source-control/mobile-hosted-review-git-preparation.ts b/mobile/src/source-control/mobile-hosted-review-git-preparation.ts index 93de10eb357..518a8724254 100644 --- a/mobile/src/source-control/mobile-hosted-review-git-preparation.ts +++ b/mobile/src/source-control/mobile-hosted-review-git-preparation.ts @@ -1,21 +1,33 @@ -import type { RpcClient } from '../transport/rpc-client' -import type { RpcSuccess } from '../transport/types' -import { readMobileGitStatusResult } from '../session/mobile-diff-review-rpc' +import type { RpcSendParams } from '../transport/rpc-params-contract' +import { + hostReplyErrorTextOrFallback, + refusedRpcMessageOrFallback +} from '../transport/rpc-refusal-message' +import type { RpcResponse } from '../transport/types' +import { gitBulkStageRun, gitCommitRun, gitPushRun } from './mobile-git-mutation-operations' +import { gitStatusProjectionRead } from './mobile-git-read-operations' import type { MobileGitStatusResult } from './mobile-git-status' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' export type MobileHostedReviewStatusReadResult = | { ok: true; status: MobileGitStatusResult | null } | { ok: false; error: string } +export type MobileHostedReviewMutationResult = { ok: true } | { ok: false; error: string } + export async function readMobileHostedReviewGitStatus( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string ): Promise { - const response = await client.sendRequest('git.status', { worktree: `id:${worktreeId}` }) - if (!response.ok) { - return { ok: false, error: response.error?.message || 'Unable to refresh source control' } + const reply = await gitStatusProjectionRead.request(client, { worktree: `id:${worktreeId}` }) + try { + return { ok: true, status: gitStatusProjectionRead.interpret(reply) } + } catch (error) { + return { + ok: false, + error: refusedRpcMessageOrFallback(error, 'Unable to refresh source control') + } } - return { ok: true, status: readMobileGitStatusResult((response as RpcSuccess).result) } } export function mobileHostedReviewBranchStillMatches( @@ -26,42 +38,73 @@ export function mobileHostedReviewBranchStillMatches( return Boolean(branch && (branch === inputBranch || branch === `refs/heads/${inputBranch}`)) } -export async function sendMobileHostedReviewGitMutation( - client: Pick, - method: string, - params: Record, +/** + * One settle shape for the preparation mutations. Two catches because main had two paths: a + * refusal with no message falls back to the step's copy, while a transport drop surfaces its own + * message verbatim and keeps its delivery-unknown mark on the way out. + */ +async function settleMobileHostedReviewMutation( + send: () => Promise, + interpret: (reply: RpcResponse) => unknown, fallback: string -): Promise<{ ok: true } | { ok: false; error: string }> { +): Promise { + let reply: RpcResponse try { - const response = await client.sendRequest(method, params) - if (!response.ok) { - return { ok: false, error: response.error?.message || fallback } - } - return { ok: true } - } catch (err) { - return { ok: false, error: err instanceof Error ? err.message : fallback } + reply = await send() + } catch (error) { + return { ok: false, error: error instanceof Error ? error.message : fallback } } + try { + interpret(reply) + } catch (error) { + return { ok: false, error: refusedRpcMessageOrFallback(error, fallback) } + } + return { ok: true } +} + +export function pushMobileHostedReviewBranch( + client: MobileSourceControlRpcSender, + params: RpcSendParams<'git.push'>, + fallback: string +): Promise { + return settleMobileHostedReviewMutation( + () => gitPushRun.request(client, params), + (reply) => gitPushRun.interpret(reply), + fallback + ) +} + +export function stageMobileHostedReviewPaths( + client: MobileSourceControlRpcSender, + worktreeId: string, + filePaths: string[] +): Promise { + return settleMobileHostedReviewMutation( + () => gitBulkStageRun.request(client, { worktree: `id:${worktreeId}`, filePaths }), + (reply) => gitBulkStageRun.interpret(reply), + 'Failed to stage changes' + ) } export async function commitMobileHostedReviewStagedChanges( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, message: string -): Promise<{ ok: true } | { ok: false; error: string }> { +): Promise { + let reply: RpcResponse try { - const response = await client.sendRequest('git.commit', { - worktree: `id:${worktreeId}`, - message - }) - if (!response.ok) { - return { ok: false, error: response.error?.message || 'Commit failed' } - } - const result = (response as RpcSuccess).result as { success?: boolean; error?: string } - if (result?.success !== true) { - return { ok: false, error: result?.error || 'Commit failed' } - } - return { ok: true } - } catch (err) { - return { ok: false, error: err instanceof Error ? err.message : 'Commit failed' } + reply = await gitCommitRun.request(client, { worktree: `id:${worktreeId}`, message }) + } catch (error) { + return { ok: false, error: error instanceof Error ? error.message : 'Commit failed' } } + let outcome: ReturnType + try { + outcome = gitCommitRun.interpret(reply) + } catch (error) { + return { ok: false, error: refusedRpcMessageOrFallback(error, 'Commit failed') } + } + // An accepted reply still reports in-band, so `success: false` is a failed commit. + return outcome.success === true + ? { ok: true } + : { ok: false, error: hostReplyErrorTextOrFallback(outcome.error, 'Commit failed') } } diff --git a/mobile/src/source-control/mobile-hosted-review-operations.ts b/mobile/src/source-control/mobile-hosted-review-operations.ts new file mode 100644 index 00000000000..579b1be6a4d --- /dev/null +++ b/mobile/src/source-control/mobile-hosted-review-operations.ts @@ -0,0 +1,27 @@ +import { bindDeferredRpcOperation, defineRpcOperation } from '../transport/rpc-operation' +import { rpcUncheckedPayloadReader } from '../transport/rpc-reader-payload' + +/** + * Eligibility is advisory: when the host cannot answer, mobile fails closed on its own rather + * than treating the refusal as an error, so refusal is a skip. + */ +export const hostedReviewEligibilityRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'hostedReview.creation-eligibility-or-skip', + method: 'hostedReview.getCreationEligibility', + acceptance: 'success-result-or-skip', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('creation-eligibility') + }) +) + +/** Creation answers in-band too: an accepted reply can carry `ok: false` plus an existing review. */ +export const hostedReviewCreateRun = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'hostedReview.create', + method: 'hostedReview.create', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('create-result') + }) +) diff --git a/mobile/src/source-control/mobile-hosted-review-remote-prerequisite.ts b/mobile/src/source-control/mobile-hosted-review-remote-prerequisite.ts index cd6e3e5bcc6..8ddbd344069 100644 --- a/mobile/src/source-control/mobile-hosted-review-remote-prerequisite.ts +++ b/mobile/src/source-control/mobile-hosted-review-remote-prerequisite.ts @@ -1,8 +1,8 @@ -import type { RpcClient } from '../transport/rpc-client' import type { MobileGitStatusResult } from './mobile-git-status' import type { MobileHostedReviewCreateIntentProgress } from './mobile-hosted-review-create-intent' import type { MobilePrPrefill } from './mobile-pr-create' -import { sendMobileHostedReviewGitMutation } from './mobile-hosted-review-git-preparation' +import { pushMobileHostedReviewBranch } from './mobile-hosted-review-git-preparation' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' type RemotePrerequisiteInput = { status: MobileGitStatusResult | null @@ -10,28 +10,27 @@ type RemotePrerequisiteInput = { } export async function applyMobileHostedReviewRemotePrerequisite( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, prefill: MobilePrPrefill, input: RemotePrerequisiteInput ): Promise<{ ok: true; ran: boolean } | { ok: false; error: string }> { + const worktree = `id:${worktreeId}` switch (prefill.blockedReason) { case 'no_upstream': { input.onProgress?.('publishing') - const result = await sendMobileHostedReviewGitMutation( + const result = await pushMobileHostedReviewBranch( client, - 'git.push', - { worktree: `id:${worktreeId}`, publish: true }, + { worktree, publish: true }, 'Failed to publish branch' ) return result.ok ? { ok: true, ran: true } : result } case 'needs_push': { input.onProgress?.('pushing') - const result = await sendMobileHostedReviewGitMutation( + const result = await pushMobileHostedReviewBranch( client, - 'git.push', - { worktree: `id:${worktreeId}` }, + { worktree }, 'Failed to push commits' ) return result.ok ? { ok: true, ran: true } : result @@ -41,10 +40,9 @@ export async function applyMobileHostedReviewRemotePrerequisite( return { ok: true, ran: false } } input.onProgress?.('force_pushing') - const result = await sendMobileHostedReviewGitMutation( + const result = await pushMobileHostedReviewBranch( client, - 'git.push', - { worktree: `id:${worktreeId}`, forceWithLease: true }, + { worktree, forceWithLease: true }, 'Failed to force push with lease' ) return result.ok ? { ok: true, ran: true } : result diff --git a/mobile/src/source-control/mobile-hosted-review-service.ts b/mobile/src/source-control/mobile-hosted-review-service.ts index c040b7a2c19..56d53031873 100644 --- a/mobile/src/source-control/mobile-hosted-review-service.ts +++ b/mobile/src/source-control/mobile-hosted-review-service.ts @@ -6,10 +6,16 @@ import type { HostedReviewLookupOutcome, HostedReviewProvider } from '../../../src/shared/hosted-review' -import type { RpcClient } from '../transport/rpc-client' -import type { RpcSuccess } from '../transport/types' +import type { RpcSendParams } from '../transport/rpc-params-contract' +import { refusedRpcMessageOrFallback } from '../transport/rpc-refusal-message' import { hostedReviewCopy } from './hosted-review-copy' +import { + hostedReviewCreateRun, + hostedReviewEligibilityRead +} from './mobile-hosted-review-operations' +import { pushMobileHostedReviewBranch } from './mobile-hosted-review-git-preparation' import { linkMobileHostedReview } from './mobile-pr-link' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' // The mobile worktree id is `${repoId}::${path}`; hosted-review RPCs expect the // repo selector separately, matching the desktop/runtime hosted-review service. @@ -31,11 +37,11 @@ export type MobileHostedReviewEligibilityInput = { } export async function fetchMobileHostedReviewEligibility( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, input: MobileHostedReviewEligibilityInput ): Promise { - const response = await client.sendRequest('hostedReview.getCreationEligibility', { + const reply = await hostedReviewEligibilityRead.request(client, { repo: mobileRepoSelectorFromWorktreeId(worktreeId), worktree: `id:${worktreeId}`, branch: input.branch, @@ -49,10 +55,9 @@ export async function fetchMobileHostedReviewEligibility( linkedGitHubPR: input.linkedGitHubPR ?? null, linkedGitLabMR: input.linkedGitLabMR ?? null }) - if (!response.ok) { - return null - } - return (response as RpcSuccess).result as HostedReviewCreationEligibility + const eligibility = hostedReviewEligibilityRead.interpret(reply) + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Preserve the established response shape at this boundary. + return eligibility.accepted ? (eligibility.value as HostedReviewCreationEligibility) : null } export type MobileHostedReviewPrefill = { @@ -73,7 +78,7 @@ export type MobileHostedReviewPrefill = { // service desktop uses. If eligibility is unavailable, return a blocked prefill // instead of inventing a provider/base locally. export async function resolveMobileHostedReviewPrefill( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, args: { branch: string | undefined @@ -154,7 +159,7 @@ export type MobileHostedReviewCreateInput = { export function buildMobileHostedReviewCreateParams( worktreeId: string, input: MobileHostedReviewCreateInput -): Record { +): RpcSendParams<'hostedReview.create'> { return { repo: mobileRepoSelectorFromWorktreeId(worktreeId), worktree: `id:${worktreeId}`, @@ -172,19 +177,20 @@ export type MobileHostedReviewCreateOutcome = | { ok: true; url: string; number?: number; existing?: boolean; linkError?: string } | { ok: false; error: string } +const PUSH_BEFORE_CREATE_ERROR = 'Push failed. Resolve the push error, then try again.' + +// Why the host's own message is discarded here: the compose form shows one actionable line for +// every push failure, refusal and transport drop alike. async function pushMobileBranchBeforeCreate( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string ): Promise<{ ok: true } | { ok: false; error: string }> { - try { - const response = await client.sendRequest('git.push', { worktree: `id:${worktreeId}` }) - if (!response.ok) { - return { ok: false, error: 'Push failed. Resolve the push error, then try again.' } - } - return { ok: true } - } catch { - return { ok: false, error: 'Push failed. Resolve the push error, then try again.' } - } + const pushed = await pushMobileHostedReviewBranch( + client, + { worktree: `id:${worktreeId}` }, + PUSH_BEFORE_CREATE_ERROR + ) + return pushed.ok ? { ok: true } : { ok: false, error: PUSH_BEFORE_CREATE_ERROR } } function formatMobileHostedReviewCreateError( @@ -203,7 +209,7 @@ function formatMobileHostedReviewCreateError( } async function finishMobileHostedReviewCreateSuccess( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, input: MobileHostedReviewCreateInput, result: { number: number; url: string }, @@ -225,7 +231,7 @@ async function finishMobileHostedReviewCreateSuccess( } export async function createMobileHostedReview( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, input: MobileHostedReviewCreateInput ): Promise { @@ -238,14 +244,20 @@ export async function createMobileHostedReview( } pushed = true } - const response = await client.sendRequest( - 'hostedReview.create', + const reply = await hostedReviewCreateRun.request( + client, buildMobileHostedReviewCreateParams(worktreeId, input) ) - if (!response.ok) { - return { ok: false, error: response.error?.message || 'Failed to create pull request' } + let result: CreateHostedReviewResult + try { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Preserve the established response shape at this boundary. + result = hostedReviewCreateRun.interpret(reply) as CreateHostedReviewResult + } catch (error) { + return { + ok: false, + error: refusedRpcMessageOrFallback(error, 'Failed to create pull request') + } } - const result = (response as RpcSuccess).result as CreateHostedReviewResult if (result.ok) { return finishMobileHostedReviewCreateSuccess(client, worktreeId, input, result) } diff --git a/mobile/src/source-control/mobile-pr-link.ts b/mobile/src/source-control/mobile-pr-link.ts index 1befb2eebfa..351d534218b 100644 --- a/mobile/src/source-control/mobile-pr-link.ts +++ b/mobile/src/source-control/mobile-pr-link.ts @@ -1,6 +1,8 @@ -import type { RpcClient } from '../transport/rpc-client' -import type { RpcSuccess } from '../transport/types' +import type { RpcSendParams } from '../transport/rpc-params-contract' +import { refusedRpcMessageOrFallback } from '../transport/rpc-refusal-message' import type { HostedReviewProvider } from '../../../src/shared/hosted-review' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' +import { worktreeLinkSet, worktreeSummaryRead } from './mobile-worktree-metadata-operations' // Link / unlink review metadata via worktree.set (the same path desktop uses). // GitHub's existing manual link flow writes linkedPR; hosted-review creation maps @@ -13,7 +15,7 @@ export type MobilePrLinkOutcome = { ok: true } | { ok: false; error: string } export function buildWorktreeSetLinkParams( worktreeId: string, linkedPR: number | null -): Record { +): RpcSendParams<'worktree.set'> { return { worktree: `id:${worktreeId}`, linkedPR } } @@ -22,7 +24,7 @@ export function buildWorktreeSetHostedReviewLinkParams( provider: HostedReviewProvider, number: number | null, options?: { baseRef?: string | null } -): Record { +): RpcSendParams<'worktree.set'> { const trimmedBaseRef = options?.baseRef?.trim() const base = { worktree: `id:${worktreeId}`, @@ -44,40 +46,43 @@ export function buildWorktreeSetHostedReviewLinkParams( } } -async function setLinkedPr( - client: Pick, - worktreeId: string, - linkedPR: number | null +/** + * Two catches, because main had two paths: a refusal falls back to the screen's copy when the + * host sent no message, while a transport drop surfaces its own message verbatim. + */ +async function setWorktreeReviewLink( + client: MobileSourceControlRpcSender, + params: RpcSendParams<'worktree.set'>, + fallback: string ): Promise { + let reply try { - const response = await client.sendRequest( - 'worktree.set', - buildWorktreeSetLinkParams(worktreeId, linkedPR) - ) - if (!response.ok) { - return { ok: false, error: response.error?.message || 'Failed to update linked pull request' } - } - return { ok: true } - } catch (err) { - // Why: a transport drop must not escape as an unhandled rejection — normalize - // to the `{ ok:false, error }` outcome the link flow surfaces. - return { - ok: false, - error: err instanceof Error ? err.message : 'Failed to update linked pull request' - } + reply = await worktreeLinkSet.request(client, params) + } catch (error) { + return { ok: false, error: error instanceof Error ? error.message : fallback } } + try { + worktreeLinkSet.interpret(reply) + } catch (error) { + return { ok: false, error: refusedRpcMessageOrFallback(error, fallback) } + } + return { ok: true } } export function linkMobilePr( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, prNumber: number ): Promise { - return setLinkedPr(client, worktreeId, prNumber) + return setWorktreeReviewLink( + client, + buildWorktreeSetLinkParams(worktreeId, prNumber), + 'Failed to update linked pull request' + ) } export async function linkMobileHostedReview( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string, provider: HostedReviewProvider, number: number, @@ -87,44 +92,32 @@ export async function linkMobileHostedReview( if (Object.keys(params).length === 1) { return { ok: true } } - try { - const response = await client.sendRequest('worktree.set', params) - if (!response.ok) { - return { ok: false, error: response.error?.message || 'Failed to update linked review' } - } - return { ok: true } - } catch (err) { - // Why: the review was already created; normalize link failures so callers can - // surface a non-fatal refresh problem instead of losing the created URL. - return { - ok: false, - error: err instanceof Error ? err.message : 'Failed to update linked review' - } - } + // Why a distinct fallback: the review already exists, so callers surface this as a non-fatal + // refresh problem rather than losing the created URL. + return setWorktreeReviewLink(client, params, 'Failed to update linked review') } export function unlinkMobilePr( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string ): Promise { - return setLinkedPr(client, worktreeId, null) + return setWorktreeReviewLink( + client, + buildWorktreeSetLinkParams(worktreeId, null), + 'Failed to update linked pull request' + ) } -// Reads the worktree's persisted linkedPR (via worktree.show) so the sidebar can -// surface a linked PR even when it's closed/merged and the branch-based lookup -// returns nothing. Returns null when unset or on any read failure. +// Reads the worktree's persisted linkedPR so the sidebar can surface a linked PR even when it's +// closed/merged and the branch-based lookup returns nothing. Null when unset or on any failure. export async function fetchWorktreeLinkedPR( - client: Pick, + client: MobileSourceControlRpcSender, worktreeId: string ): Promise { try { - const response = await client.sendRequest('worktree.show', { worktree: `id:${worktreeId}` }) - if (!response.ok) { - return null - } - const result = (response as RpcSuccess).result as { worktree?: { linkedPR?: number | null } } - const linked = result?.worktree?.linkedPR - return typeof linked === 'number' ? linked : null + const reply = await worktreeSummaryRead.request(client, { worktree: `id:${worktreeId}` }) + const summary = worktreeSummaryRead.interpret(reply) + return summary.accepted ? (summary.value?.linkedPR ?? null) : null } catch { // Why: a fallback read — a transport drop is non-fatal, fall back to "no link". return null diff --git a/mobile/src/source-control/mobile-repo-base-ref-operations.ts b/mobile/src/source-control/mobile-repo-base-ref-operations.ts new file mode 100644 index 00000000000..39ddee26880 --- /dev/null +++ b/mobile/src/source-control/mobile-repo-base-ref-operations.ts @@ -0,0 +1,68 @@ +import { bindDeferredRpcOperation, defineRpcOperation } from '../transport/rpc-operation' +import type { RpcCompatibleReader } from '../transport/rpc-operation-contract' + +export type MobileRepoBaseRefSummary = { + readonly id: string + readonly worktreeBaseRef: string | null +} + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null +} + +const repoBaseRefSummariesReader: RpcCompatibleReader< + unknown, + 'repo-base-refs', + MobileRepoBaseRefSummary[] +> = (raw) => ({ + compatible: true, + variant: 'repo-base-refs', + value: + isRecord(raw) && Array.isArray(raw.repos) + ? raw.repos.flatMap((candidate): MobileRepoBaseRefSummary[] => + isRecord(candidate) && typeof candidate.id === 'string' + ? [ + { + id: candidate.id, + worktreeBaseRef: + typeof candidate.worktreeBaseRef === 'string' ? candidate.worktreeBaseRef : null + } + ] + : [] + ) + : [], + salvage: { droppedPaths: [], droppedCount: 0 } +}) + +/** Only the base-ref hint is read here; the repo catalog itself has its own callers. */ +export const repoBaseRefListRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'repo.base-ref-list-or-skip', + method: 'repo.list', + acceptance: 'success-result-or-skip', + barrier: 'after-caller-barrier', + read: repoBaseRefSummariesReader + }) +) + +const defaultBaseRefReader: RpcCompatibleReader = ( + raw +) => ({ + compatible: true, + variant: 'default-base-ref', + value: + isRecord(raw) && typeof raw.defaultBaseRef === 'string' + ? raw.defaultBaseRef.trim() || null + : null, + salvage: { droppedPaths: [], droppedCount: 0 } +}) + +export const repoDefaultBaseRefRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'repo.default-base-ref', + method: 'repo.baseRefDefault', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: defaultBaseRefReader + }) +) diff --git a/mobile/src/source-control/mobile-source-control-rpc-sender.ts b/mobile/src/source-control/mobile-source-control-rpc-sender.ts new file mode 100644 index 00000000000..4b7eb44ec15 --- /dev/null +++ b/mobile/src/source-control/mobile-source-control-rpc-sender.ts @@ -0,0 +1,10 @@ +import { gitStatusHostPayloadRead } from './mobile-git-read-operations' + +/** + * What a source-control operation needs to send with. + * + * Derived from an operation rather than restated, so accepting a client does not require a module + * to name the raw request port. It stays exactly as narrow as the `Pick` + * it replaces — widening it to `RpcClient` would make every unit test build a whole client. + */ +export type MobileSourceControlRpcSender = Parameters[0] diff --git a/mobile/src/source-control/mobile-source-file-open-operations.ts b/mobile/src/source-control/mobile-source-file-open-operations.ts new file mode 100644 index 00000000000..f9090dfaf65 --- /dev/null +++ b/mobile/src/source-control/mobile-source-file-open-operations.ts @@ -0,0 +1,68 @@ +import { bindDeferredRpcOperation, defineRpcOperation } from '../transport/rpc-operation' +import type { RpcCompatibleReader } from '../transport/rpc-operation-contract' +import { rpcUncheckedPayloadReader } from '../transport/rpc-reader-payload' + +// Opening a file from the Changes list. Neither reply's payload is read: the tab arrives over the +// session stream, and the caller only needs to know the host accepted. + +export const sourceFileDiffOpenRun = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'files.open-diff-tab', + method: 'files.openDiff', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('diff-tab-opened') + }) +) + +/** The fallback when a host is too old to offer a diff tab. */ +export const sourceFileOpenRun = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'files.open-edit-tab', + method: 'files.open', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('edit-tab-opened') + }) +) + +export type MobileSessionFileTabCandidate = { + readonly id: string + readonly type: string + readonly mode?: unknown + readonly relativePath?: unknown + readonly diffSource?: unknown +} + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null +} + +function isSessionFileTabCandidate(value: unknown): value is MobileSessionFileTabCandidate { + return isRecord(value) && typeof value.id === 'string' && typeof value.type === 'string' +} + +const sessionFileTabsReader: RpcCompatibleReader< + unknown, + 'session-file-tabs', + { tabs: MobileSessionFileTabCandidate[] } | null +> = (raw) => ({ + compatible: true, + variant: 'session-file-tabs', + value: + isRecord(raw) && Array.isArray(raw.tabs) && raw.tabs.every(isSessionFileTabCandidate) + ? { tabs: raw.tabs } + : null, + salvage: { droppedPaths: [], droppedCount: 0 } +}) + +/** A refused list means poll again, so refusal is a skip rather than the end of the reveal. */ +export const sessionFileTabListRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'session.file-tab-list-or-skip', + method: 'session.tabs.list', + acceptance: 'success-result-or-skip', + barrier: 'after-caller-barrier', + read: sessionFileTabsReader + }) +) diff --git a/mobile/src/source-control/mobile-worktree-metadata-operations.ts b/mobile/src/source-control/mobile-worktree-metadata-operations.ts new file mode 100644 index 00000000000..6619b356a8e --- /dev/null +++ b/mobile/src/source-control/mobile-worktree-metadata-operations.ts @@ -0,0 +1,58 @@ +import { bindDeferredRpcOperation, defineRpcOperation } from '../transport/rpc-operation' +import type { RpcCompatibleReader } from '../transport/rpc-operation-contract' +import { rpcUncheckedPayloadReader } from '../transport/rpc-reader-payload' + +export type MobileWorktreeSummary = { + readonly baseRef: string | null + readonly linkedPR: number | null +} + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null +} + +/** + * One reader for both worktree.show consumers. Branch compare read `worktree.baseRef` behind an + * `isRecord` guard and the PR sidebar read `worktree.linkedPR` through optional chaining; both + * yield null on the same inputs, so the fields merge without changing either answer. + */ +const worktreeSummaryReader: RpcCompatibleReader< + unknown, + 'worktree-summary', + MobileWorktreeSummary | null +> = (raw) => { + const worktree = isRecord(raw) ? raw.worktree : undefined + return { + compatible: true, + variant: 'worktree-summary', + value: isRecord(worktree) + ? { + baseRef: typeof worktree.baseRef === 'string' ? worktree.baseRef : null, + linkedPR: typeof worktree.linkedPR === 'number' ? worktree.linkedPR : null + } + : null, + salvage: { droppedPaths: [], droppedCount: 0 } + } +} + +/** A refused show is a missing hint, not a failure: both callers fall back to another source. */ +export const worktreeSummaryRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'worktree.summary-or-skip', + method: 'worktree.show', + acceptance: 'success-result-or-skip', + barrier: 'after-caller-barrier', + read: worktreeSummaryReader + }) +) + +/** Persisting a review link. The payload is unread; only acceptance matters. */ +export const worktreeLinkSet = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'worktree.set-review-link', + method: 'worktree.set', + acceptance: 'require-result-or-throw-message', + barrier: 'after-caller-barrier', + read: rpcUncheckedPayloadReader('link-accepted') + }) +) diff --git a/mobile/src/source-control/reveal-mobile-source-control-session-diff.ts b/mobile/src/source-control/reveal-mobile-source-control-session-diff.ts index 9391c0c2961..7b0c2082c38 100644 --- a/mobile/src/source-control/reveal-mobile-source-control-session-diff.ts +++ b/mobile/src/source-control/reveal-mobile-source-control-session-diff.ts @@ -1,18 +1,12 @@ -import type { RpcClient } from '../transport/rpc-client' import { activateMobileSessionTab } from '../session/mobile-session-tab-activation' - -type ActivationClient = Pick - -type SessionFileTabCandidate = { - id: string - type: string - mode?: unknown - relativePath?: unknown - diffSource?: unknown -} +import { + sessionFileTabListRead, + type MobileSessionFileTabCandidate +} from './mobile-source-file-open-operations' +import type { MobileSourceControlRpcSender } from './mobile-source-control-rpc-sender' type Options = { - client: ActivationClient + client: MobileSourceControlRpcSender worktreeId: string relativePath: string tabMode: 'diff' | 'edit' @@ -59,20 +53,19 @@ export async function revealMobileSourceControlSessionDiff( return 'timeout' } -async function findOpenedSessionFileTab(options: Options): Promise { +async function findOpenedSessionFileTab( + options: Options +): Promise { try { - const response = await options.client.sendRequest('session.tabs.list', { + const reply = await sessionFileTabListRead.request(options.client, { worktree: `id:${options.worktreeId}` }) - if (!response.ok) { - return null - } - const snapshot = readTabSnapshot(response.result) - if (!snapshot) { + const listed = sessionFileTabListRead.interpret(reply) + if (!listed.accepted || !listed.value) { return null } - const matches = snapshot.tabs.filter( + const matches = listed.value.tabs.filter( (tab) => tab.type !== 'browser' && tab.type !== 'terminal' && @@ -112,21 +105,6 @@ async function activateSessionFileTab(options: Options, tabId: string): Promise< } } -function readTabSnapshot(value: unknown): { tabs: SessionFileTabCandidate[] } | null { - if ( - !isRecord(value) || - !Array.isArray(value.tabs) || - !value.tabs.every(isSessionFileTabCandidate) - ) { - return null - } - return { tabs: value.tabs } -} - -function isSessionFileTabCandidate(value: unknown): value is SessionFileTabCandidate { - return isRecord(value) && typeof value.id === 'string' && typeof value.type === 'string' -} - function readActiveTabId(value: unknown): string | null { return isRecord(value) && typeof value.activeTabId === 'string' ? value.activeTabId : null } diff --git a/mobile/src/source-control/use-mobile-source-control-loaders.ts b/mobile/src/source-control/use-mobile-source-control-loaders.ts index 86055d21d3f..da03e8639b5 100644 --- a/mobile/src/source-control/use-mobile-source-control-loaders.ts +++ b/mobile/src/source-control/use-mobile-source-control-loaders.ts @@ -1,11 +1,14 @@ import { useCallback, useEffect, useRef, useState, type MutableRefObject } from 'react' import { View } from 'react-native' import type { RpcClient } from '../transport/rpc-client' -import type { ConnectionState, RpcSuccess } from '../transport/types' +import { refusedRpcMessageOrFallback } from '../transport/rpc-refusal-message' +import type { ConnectionState } from '../transport/types' import { resolveMobileBranchCompareBaseRef } from './mobile-branch-base-ref' +import { gitBranchCompareRead, gitStatusHostPayloadRead } from './mobile-git-read-operations' import { - isMobileGitUnavailable, isMobileGitTransientRefreshError, + isMobileGitUnavailableReply, + readMobileGitRefusal, type MobileGitStatusResult } from './mobile-git-status' import type { MobileGitBranchCompareResult } from './mobile-branch-compare' @@ -117,28 +120,34 @@ export function useMobileSourceControlLoaders(params: Params): MobileSourceContr }) return false } - const response = await client.sendRequest('git.branchCompare', { + const reply = await gitBranchCompareRead.request(client, { worktree: `id:${worktreeId}`, baseRef }) if (!isCurrentLoad()) { return false } - if (!response.ok) { - if (isMobileGitUnavailable(response.error?.code, response.error?.message)) { - setBranchCompareState((prev) => { - if (options?.preserveReadyOnFailure && prev.kind === 'ready') { - return prev - } - return { kind: 'idle' } - }) - return false - } - throw new Error(response.error?.message || 'Unable to load committed changes') + // Why the raw refusal: a host that does not offer git to mobile is a capability gap this + // screen degrades on, and no acceptance policy carries the code and message through. + if (isMobileGitUnavailableReply(reply)) { + setBranchCompareState((prev) => { + if (options?.preserveReadyOnFailure && prev.kind === 'ready') { + return prev + } + return { kind: 'idle' } + }) + return false + } + let compared: unknown + try { + compared = gitBranchCompareRead.interpret(reply) + } catch (error) { + throw new Error(refusedRpcMessageOrFallback(error, 'Unable to load committed changes')) } setBranchCompareState({ kind: 'ready', - result: (response as RpcSuccess).result as MobileGitBranchCompareResult + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Preserve the established response shape at this boundary. + result: compared as MobileGitBranchCompareResult }) return true } catch (err) { @@ -195,14 +204,18 @@ export function useMobileSourceControlLoaders(params: Params): MobileSourceContr setScreenState((prev) => (prev.kind === 'ready' ? prev : { kind: 'loading' })) try { for (let attempt = 0; attempt <= SELECTOR_RETRY_COUNT; attempt += 1) { - const response = await client.sendRequest('git.status', { + const reply = await gitStatusHostPayloadRead.request(client, { worktree: `id:${worktreeId}` }) if (!isCurrentLoad()) { return false } - if (response.ok) { - const result = (response as RpcSuccess).result as MobileGitStatusResult + // Why the raw refusal: the retry and capability routes below are decided by the + // refusal's code, which no acceptance policy carries through. + const refusal = readMobileGitRefusal(reply) + if (!refusal) { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Preserve the established response shape at this boundary. + const result = gitStatusHostPayloadRead.interpret(reply) as MobileGitStatusResult setScreenState({ kind: 'ready', status: result }) void loadBranchCompare({ preserveReadyOnFailure: true }) if (options?.clearActionErrorOnSuccess !== false) { @@ -213,7 +226,7 @@ export function useMobileSourceControlLoaders(params: Params): MobileSourceContr onStatusLoadSuccess?.() return true } - if (isMobileGitUnavailable(response.error?.code, response.error?.message)) { + if (isMobileGitUnavailableReply(reply)) { setScreenState({ kind: 'unavailable', message: 'Update Orca desktop to use Source Control on mobile.' @@ -221,8 +234,8 @@ export function useMobileSourceControlLoaders(params: Params): MobileSourceContr return false } const shouldRetry = - response.error?.code === 'selector_not_found' || - isMobileGitTransientRefreshError(response.error?.code, response.error?.message) + refusal.code === 'selector_not_found' || + isMobileGitTransientRefreshError(refusal.code, refusal.message) if (shouldRetry && attempt < SELECTOR_RETRY_COUNT) { await wait(SELECTOR_RETRY_DELAY_MS) if (!isCurrentLoad()) { @@ -230,7 +243,7 @@ export function useMobileSourceControlLoaders(params: Params): MobileSourceContr } continue } - throw new Error(response.error?.message || 'Unable to load source control') + throw new Error(refusal.message || 'Unable to load source control') } } catch (err) { if (!isCurrentLoad()) { diff --git a/mobile/src/source-control/use-mobile-source-control-openers.ts b/mobile/src/source-control/use-mobile-source-control-openers.ts index f6c44825715..4d92964c803 100644 --- a/mobile/src/source-control/use-mobile-source-control-openers.ts +++ b/mobile/src/source-control/use-mobile-source-control-openers.ts @@ -1,7 +1,8 @@ import { useCallback, useRef, useState, type MutableRefObject } from 'react' import { useRouter } from 'expo-router' import type { RpcClient } from '../transport/rpc-client' -import type { ConnectionState, RpcSuccess } from '../transport/types' +import { refusedRpcMessageOrFallback } from '../transport/rpc-refusal-message' +import type { ConnectionState } from '../transport/types' import { triggerError, triggerSelection } from '../platform/haptics' import { buildMobileDiffLines } from '../session/mobile-diff-lines' import { @@ -12,11 +13,13 @@ import { canOpenMobileBranchCompareDiff, type MobileGitBranchChangeEntry } from './mobile-branch-compare' +import { gitBranchDiffRead } from './mobile-git-read-operations' import { canOpenMobileGitStatusEntry, - isMobileGitUnavailable, + isMobileGitUnavailableReply, type MobileGitStatusEntry } from './mobile-git-status' +import { sourceFileDiffOpenRun, sourceFileOpenRun } from './mobile-source-file-open-operations' import { buildMobileReviewFileRoute } from './mobile-review-route' import { revealMobileSourceControlSessionDiff } from './reveal-mobile-source-control-session-diff' import type { @@ -111,21 +114,29 @@ export function useMobileSourceControlOpeners(params: Params) { // the session uses it to avoid stealing focus if the user switches tabs // during the RPC window. onFileOpenStart?.() - let response = await client.sendRequest('files.openDiff', { + const diffReply = await sourceFileDiffOpenRun.request(client, { worktree: `id:${worktreeId}`, relativePath: entry.path, staged: entry.area === 'staged' }) - let openedTabMode: 'diff' | 'edit' = 'diff' - if (!response.ok && isMobileGitUnavailable(response.error?.code, response.error?.message)) { - response = await client.sendRequest('files.open', { - worktree: `id:${worktreeId}`, - relativePath: entry.path - }) - openedTabMode = 'edit' - } - if (!response.ok) { - throw new Error(response.error?.message || 'Unable to open diff') + // Why the raw refusal: a host too old to open a diff tab is a capability gap this flow + // falls back from, and no acceptance policy carries the code and message through. + const fallbackToEdit = isMobileGitUnavailableReply(diffReply) + const openedTabMode: 'diff' | 'edit' = fallbackToEdit ? 'edit' : 'diff' + const editReply = fallbackToEdit + ? await sourceFileOpenRun.request(client, { + worktree: `id:${worktreeId}`, + relativePath: entry.path + }) + : undefined + try { + if (editReply) { + sourceFileOpenRun.interpret(editReply) + } else { + sourceFileDiffOpenRun.interpret(diffReply) + } + } catch (error) { + throw new Error(refusedRpcMessageOrFallback(error, 'Unable to open diff')) } if (!mountedRef.current) { return @@ -231,7 +242,7 @@ export function useMobileSourceControlOpeners(params: Params) { } setBranchDiffPreview({ kind: 'loading', entry }) try { - const response = await client.sendRequest('git.branchDiff', { + const reply = await gitBranchDiffRead.request(client, { worktree: `id:${worktreeId}`, filePath: entry.path, ...(entry.oldPath ? { oldPath: entry.oldPath } : {}), @@ -242,10 +253,14 @@ export function useMobileSourceControlOpeners(params: Params) { mergeBase: summary.mergeBase } }) - if (!response.ok) { - throw new Error(response.error?.message || 'Unable to load committed diff') + let interpreted: unknown + try { + interpreted = gitBranchDiffRead.interpret(reply) + } catch (error) { + throw new Error(refusedRpcMessageOrFallback(error, 'Unable to load committed diff')) } - const result = (response as RpcSuccess).result as GitDiffTextResult | { kind: 'binary' } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Preserve the established response shape at this boundary. + const result = interpreted as GitDiffTextResult | { kind: 'binary' } if (result.kind !== 'text') { throw new Error('Binary branch diff preview unavailable on mobile') } diff --git a/mobile/src/terminal/terminal-copy-gutter-preference.ts b/mobile/src/terminal/terminal-copy-gutter-preference.ts new file mode 100644 index 00000000000..b5e80d542d3 --- /dev/null +++ b/mobile/src/terminal/terminal-copy-gutter-preference.ts @@ -0,0 +1,43 @@ +import { useEffect, useRef, type RefObject } from 'react' +import { terminalCopyTrimsGutterRead } from '../transport/settings-read-operations' +import type { RpcClient } from '../transport/rpc-client' +import type { ConnectionState } from '../transport/types' + +/** + * Desktop owns "Trim Gutter on Copy" (GlobalSettings.terminalCopyTrimsGutter); + * mobile mirrors it so turning the setting off yields verbatim screen cells on + * every surface. Read once per connection — the mobile RPC has no + * settings-change stream — and default to on while the read is in flight. + */ +export function useTerminalCopyTrimsGutter( + client: RpcClient | null, + connState: ConnectionState +): RefObject { + const trimsGutterRef = useRef(true) + + useEffect(() => { + if (!client || connState !== 'connected') { + return + } + let stale = false + void terminalCopyTrimsGutterRead + .request(client) + .then((response) => { + if (stale) { + return + } + const preference = terminalCopyTrimsGutterRead.interpret(response) + if (preference.accepted) { + trimsGutterRef.current = preference.value + } + }) + .catch(() => { + // Best-effort: an unreachable host leaves the on-by-default trim in place. + }) + return () => { + stale = true + } + }, [client, connState]) + + return trimsGutterRef +} diff --git a/mobile/src/test-support/rpc-recording/README.md b/mobile/src/test-support/rpc-recording/README.md new file mode 100644 index 00000000000..7870eb239bf --- /dev/null +++ b/mobile/src/test-support/rpc-recording/README.md @@ -0,0 +1,317 @@ +# Main RPC recordings + +Test infrastructure only. `pilot-scenarios.json` binds logical operations/actions to small +mount adapters. The adapters execute the actual product modules from the selected source +root, using React's test renderer; they do not reconstruct acceptance or lifecycle logic. +The module loader transpiles the real source with TypeScript and resolves task barrels +lazily so unused native views do not need a device. Accessing an unspecified native import +fails. The history metadata function is exposed to its adapter without rewriting its body. + +The transport reuses `createStableLogicalRpcClient`, `projectMobileRpcRequestParams` +(through that client), `RpcClientRequestTracker`, and the delivery-unknown marker. Hook +mounting follows `use-mobile-native-chat-file-search.test.ts`; physical session mounting +follows `stable-logical-rpc-client.test.ts`. Neither test exported a reusable mount utility. + +## Scenario actions + +```json +{"action":"mount","id":"mount"} +{"action":"query","id":"old-query","args":{"query":"old"}} +{"advance":120} +{"complete":"files.searchPaths#1","params":{"worktree":"id:A","query":"old","limit":16},"reply":{"ok":false,"error":{"code":"method_not_found","message":"Unknown method"}}} +{"bind":"old-inventory","request":"files.list#1","params":{"worktree":"id:A"}} +{"checkpoint":"pending"} +{"action":"select","id":"select-b","args":{"workspace":"B"}} +{"action":"select","id":"reset-a","args":{"workspace":"A"}} +{"complete":"old-inventory","params":{"worktree":"id:A"},"reply":{"ok":true,"result":{"files":[]}}} +{"checkpoint":"stale-completed"} +``` + +`{"$undefined":true}` in the input means explicit undefined, including an own property; +absence remains absence. Completion params are asserted against projected sender params. +Concurrent requests of one method require a logical binding and asserted params; random +wire ids never identify completions. Timers only advance explicitly, and zero-time drains +flush due timers, promise continuations, and React work after every step. Date, performance, +Math.random, Web Crypto random bytes/UUIDs, and transport ids are deterministic. + +### Recorded time + +Every settlement carries `startedAt` and `settledAt` in virtual milliseconds since the pinned epoch, +so the projection has a temporal dimension instead of relying on where a checkpoint happens to sit. +Any transition the product schedules for itself is recorded at the time it actually fires: change a +request deadline or the search debounce by any amount, in either direction, and a recorded number +moves. Granularity is exact milliseconds, because the fake timers fire at their scheduled time and +never coalesce; `recording-runner.test.ts` pins a 5 ms deadline settling at exactly `settledAt: 5`. + +A checkpoint's own clock is not recorded. It is always the sum of the scripted `advance` steps, so +it is a function of the scenario rather than of the code under test; `run-recording.ts` asserts that +equality at every checkpoint instead, which costs no bytes and fails loudly if it ever drifts. + +Recorded time covers thresholds the product schedules for itself. It cannot cover a threshold the +product only consults when something else makes it act, because no observation exists unless a +scenario acts inside the window. The `Date.now()` cache TTL in `use-host-repo-metadata.ts` is the +one such case here, so `settings-repo-cache-expiry` probes the cache at 59 s as well as at 60 s; +without the earlier probe a 20 s TTL and a 60 s TTL are both expired at 60 s and record identically. +That probe is coverage, not a substitute for recorded time: it bounds how small a TTL reduction is +visible, it does not make the reduction itself observable. + +## Golden schema + +Each file records `runnerVersion`, `baseline`, `lockfileSha256` (mobile's lockfile), +`recorderSha256`, `platform`, `scenarioVersion`, `projectionVersion`, `goldenFormatVersion`, +`operation`, `family`, and `namedDeltas`. `platform` and `lockfileSha256` are provenance and are +not compared: a dependency or OS that changes behaviour changes the trace itself, so comparing +them would only fail candidates on unrelated bumps. The rest are pinned. `recorderSha256` covers every non-markdown file under +this directory plus `pilot-scenarios.json`, so the runner that produced a golden is as pinned as +the product baseline: editing an adapter projection, a fixture or a scenario fails candidate mode +on the header and forces a deliberate re-record. Checkpoints +contain ordered sender calls and serialized physical application payloads, action and request +settlements, projected state, and ordered external effects. Sender args have three positional +slots; absent, undefined and null are distinct `$rpc` tags. Literal objects containing `$rpc` +are escaped. Only object keys are sorted; array/effect order, options, budgets, settlement times +and errors stay observable. Errors contain category, message and `isRpcDeliveryUnknown`, never +stack paths, plus `code` and a recursively captured `cause` when the thrown error carries them. +Platform is provenance; candidate comparison does not require the same operating system. + +### Value pool + +Format version 3 stores each distinct observation _entry_ once under `values`, keyed by the first +12 hex of sha256 over the entry's sorted-key, whitespace-free JSON. `golden-value-pool.ts` declares +how each field interns rather than sniffing it from the value: `sender`, `payloads` and `effects` +are lists of pool hashes, `settlements` is a map from action id to a pool hash, and `state` is one +hash. A field recorded in a container its declaration does not name fails, so a projection change +cannot silently flip a field's encoding. Files stay pretty-printed; compact printing and recursive +interning of nested sub-values were measured and rejected. + +Version 2 pooled each field _whole_, which stored the shared prefix of these append-only histories +once per checkpoint — and once per reply partition in a matrix golden. Interning per entry is a +pure re-encoding: the resolved `Recording` is unchanged, which is why the version bump moved no +observation. Over the 153 goldens it is 5.35 MB → 2.78 MB raw, and the pathological family +(`hostedReview.create-intent`, 12 sites over a 12-request chain) 2.0 MB → 792 KB. + +It also makes a real diff smaller rather than larger, which is the opposite of what version 2's +note predicted. Adding a `timeoutMs` to the first `git.status` of the create-intent chain — an +early request every downstream checkpoint re-states — touches the same 16 files either way, but +under version 2 that is ±17,100 lines and 1.03 MB of diff, and under version 3 ±3,764 lines and +0.20 MB, because a moved entry no longer rewrites every field value that contains it. + +`readGolden` refuses any other `goldenFormatVersion`, checks that every pooled entry hashes to its +own key and that no entry sits in the pool unreferenced — content addressing is what keeps an entry +shared across checkpoints honest, and an unread entry would be content in the file that nothing +compares. It then resolves hashes back to values, and `compareGolden` reports the scenario, the +checkpoint id, the field, the JSON path inside it, and both resolved values. + +### Prelude checkpoints + +A generated variant declares the index where its distinguishing input lands. Checkpoints before +that index observe steps identical to the base, so `hoistPreludeCheckpoints` records them once in +a `.prelude` scenario and starts each variant at its own divergence; it asserts each +variant's pre-divergence prefix matches the base. Reply matrices, interruption schedules and +lifecycle schedules use it. Checkpoints that merely happen to be equal are never merged: reaching +the same state through different inputs is evidence. Sibling schedules already drop their shared +prefix, so they are unchanged. + +Nothing about a shared prelude is unverified. The `.prelude` scenario's checkpoints live in the same +golden as the variants that start after them, and `compareGolden` walks every checkpoint in the +file, so changing the prelude fails the golden it belongs to. The value pool does not weaken that: +it is per-file and content-addressed, so a prelude entry a later checkpoint re-states is stored once +and any change to it moves the hash in every checkpoint that reads it. + +Family matrices and schedule recordings retain both boundaries. Matrices execute +raw reply partitions at the scripted sender port; they do not claim malformed-frame coverage +through direct/relay frame validation. Caches +are tested by follow-up requests; no private cache maps are inspected. + +Every family runs the eleven partitions in `reply-matrix.ts` at **every reply its base scenario +scripts**, one golden per site, and nothing is crossed against consumed fields. The partitions are +the reply shapes a host can send: a normal result, an absent result, `null`, an inner `{ok: false}` +envelope with a string or object error, an inner envelope missing `ok`, an outer refusal with and +without a message, `method_not_found`, and a transport rejection with and without a message. Shapes +that were recorded before and are gone were unreachable: `successResponse` always sets `result`, so +JSON carries no explicit-undefined slot, and no mounted method's handler returns a number, a string, +an array, a bare `{}`, or a boolean. `null` stays because `linear.getIssue` returns it for a missing +issue and the b2 seed is a shipped null-result bug. + +The message-less refusal and rejection are what separate the two failure paths a migrated call site +must keep apart: a refusal with no message falls back to the screen's copy, a transport drop with no +message surfaces its empty message verbatim. With only the message-carrying shapes both produce the +same text, so collapsing the two catches is invisible. Every source-control family used to carry a +hand-written `*-empty-message` scenario for exactly that; the partition carries it now. + +### Which request a matrix drives + +All of them. Selecting one per family was a hardcoded prefix list, and it silently `continue`d past +any family it did not name — ten of twenty-three, every family the source-control migration added, +which is why that migration's mutation evidence came down to single hand-written scenarios. +`replyMatrixSites` takes every completion step in the family's base scenario instead: no judgement +about which request is the "real" one, and no edit when a domain is added. A family that scripts no +reply at all throws, and a repeated request name throws, because the divergence would be ambiguous. + +A variant answers its own site differently, so the replies scripted after it may never be asked +for. Those steps are marked `optional` and are answered only if the request is outstanding; the +sender list in each checkpoint records which ones the operation actually sent. + +The `normal` partition replays a result the family already records for that request — the first +fulfilled reply in scenario order, base first — so no migrator invents a plausible payload per +domain. `null` and absent do not count, because each is already a partition of its own and +replaying one would leave the site with no success control. A site whose family records no other +success fails the suite until it is given a fulfilled scenario or a line in +`REPLY_MATRIX_NORMAL_RESULT_INVENTORY`, which carries the reply and the reason; an entry whose +family has since recorded a success fails too, so the list only shrinks. Four sites are on it: both +legs of the b3 seed, whose single scenario exists to record the defect; the b2 seed, whose only +recorded success is the shipped null result; and `settings.update`, a best-effort write whose reply +body no call site reads. + +Detached unhandled rejections are captured as effects in a sequential process-scoped window, +with prior process listeners restored afterward. This preserves the known main bug recorded +as `new-workspace-runtime-context-null-settings-typeerror`; it does not repair the effect. +Task-model projections record setter invocations and resulting model values, not native UI. + +## Commands and checker contract + +Record only from unchanged pinned product sources and lockfile. The fence exempts only +`mobile/src/test-support/rpc-recording`, which `recorderSha256` pins instead; every other +test-support path is compared against the baseline like product code: + +```sh +ORCA_BACKGROUND_LAUNCH=1 RPC_FOUNDATION_RECORD=1 pnpm --dir mobile exec tsx scripts/rpc-recording.mts --record +ORCA_BACKGROUND_LAUNCH=1 pnpm --dir mobile test src/test-support/rpc-recording +``` + +Mutants are the defect evidence. `operation-mutations.ts` holds one anchored source edit per +adapter family, and every family's recording must change visible state when its mutant is applied, +which is what shows that family's `state()` projection observes the operation's real output. +Anchors are asserted to match exactly one site, because a repeated anchor would half-apply while +still counting as applied. Mutants replace the expression in memory, then run the same real hook. +`runRecordingMutant` accepts a mutated mounting adapter, scheduler, baseline and optional +observation projection, and returns `{verdict: "killed" | "survived", recording}`. Every mutant +test requires the mutation to apply exactly once and change visible state to count as killed. + +Set `RPC_FOUNDATION_REFERENCE_ROOT` to an archived `bcba08b3e4` source tree to corroborate the +three B-seed mutants against the real defect; the reference checkout is never edited. Each seed +pins the archived tree's visible state, so a later refactor of those files cannot pass by merely +differing from main. Archived-tree corroboration for b1/b2/b3 is **unproven in CI**: +CI does not set `RPC_FOUNDATION_REFERENCE_ROOT`. These three checks remain opt-in; the +in-memory mutant checks run in CI. No archived-tree checks are registered for other +families because no reference states are defined for them. + +## What this oracle does and does not see + +It replays 78 scenarios against frozen goldens and fails on any divergence: 153 goldens over 200 +tests, all inside `pnpm --dir mobile test`. For a migration it answers one question — does the +rewritten call site produce the same sender calls, settlements, state and effects as main did? + +It is not a substitute for reading the diff. Three facts bound it, all learned the hard way: + +- **It was blind to refusal ordering.** Reordering the settings and sibling refusal checks in + `mobile-new-tab-agent-loader.ts` survives every golden except `probe-new-tab-both-refused` — + measured by applying the reorder to the real source: 1 failure in 84 tests, and the one failure + is a probe. Every pre-probe "refused" scenario refuses on the _first_ request, and every + correlated-failure schedule rejects at the transport, where neither check is reached. A human + reviewer caught that class by reading #20499. +- **It did not observe data loss on refresh.** No pre-probe golden records state after a refused + _refresh_, so "does this screen keep its data or blank it?" was undocumented. This one is an + observational gap, not a proven detection gap: publishing an unaccepted read in + `use-new-workspace-runtime-context.ts` is caught by the refuse-after-data probe _and_ by + `matrix-settings.workspace-context`, because a refusal from cold publishes `null` over a non-null + initial value. Claim the recorded behaviour, not blindness. +- **It was blind to whatever the matrix skipped.** While the driven request came from a hardcoded + prefix list, moving `readMobileHostedReviewGitStatus`'s `interpret` into the request chain — which + turns a transport rejection into an `{ok: false}` result instead of letting it propagate — survived + all 163 tests, because no scenario rejected `git.status` for that family. Driving every scripted + reply kills it on five matrix goldens. The lesson is about the skip, not about that call site: a + generator that opts a family out without failing is indistinguishable from coverage. + +`probe-hole-witness.test.ts` closes the first two and keeps them closed. It asserts the hole and the closure +together: each probe must kill its mutation _and_ every pre-probe scenario of the same operation +must still survive it. A probe that stops being load-bearing fails instead of lingering. + +What is still not covered: what the count-based raw-port inventory covers instead (which files +reach `sendRequest`, and how often), native storage, transport skew, the `subscribe`/ +`sendUnsubscribe` ports, and the two mutations under _Known-open holes_ below. Four of the nine +probes pin behaviour with no demonstrated mutation — the two mixed reject/refusal new-tab orders +and the home-providers and resume-metadata refresh refusals; they are frozen observations, not +proven defect detectors. `settings.resume-metadata` projects `{}` as its state, so its probe +observes only sender calls and settlements. + +### Recorded finding: a refused refresh is not handled the same way twice + +The five refuse-after-data probes record `settingsRead` refusing a _refresh_ after a success. +Four call sites retain what they had. `use-mobile-tasks-runtime-hydration.tsx` does not: it +publishes `{}`, so a refused refresh wipes the runtime task settings. That divergence is recorded, +not repaired — `settings-task-hydration-refuse-after-data.json` is the observation, and changing +the behaviour is a product change with its own re-record. + +### Running it for a step-4 migration + +```sh +# 1. Before touching the call site, confirm the oracle is green on your branch. +ORCA_BACKGROUND_LAUNCH=1 pnpm --dir mobile test src/test-support/rpc-recording + +# 2. Migrate the call site. Re-run. Any divergence is your diff, reported down to the JSON path. + +# 3. If a divergence is intended, say so deliberately. Recording refuses to run unless the +# product tree matches the pinned baseline, so bump `baseline` in pilot-scenarios.json to the +# commit you are recording from first. +ORCA_BACKGROUND_LAUNCH=1 RPC_FOUNDATION_RECORD=1 \ + pnpm --dir mobile exec tsx scripts/rpc-recording.mts --record +``` + +A re-record is a claim about behaviour. State the cause in the commit; every golden the refresh +moves should have one. + +Editing the recorder itself on a migration branch is the awkward case: `recorderSha256` moves, so +every golden needs rewriting, but the product tree no longer matches `baseline`, and bumping +`baseline` to the branch would record the migrated source and make the parity claim circular. Record +from the pinned commit instead, with this branch's recorder laid over it — a detached checkout or a +`git archive` extraction of `baseline`, this tree's `rpc-recording/` and `pilot-scenarios.json` +copied in, `node_modules` symlinked, `RPC_FOUNDATION_GOLDENS` pointed at a scratch directory — then +copy the result back and run the candidate suite here. Format the recorder before recording: an +`oxfmt` pass afterwards moves `recorderSha256` again. + +If your call site carries a mutation anchor in `operation-mutations.ts`, rewriting it will make the +anchor match zero sites. Re-anchor the same defect at its new home rather than deleting the mutant: +#20499 broke five anchors that way, and each one had a new home. + +`live-probe/` holds the runtime companion: `mock-desktop-settings-reply-modes.patch` teaches the +mock desktop server to answer `settings.get` with a refusal, `method_not_found`, a null or absent +result, absent settings, or silence, and `settings-get-reply-probe.mts` drives a real socket +through the migrated acceptance layer. Opt-in, never applied by the suite, because the patch is a +product-tree edit. + +## Known-open holes + +Two behavioural mutations are not caught by any golden. Both were confirmed by mutating product +source and re-deriving the whole suite; neither is reachable through the adapters as they stand, +so closing them needs new adapter capability rather than another scenario. Anyone migrating these +call sites should not assume the recordings will notice a change here: + +- **`use-host-repo-metadata.ts` cross-module cache write.** Deleting `setCachedRepos(...)` survives. + No adapter mounts `useNewWorkspaceRepositories`, which is the consumer that reads that cache to + open workspace creation without waiting, so the write has no observer. Closing it needs a + cache-consumer mount after the metadata fetch. +- **`use-pr-bot-author-overrides.ts` client-identity guard.** Forcing + `sourceClientRef.current !== client` to `false` survives. The adapter closes over one client + object: `reset` changes only the refresh key, `cutover` migrates the same stable logical client, + and remounting discards the old hook state. Closing it needs a same-mount client replacement. + +The original settings slice coverage maps nine host-RPC callers in +`settings-recording-coverage.json`; device-preference entries are excluded by coordinator +instruction. Later manifest additions require new scenarios and remain uncovered until +those recordings land. This runner does not certify native storage or transport skew. + +## The cleanup checkpoint + +Teardown runs on the recorded path, not only in `finally`. Each checkpoint clones the effects +array, so a rejection or state write produced by `dispose()`, the transport teardown or the final +`scheduler.flush()` used to land after the recording was built and never reached a golden — and an +unmount leak is exactly what this oracle exists to catch. + +When teardown observes anything, it becomes a checkpoint with id `cleanup`. `state` is captured +before dispose, because the operation is gone afterwards. + +Five goldens carry one today, covering six scenarios whose dropped observations were not noise: +`projectRowDetailError`, `projectMutating`, `hostLabelById`, `hostPlatform`, `workspaceAgent`, +`workspaceAgentOverridden`, `creatingKey`, `selectedAgent`, `agentOverridden` and `error`. A +scenario that stops leaking loses its checkpoint, which is a visible golden diff rather than a +silent improvement. diff --git a/mobile/src/test-support/rpc-recording/determinism-runs.ts b/mobile/src/test-support/rpc-recording/determinism-runs.ts new file mode 100644 index 00000000000..4e46d212113 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/determinism-runs.ts @@ -0,0 +1,20 @@ +/** + * How many times each scenario is recorded and compared against itself. + * + * Why it validates instead of coercing: the loop bound came straight from `Number(env ?? 2)`, so + * `0`, `-1` or a typo skipped the body entirely and every scenario reported green having recorded + * and compared nothing. A verification suite must not have a silent no-op mode. + */ +export function determinismRuns(): number { + const raw = process.env.RPC_FOUNDATION_DETERMINISM_RUNS + if (raw === undefined) { + return 2 + } + const runs = Number(raw) + if (!Number.isInteger(runs) || runs < 2) { + throw new Error( + `RPC_FOUNDATION_DETERMINISM_RUNS must be an integer >= 2 to compare a run against another; got ${JSON.stringify(raw)}` + ) + } + return runs +} diff --git a/mobile/src/test-support/rpc-recording/family-recordings.test.ts b/mobile/src/test-support/rpc-recording/family-recordings.test.ts new file mode 100644 index 00000000000..0fcac72a068 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/family-recordings.test.ts @@ -0,0 +1,160 @@ +import { resolve } from 'node:path' +import { describe, expect, it } from 'vitest' +import { readScenarios } from './scenario-input' +import { driveReplyMatrix, replyMatrixGoldenId, replyMatrixSites } from './reply-matrix' +import { + REPLY_MATRIX_NORMAL_RESULT_INVENTORY, + replyMatrixNormalResult +} from './reply-matrix-normal-result' +import { + bindCompletions, + interruptionSchedules, + lifecycleSchedules, + siblingSchedules +} from './schedule-driver' +import { hoistPreludeCheckpoints } from './prelude-checkpoints' +import { runRecording } from './run-recording' +import { pilotMountAdapters } from './pilot-mount-adapters' +import { vitestRecordingScheduler } from './vitest-recording-scheduler' +import { + compareGolden, + goldenBytes, + goldenRecording, + readGolden, + writeGolden +} from './golden-recording' +import type { Recording, RecordingScenario } from './recording-scenario' +import { determinismRuns } from './determinism-runs' + +const root = resolve(import.meta.dirname, '../../../..') +const input = readScenarios( + process.env.RPC_FOUNDATION_SCENARIOS ?? + resolve(root, 'mobile/rpc-foundation/pilot-scenarios.json') +) +const directory = + process.env.RPC_FOUNDATION_GOLDENS ?? resolve(root, 'mobile/rpc-foundation/goldens') +async function certify(id: string, scenarios: RecordingScenario[]) { + let first = '' + for (let run = 0; run < determinismRuns(); run++) { + const checkpoints: Recording['checkpoints'] = [] + for (const scenario of scenarios) { + const { adapters } = pilotMountAdapters(root) + const recording = await runRecording( + scenario, + adapters[scenario.operation], + vitestRecordingScheduler() + ) + for (const checkpoint of recording.checkpoints) { + checkpoints.push({ ...checkpoint, id: `${scenario.id}:${checkpoint.id}` }) + } + } + const golden = goldenRecording(root, input.baseline, scenarios[0], { + scenario: id, + checkpoints + }) + const bytes = goldenBytes(golden) + if (run) { + expect(bytes).toBe(first) + } + first = bytes + if (process.env.RPC_FOUNDATION_MODE === '--record') { + await writeGolden(directory, golden, '--record') + } else { + compareGolden(readGolden(directory, id), golden) + } + } +} + +describe('family reply partitions and owned schedules', () => { + const families = new Map() + for (const scenario of input.scenarios) { + families.set(scenario.family, [...(families.get(scenario.family) ?? []), scenario]) + } + const goldenIds = new Set() + // Filled only when a site actually generates a test, so the census below is independent of + // replyMatrixSites throwing on an empty list: the mechanism this replaced skipped families. + const matrixed = new Set() + const liveSites = new Set() + it('matrices every family in the manifest', () => { + expect([...matrixed]).toEqual([...families.keys()]) + }) + // The inventory is only consulted for a live site, so a stale entry would retire silently. + it('lists only live matrix sites in the normal-result inventory', () => { + const stale = REPLY_MATRIX_NORMAL_RESULT_INVENTORY.filter( + (entry) => !liveSites.has(`${entry.family}\0${entry.request}`) + ).map((entry) => `${entry.family} ${entry.request}`) + expect(stale).toEqual([]) + }) + for (const [family, scenarios] of families) { + const base = scenarios[0]! + for (const request of replyMatrixSites(base)) { + const id = replyMatrixGoldenId(family, request) + if (goldenIds.has(id)) { + throw new Error(`Two matrix sites share a golden: ${id}`) + } + goldenIds.add(id) + matrixed.add(family) + liveSites.add(`${family}\0${request}`) + it(`${family}: reply partitions at ${request}`, async () => { + await certify( + id, + driveReplyMatrix(base, request, replyMatrixNormalResult(family, scenarios, request)) + ) + }, 30_000) + } + } + for (const id of [ + 'b3', + 'settings-new-tab-ssh', + 'settings-home-providers-fulfilled', + 'settings-workspace-context-fulfilled', + 'settings-resume-metadata-fulfilled', + 'settings-task-hydration-fulfilled', + 'settings-repo-metadata-fulfilled' + ]) { + const base = input.scenarios.find((scenario) => scenario.id === id)! + const replies = base.steps.filter((step) => 'complete' in step) + // Complete prerequisites before permuting the sibling barrier. + const first = replies.find((step) => + step.complete.startsWith(id === 'b3' ? 'linear.getIssue' : 'settings.get') + )! + const second = replies[replies.indexOf(first) + 1] + if (!second) { + continue + } + it(`${id}: completion orders and correlated faults`, async () => { + await certify(`schedules-${id}`, siblingSchedules(base, first, second)) + }) + } + for (const id of ['inventory-lifecycle', 'settings-bot-overrides-fulfilled']) { + const base = input.scenarios.find((scenario) => scenario.id === id)! + it(`${id}: timeout, disconnect and stable-client cutover`, async () => { + await certify(`interruptions-${id}`, interruptionSchedules(base)) + }) + } + for (const id of [ + 'inventory-lifecycle', + 'b3', + 'settings-bot-overrides-fulfilled', + 'settings-workspace-context-fulfilled', + 'settings-task-hydration-fulfilled' + ]) { + const base = input.scenarios.find((scenario) => scenario.id === id)! + const actions = id.includes('hydration') + ? (['unmount'] as const) + : id.includes('context') + ? (['unmount', 'blur'] as const) + : (['reset', 'unmount', 'blur'] as const) + it(`${id}: lifecycle boundaries`, async () => { + await certify( + `lifecycle-${id}`, + hoistPreludeCheckpoints( + { ...base, steps: bindCompletions(base.steps) }, + actions + .flatMap((action) => lifecycleSchedules(base, action)) + .filter(({ scenario }) => !id.includes('hydration') || !scenario.id.endsWith('-1')) + ) + ) + }) + } +}) diff --git a/mobile/src/test-support/rpc-recording/golden-recording.ts b/mobile/src/test-support/rpc-recording/golden-recording.ts new file mode 100644 index 00000000000..e7ae72c60b1 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/golden-recording.ts @@ -0,0 +1,194 @@ +import { format } from 'oxfmt' +import { createHash } from 'node:crypto' +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs' +import { join } from 'node:path' +import { + canonicalJson, + internRecording, + OBSERVATION_FIELDS, + resolveRecording, + type InternedRecording, + type ValuePool +} from './golden-value-pool' +import { recorderSha256 } from './recorder-digest' +import type { Recording, RecordingScenario } from './recording-scenario' +import type { RecordedValue } from './recording-values' + +export const RUNNER_VERSION = 1 +// 2 stamps every settlement with startedAt/settledAt on the pinned virtual clock. +export const PROJECTION_VERSION = 2 +// 3 interns each entry of a list or map field, not the whole field; an older file is not comparable. +export const GOLDEN_FORMAT_VERSION = 3 +export type GoldenRecording = { + operation: string + family: string + namedDeltas: string[] + runnerVersion: number + baseline: string + lockfileSha256: string + recorderSha256: string + platform: string + scenarioVersion: number + projectionVersion: number + goldenFormatVersion: number + recording: Recording +} +type GoldenFile = Omit & { + values: ValuePool + recording: InternedRecording +} +export function goldenRecording( + root: string, + baseline: string, + scenario: RecordingScenario, + recording: Recording +): GoldenRecording { + return { + operation: scenario.operation, + family: scenario.family, + namedDeltas: scenario.namedDeltas ?? [], + runnerVersion: RUNNER_VERSION, + baseline, + lockfileSha256: createHash('sha256') + .update(readFileSync(join(root, 'mobile/pnpm-lock.yaml'))) + .digest('hex'), + recorderSha256: recorderSha256(root), + platform: process.platform, + scenarioVersion: scenario.version, + projectionVersion: PROJECTION_VERSION, + goldenFormatVersion: GOLDEN_FORMAT_VERSION, + recording + } +} +export function goldenBytes(golden: GoldenRecording): string { + const { recording: _value, ...header } = golden + const interned = internRecording(golden.recording) + return `${JSON.stringify({ ...header, values: interned.values, recording: interned.recording }, null, 2)}\n` +} +export function readGolden(directory: string, id: string): GoldenRecording { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the file is validated against GoldenFile on the next lines. + const file = JSON.parse(readFileSync(goldenPath(directory, id), 'utf8')) as Partial + if (file.goldenFormatVersion !== GOLDEN_FORMAT_VERSION) { + throw new Error( + `Golden ${id} has format version ${JSON.stringify(file.goldenFormatVersion)}; this reader requires ${GOLDEN_FORMAT_VERSION}. Re-record with --record.` + ) + } + if (!file.values || !file.recording) { + throw new Error(`Golden ${id} is missing its value pool or recording`) + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: goldenFormatVersion was just checked, so the pool is present. + const { values: _pool, ...header } = file as GoldenFile + return { ...header, recording: resolveRecording(file.values, file.recording) } +} +export async function writeGolden( + directory: string, + golden: GoldenRecording, + mode: string +): Promise { + if (mode !== '--record' || process.env.RPC_FOUNDATION_RECORD !== '1') { + throw new Error('Golden writes require --record and RPC_FOUNDATION_RECORD=1') + } + mkdirSync(directory, { recursive: true }) + const path = goldenPath(directory, golden.recording.scenario) + const result = await format(path, goldenBytes(golden), { printWidth: 100, trailingComma: 'none' }) + if (result.errors.length) { + throw new Error('Cannot format golden') + } + writeFileSync(path, result.code) +} +function goldenPath(directory: string, id: string): string { + if (!/^[a-z0-9][a-z0-9._-]*$/.test(id)) { + throw new Error(`Unsafe scenario id: ${id}`) + } + return join(directory, `${id}.json`) +} +export function compareGolden(expected: GoldenRecording, actual: GoldenRecording): void { + const scenario = actual.recording.scenario + // Platform and lockfile are provenance: a dependency that changes behaviour changes the trace + // below, and one that does not must not fail the compare on every unrelated bump. + const pinned = { ...expected, platform: actual.platform, lockfileSha256: actual.lockfileSha256 } + const { recording: _expectedRecording, ...expectedHeader } = pinned + const { recording: _actualRecording, ...actualHeader } = actual + for (const [key, value] of Object.entries(expectedHeader)) { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: header keys are compared as data, not consumed as fields. + const found = (actualHeader as Record)[key] + if (JSON.stringify(found) !== JSON.stringify(value)) { + throw new Error( + `Recording differs: ${scenario} header ${key}\n expected ${JSON.stringify(value)}\n actual ${JSON.stringify(found)}` + ) + } + } + const expectedIds = pinned.recording.checkpoints.map((checkpoint) => checkpoint.id) + const actualIds = actual.recording.checkpoints.map((checkpoint) => checkpoint.id) + if (JSON.stringify(expectedIds) !== JSON.stringify(actualIds)) { + const index = expectedIds.findIndex((id, at) => id !== actualIds[at]) + throw new Error( + `Recording differs: ${scenario} checkpoint list (${expectedIds.length} expected, ${actualIds.length} actual)\n first divergence at index ${index}: expected ${JSON.stringify(expectedIds[index])}, actual ${JSON.stringify(actualIds[index])}` + ) + } + for (const [index, checkpoint] of pinned.recording.checkpoints.entries()) { + const found = actual.recording.checkpoints[index]! + for (const field of OBSERVATION_FIELDS) { + if ( + canonicalJson(checkpoint.observation[field]) === canonicalJson(found.observation[field]) + ) { + continue + } + const path = firstDifference(checkpoint.observation[field], found.observation[field]) + throw new Error( + `Recording differs: ${scenario} checkpoint ${checkpoint.id} field ${field}${path.path}\n expected ${excerpt(path.expected)}\n actual ${excerpt(path.actual)}` + ) + } + } + if (goldenBytes(pinned) !== goldenBytes(actual)) { + throw new Error(`Recording differs: ${scenario} (encoding)`) + } +} +function firstDifference( + expected: RecordedValue, + actual: RecordedValue, + path = '' +): { path: string; expected: RecordedValue; actual: RecordedValue } { + const here = { path, expected, actual } + if ( + expected === null || + actual === null || + typeof expected !== 'object' || + typeof actual !== 'object' || + Array.isArray(expected) !== Array.isArray(actual) + ) { + return here + } + if (Array.isArray(expected) && Array.isArray(actual)) { + const index = expected.findIndex( + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: both sides are recorded observations, so every member is a RecordedValue. + (entry, at) => canonicalJson(entry) !== canonicalJson(actual[at] as RecordedValue) + ) + return index === -1 || index >= actual.length + ? here + : firstDifference( + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: both sides are recorded observations, so every member is a RecordedValue. + expected[index] as RecordedValue, + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: both sides are recorded observations, so every member is a RecordedValue. + actual[index] as RecordedValue, + `${path}[${index}]` + ) + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the array branch above already rejected a non-object pair. + const left = expected as Record + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the array branch above already rejected a non-object pair. + const right = actual as Record + const key = [...new Set([...Object.keys(left), ...Object.keys(right)])].sort().find( + (name) => + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: both sides are recorded observations, so every member is a RecordedValue. + canonicalJson(left[name] as RecordedValue) !== canonicalJson(right[name] as RecordedValue) + ) + return key === undefined || !(key in left) || !(key in right) + ? here + : // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: both sides are recorded observations, so every member is a RecordedValue. + firstDifference(left[key] as RecordedValue, right[key] as RecordedValue, `${path}.${key}`) +} +function excerpt(value: RecordedValue): string { + const json = JSON.stringify(value) + return json === undefined ? 'absent' : json.length > 600 ? `${json.slice(0, 600)}…` : json +} diff --git a/mobile/src/test-support/rpc-recording/golden-value-pool.ts b/mobile/src/test-support/rpc-recording/golden-value-pool.ts new file mode 100644 index 00000000000..2e91dbb55c7 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/golden-value-pool.ts @@ -0,0 +1,177 @@ +import { createHash } from 'node:crypto' +import type { Observation, Recording } from './recording-scenario' +import type { RecordedValue } from './recording-values' + +type FieldShape = 'list' | 'map' | 'whole' + +/** + * How each observation field is interned. `sender`, `payloads` and `effects` are append-only + * histories and `settlements` is keyed by action id, so every checkpoint after the first re-states + * its predecessor's entries: pooling the whole field stored that shared prefix once per checkpoint, + * and once per reply partition in a matrix golden. Interning per entry stores it once per file. + * + * Declared rather than sniffed from the value, so an empty list cannot be encoded as a map and a + * projection that changes a field's container fails loudly instead of silently switching encodings. + * `Record` makes a new observation field declare how it interns. + */ +const FIELD_SHAPES = { + sender: 'list', + payloads: 'list', + settlements: 'map', + state: 'whole', + effects: 'list' +} as const satisfies Record + +export const OBSERVATION_FIELDS = [ + 'sender', + 'payloads', + 'settlements', + 'state', + 'effects' +] as const satisfies readonly (keyof typeof FIELD_SHAPES)[] + +export type ValuePool = Record +type InternedField = Shape extends 'list' + ? string[] + : Shape extends 'map' + ? Record + : string +export type InternedObservation = { + [Field in keyof typeof FIELD_SHAPES]: InternedField<(typeof FIELD_SHAPES)[Field]> +} +export type InternedRecording = { + scenario: string + checkpoints: { id: string; observation: InternedObservation }[] +} + +export function canonicalJson(value: RecordedValue): string { + if (value === null || typeof value !== 'object') { + return JSON.stringify(value) + } + if (Array.isArray(value)) { + return `[${value.map(canonicalJson).join(',')}]` + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: canonicalJson only reaches here for a plain object observation. + const record = value as Record + return `{${Object.keys(record) + .sort() + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a recorded object holds recorded values. + .map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key] as RecordedValue)}`) + .join(',')}}` +} + +export function valueHash(value: RecordedValue): string { + return createHash('sha256').update(canonicalJson(value)).digest('hex').slice(0, 12) +} + +function listEntries(at: string, value: RecordedValue): RecordedValue[] { + if (!Array.isArray(value)) { + throw new Error(`Observation field ${at} is declared a list but recorded ${typeof value}`) + } + return value +} + +function mapEntries(at: string, value: RecordedValue): [string, RecordedValue][] { + if (value === null || typeof value !== 'object' || Array.isArray(value)) { + throw new Error(`Observation field ${at} is declared a map but recorded ${typeof value}`) + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the guard above rejected null and arrays, leaving a recorded object. + return Object.entries(value as Record) +} + +export function internRecording(recording: Recording): { + values: ValuePool + recording: InternedRecording +} { + const pool: ValuePool = {} + const canonical = new Map() + const intern = (entry: RecordedValue, at: string): string => { + const hash = valueHash(entry) + const json = canonicalJson(entry) + const seen = canonical.get(hash) + if (seen !== undefined && seen !== json) { + throw new Error(`Golden value hash collision at ${hash} (${at})`) + } + canonical.set(hash, json) + pool[hash] = entry + return hash + } + const checkpoints = recording.checkpoints.map((checkpoint) => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: every declared field is assigned below before the value is read. + const observation = {} as Record + for (const field of OBSERVATION_FIELDS) { + const value = checkpoint.observation[field] + const at = `${checkpoint.id}.${field}` + observation[field] = + FIELD_SHAPES[field] === 'list' + ? listEntries(at, value).map((entry, index) => intern(entry, `${at}[${index}]`)) + : FIELD_SHAPES[field] === 'map' + ? Object.fromEntries( + mapEntries(at, value).map(([key, entry]) => [key, intern(entry, `${at}.${key}`)]) + ) + : intern(value, at) + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: each field was just encoded to the shape its declaration names. + return { id: checkpoint.id, observation: observation as InternedObservation } + }) + // Hash-ordered so a value's position in the pool does not move when checkpoints are reordered. + const values = Object.fromEntries( + Object.keys(pool) + .sort() + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: pool entries are the recorded values that were interned into it. + .map((hash) => [hash, pool[hash] as RecordedValue]) + ) + return { values, recording: { scenario: recording.scenario, checkpoints } } +} + +export function resolveRecording(values: ValuePool, recording: InternedRecording): Recording { + // Content addressing is what keeps an entry shared between checkpoints honest: editing a pooled + // value without moving every reference to it is caught here rather than resolving silently. + for (const [hash, value] of Object.entries(values)) { + if (valueHash(value) !== hash) { + throw new Error(`Golden value ${hash} does not hash to its pool key`) + } + } + const referenced = new Set() + const resolve = (hash: unknown, at: string): RecordedValue => { + if (typeof hash !== 'string' || !Object.hasOwn(values, hash)) { + throw new Error(`Golden value ${JSON.stringify(hash)} is missing from the pool (${at})`) + } + referenced.add(hash) + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the hash was resolved against the same pool that interned it. + return values[hash] as RecordedValue + } + const resolved = { + scenario: recording.scenario, + checkpoints: recording.checkpoints.map((checkpoint) => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: every declared field is assigned below before the value is read. + const observation = {} as Observation + for (const field of OBSERVATION_FIELDS) { + const interned: unknown = checkpoint.observation[field] + const at = `${checkpoint.id}.${field}` + if (FIELD_SHAPES[field] === 'list') { + if (!Array.isArray(interned)) { + throw new Error(`Golden field ${at} is not a list of pool hashes`) + } + observation[field] = interned.map((hash, index) => resolve(hash, `${at}[${index}]`)) + } else if (FIELD_SHAPES[field] === 'map') { + if (interned === null || typeof interned !== 'object' || Array.isArray(interned)) { + throw new Error(`Golden field ${at} is not a map of pool hashes`) + } + observation[field] = Object.fromEntries( + Object.entries(interned).map(([key, hash]) => [key, resolve(hash, `${at}.${key}`)]) + ) + } else { + observation[field] = resolve(interned, at) + } + } + return { id: checkpoint.id, observation } + }) + } + // An entry no checkpoint reads is content in the file that nothing compares. + const orphans = Object.keys(values).filter((hash) => !referenced.has(hash)) + if (orphans.length) { + throw new Error(`Golden pool holds unreferenced values: ${orphans.join(', ')}`) + } + return resolved +} diff --git a/mobile/src/test-support/rpc-recording/hook-mount.ts b/mobile/src/test-support/rpc-recording/hook-mount.ts new file mode 100644 index 00000000000..97e646b81d0 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/hook-mount.ts @@ -0,0 +1,36 @@ +import { createElement } from 'react' +import { act, create, type ReactTestRenderer } from 'react-test-renderer' + +export function hookMount(render: () => void) { + let renderer: ReactTestRenderer | undefined + function Harness() { + render() + return null + } + return { + mount() { + act(() => { + renderer = create(createElement(Harness)) + }) + }, + update() { + act(() => { + renderer?.update(createElement(Harness)) + }) + }, + unmount() { + act(() => { + renderer?.unmount() + renderer = undefined + }) + } + } +} + +export function performHookAction(action: () => T): T { + let result!: T + act(() => { + result = action() + }) + return result +} diff --git a/mobile/src/test-support/rpc-recording/hosted-review-mount-adapters.ts b/mobile/src/test-support/rpc-recording/hosted-review-mount-adapters.ts new file mode 100644 index 00000000000..df836e7bc13 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/hosted-review-mount-adapters.ts @@ -0,0 +1,155 @@ +import type { MountAdapter } from './recording-scenario' +import { operationModuleLoader } from './operation-module-loader' + +const WORKTREE = 'repo42::/p' + +const STATUS_WITH_STAGED_CHANGE = { + branch: 'feature', + head: 'abc1234', + entries: [{ path: 'src/app.ts', status: 'modified', area: 'staged' }], + upstreamStatus: { ahead: 1, behind: 0, hasUpstream: true } +} + +/** Hosted-review create: the mutation chain (status, stage, commit, push, create, link). */ +export function hostedReviewMountAdapters( + modules: ReturnType +): Record { + return { + 'source-control.review-git-preparation': ({ client }) => { + const preparation = modules.load< + typeof import('../../source-control/mobile-hosted-review-git-preparation') + >('mobile/src/source-control/mobile-hosted-review-git-preparation.ts') + let status: unknown = 'unread' + let committed: unknown = 'uncommitted' + return { + action(name) { + if (name === 'commit') { + return preparation + .commitMobileHostedReviewStagedChanges(client, WORKTREE, 'recorded message') + .then((value) => { + committed = value + return value + }) + } + return preparation.readMobileHostedReviewGitStatus(client, WORKTREE).then((value) => { + status = value + return value + }) + }, + state: () => ({ status, committed }), + dispose: () => {} + } + }, + 'source-control.remote-prerequisite': (context) => { + const apply = modules.load< + typeof import('../../source-control/mobile-hosted-review-remote-prerequisite') + >( + 'mobile/src/source-control/mobile-hosted-review-remote-prerequisite.ts' + ).applyMobileHostedReviewRemotePrerequisite + let outcome: unknown = 'unapplied' + return { + action(name, args) { + const patchEquivalent = args.patchEquivalent === true + return apply( + context.client, + WORKTREE, + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the scenario supplies the blocked reason as JSON, not as a typed prefill. + { blockedReason: args.blockedReason } as Parameters[2], + { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the prerequisite reads only upstreamStatus off the status. + status: { + entries: [], + upstreamStatus: { behindCommitsArePatchEquivalent: patchEquivalent } + } as unknown as Parameters[3]['status'], + onProgress: (progress) => context.effect('progress', progress) + } + ).then((value) => { + outcome = value + return value + }) + }, + state: () => ({ outcome }), + dispose: () => {} + } + }, + 'source-control.hosted-review-eligibility': ({ client }) => { + const service = modules.load< + typeof import('../../source-control/mobile-hosted-review-service') + >('mobile/src/source-control/mobile-hosted-review-service.ts') + let eligibility: unknown = 'unfetched' + let prefill: unknown = 'unresolved' + return { + action(name) { + if (name === 'prefill') { + return service + .resolveMobileHostedReviewPrefill(client, WORKTREE, { + branch: 'feature', + title: 'Recorded title' + }) + .then((value) => { + prefill = value + return value + }) + } + return service + .fetchMobileHostedReviewEligibility(client, WORKTREE, { branch: 'feature' }) + .then((value) => { + eligibility = value + return value + }) + }, + state: () => ({ eligibility, prefill }), + dispose: () => {} + } + }, + 'source-control.hosted-review-create': ({ client }) => { + const create = modules.load< + typeof import('../../source-control/mobile-hosted-review-service') + >('mobile/src/source-control/mobile-hosted-review-service.ts').createMobileHostedReview + let outcome: unknown = 'uncreated' + return { + action: (_name, args) => + create(client, WORKTREE, { + provider: 'github', + base: 'main', + head: 'feature', + title: 'Recorded title', + body: 'Recorded body', + draft: false, + pushBeforeCreate: args.pushBeforeCreate === true + }).then((value) => { + outcome = value + return value + }), + state: () => ({ outcome }), + dispose: () => {} + } + }, + 'source-control.create-intent': (context) => { + const run = modules.load< + typeof import('../../source-control/mobile-hosted-review-create-intent-runner') + >( + 'mobile/src/source-control/mobile-hosted-review-create-intent-runner.ts' + ).runMobileHostedReviewCreateIntent + let outcome: unknown = 'unrun' + return { + action: (_name, args) => + run(context.client, WORKTREE, { + branch: 'feature', + title: 'Recorded title', + ...(args.commitMessage === undefined + ? {} + : { commitMessage: String(args.commitMessage) }), + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the seed status is scenario data, not a validated host payload. + status: STATUS_WITH_STAGED_CHANGE as unknown as Parameters[2]['status'], + onProgress: (progress) => context.effect('progress', progress) + }).then((value) => { + outcome = value + return value + }), + state: () => ({ outcome }), + dispose: () => {} + } + } + } +} diff --git a/mobile/src/test-support/rpc-recording/observable-model.ts b/mobile/src/test-support/rpc-recording/observable-model.ts new file mode 100644 index 00000000000..c3e0941b3fe --- /dev/null +++ b/mobile/src/test-support/rpc-recording/observable-model.ts @@ -0,0 +1,45 @@ +import type { MountContext } from './recording-scenario' + +export function projectObservable(value: unknown): unknown { + if (value instanceof Set) { + return [...value].map(projectObservable) + } + if (value instanceof Map) { + return [...value].map(([key, entry]) => [key, projectObservable(entry)]) + } + if (Array.isArray(value)) { + return value.map(projectObservable) + } + if (value && typeof value === 'object') { + return Object.fromEntries( + Object.entries(value).map(([key, entry]) => [ + key, + key === 'client' ? 'logical-client' : projectObservable(entry) + ]) + ) + } + return value +} + +export function observableModel(context: MountContext, initial: Record) { + const values = { ...initial } + const callbacks = new Map void>() + return new Proxy(values, { + get(target, key: string) { + if (key in target) { + return target[key] + } + if (!key.startsWith('set') || key.length < 4) { + throw new Error(`Missing model fixture: ${key}`) + } + if (!callbacks.has(key)) { + const field = key[3].toLowerCase() + key.slice(4) + callbacks.set(key, (value) => { + target[field] = typeof value === 'function' ? value(target[field]) : value + context.effect(field, projectObservable(target[field])) + }) + } + return callbacks.get(key) + } + }) +} diff --git a/mobile/src/test-support/rpc-recording/operation-module-loader.ts b/mobile/src/test-support/rpc-recording/operation-module-loader.ts new file mode 100644 index 00000000000..03c31a4f707 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/operation-module-loader.ts @@ -0,0 +1,131 @@ +import { compileFunction } from 'node:vm' +import { existsSync, readFileSync } from 'node:fs' +import { dirname, resolve } from 'node:path' +import * as React from 'react' +import ts from 'typescript' +import { OPERATION_EXPOSURES, OPERATION_MUTATIONS, type Mutation } from './operation-mutations' + +export type { Mutation } +export type OperationModule = Record unknown> + +// Only mounting boundaries are substituted; every operation and projection is loaded from source. +export function operationModuleLoader(root: string, mutation?: Mutation) { + const cache = new Map() + let mutationCount = 0 + function pathFor(base: string): string { + const file = ['', '.ts', '.tsx', '/index.ts'] + .map((suffix) => base + suffix) + .find((path) => existsSync(path) && /\.tsx?$/.test(path)) + if (!file) { + throw new Error(`Module not found: ${base}`) + } + return file + } + function imported(base: string, name: string): unknown { + if (name === 'react') { + return React + } + if (!name.startsWith('.')) { + return new Proxy( + {}, + { + get: () => { + throw new Error(`Unspecified native mounting dependency: ${name}`) + } + } + ) + } + return new Proxy( + {}, + { get: (_target, key) => load(pathFor(resolve(dirname(base), name)))[String(key)] } + ) + } + function barrel(file: string, source: string): OperationModule { + const parsed = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true) + return new Proxy( + {}, + { + get: (_target, key) => { + for (const statement of parsed.statements) { + if ( + !ts.isExportDeclaration(statement) || + !statement.moduleSpecifier || + !ts.isStringLiteral(statement.moduleSpecifier) || + statement.isTypeOnly + ) { + continue + } + const name = statement.moduleSpecifier.text + if (statement.exportClause && ts.isNamedExports(statement.exportClause)) { + const binding = statement.exportClause.elements.find( + (item) => item.name.text === key && !item.isTypeOnly + ) + if (binding) { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the barrel target is a module this loader evaluated. + return (imported(file, name) as OperationModule)[ + binding.propertyName?.text ?? String(key) + ] + } + } else if (!statement.exportClause) { + const target = pathFor(resolve(dirname(file), name)) + const text = readFileSync(target, 'utf8') + if ( + new RegExp(`export (?:async )?(?:function|const|class) ${String(key)}\\b`).test( + text + ) + ) { + return load(target)[String(key)] + } + } + } + throw new Error(`Unmapped barrel export: ${String(key)} in ${file}`) + } + } + ) + } + function load(file: string): OperationModule { + const cached = cache.get(file) + if (cached) { + return cached + } + let source = readFileSync(file, 'utf8') + if (/mobile-tasks-(dependencies|legacy-foundation)\.tsx?$/.test(file)) { + const result = barrel(file, source) + cache.set(file, result) + return result + } + const spec = mutation ? OPERATION_MUTATIONS[mutation] : undefined + if (spec && file.endsWith(spec.file)) { + // Counting occurrences, not replace calls: `replace` would silently take only the first. + const occurrences = source.split(spec.before).length - 1 + if (occurrences !== 1) { + throw new Error(`Mutant anchor matched ${occurrences} sites, expected 1: ${mutation}`) + } + source = source.replace(spec.before, spec.after) + mutationCount++ + } + const exports: OperationModule = {} + cache.set(file, exports) + const output = ts.transpileModule(source, { + compilerOptions: { + module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.ES2022, + jsx: ts.JsxEmit.React + } + }).outputText + const exposure = OPERATION_EXPOSURES.find(([suffix]) => file.endsWith(suffix))?.[1] ?? '' + const evaluate = compileFunction(output + exposure, ['require', 'exports'], { filename: file }) + evaluate((name: string) => imported(file, name), exports) + return exports + } + return { + load: (path: string): T => + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a VM-evaluated module has no static type; the caller names the shape it mounts. + load(pathFor(resolve(root, path))) as unknown as T, + assertMutationApplied: () => { + if (mutation && mutationCount !== 1) { + throw new Error(`Expected one mutation, applied ${mutationCount}`) + } + } + } +} diff --git a/mobile/src/test-support/rpc-recording/operation-mutations.ts b/mobile/src/test-support/rpc-recording/operation-mutations.ts new file mode 100644 index 00000000000..cd760f0004f --- /dev/null +++ b/mobile/src/test-support/rpc-recording/operation-mutations.ts @@ -0,0 +1,143 @@ +/** + * One in-memory source edit per adapter family. Each anchor names a real expression in a mounted + * operation; the recording that owns the family must change visible state when it is applied, which + * is what proves that family's `state()` projection observes the operation's actual output. + */ +export type OperationMutation = { + /** Suffix of the mounted source file the anchor belongs to. */ + file: string + before: string + after: string +} + +export const OPERATION_MUTATIONS = { + // Loses the generation comparison, so a stale workspace response poisons the search cache. + race: { + file: 'use-mobile-native-chat-file-search.ts', + before: '!response.ok || generationRef.current !== generation', + after: '!response.ok' + }, + // Accepts a null result envelope instead of rejecting it. The guard is repeated for three + // mutations in this file; the anchor carries the message so only the recorded one is edited. + acceptance: { + file: 'use-mobile-tasks-project-metadata-actions.tsx', + before: `if (result.ok === false) { + throw new Error(result.error?.message ?? 'Failed to update GitHub item')`, + after: `if (result?.ok === false) { + throw new Error(result.error?.message ?? 'Failed to update GitHub item')` + }, + // Rejects the barrier early, so the sibling comment request is abandoned out of order. + order: { + file: 'use-mobile-tasks-item-detail-loading.tsx', + before: `{ timeoutMs: 30_000 } + ), + client.sendRequest( + 'linear.issueComments'`, + after: `{ timeoutMs: 30_000 } + ).then((response) => { if (!isSuccess(response)) throw new Error(response.error.message); return response }), + client.sendRequest( + 'linear.issueComments'` + }, + // Reads the overrides one level above the settings envelope. + 'bot-overrides-envelope': { + file: 'settings-read-operations.ts', + before: "settings == null ? undefined : Reflect.get(Object(settings), 'prBotAuthorOverrides')", + after: "raw == null ? undefined : Reflect.get(Object(raw), 'prBotAuthorOverrides')" + }, + // Publishes the settings envelope instead of the accepted operation value. + 'workspace-context-envelope': { + file: 'use-new-workspace-runtime-context.ts', + before: + '(settingsResult.value as NewWorktreeRuntimeSettings & { visibleTaskProviders?: unknown })', + after: + '(settingsRes.value.result as NewWorktreeRuntimeSettings & { visibleTaskProviders?: unknown })' + }, + // Treats any successful linear.status reply as a connected Linear account. + 'home-providers-linear': { + file: 'mobile-home-host-requests.ts', + before: 'linearConnected: linear?.connected === true', + after: 'linearConnected: linear !== null' + }, + // Reads the host platform from the wrong field of the host.platform result. + 'repo-metadata-platform': { + file: 'use-host-repo-metadata.ts', + before: 'const platform = (result as { platform?: unknown } | null)?.platform', + after: 'const platform = (result as { hostPlatform?: unknown } | null)?.hostPlatform' + }, + // Hydrates the runtime task settings from the envelope rather than the accepted value. + 'task-hydration-envelope': { + file: 'use-mobile-tasks-runtime-hydration.tsx', + before: '((settingsResult.value ?? {}) as RuntimeTaskSettings)', + after: '((settingsResponse.result ?? {}) as RuntimeTaskSettings)' + }, + // Applies the preset only after the write settles, dropping the optimistic update. + 'task-preferences-optimistic': { + file: 'use-mobile-tasks-client-settings-actions.tsx', + before: ` setDefaultGitHubPreset(preset) + if (!client || !taskUiReady) { + return + } + void client.sendRequest('settings.update', { defaultTaskViewPreset: preset }).catch(() => {`, + after: ` if (!client || !taskUiReady) { + setDefaultGitHubPreset(preset) + return + } + void client + .sendRequest('settings.update', { defaultTaskViewPreset: preset }) + .then(() => setDefaultGitHubPreset(preset)) + .catch(() => {` + }, + // Publishes the settings envelope as the refreshed workspace runtime settings. + 'workspace-submit-envelope': { + file: 'use-new-workspace-create-submit.ts', + before: 'latestRuntimeSettings = settings.value as NewWorktreeRuntimeSettings', + after: 'latestRuntimeSettings = settingsReply.result as NewWorktreeRuntimeSettings' + }, + // Reads settings eagerly, so a null result throws before the sibling's refusal is checked. + 'new-tab-deferred-settings-read': { + file: 'settings-read-operations.ts', + before: ' value: () => settingsMember(raw),', + after: ' value: ((settings) => () => settings)(settingsMember(raw)),' + }, + // Checks the sibling's refusal before the operation's own, so a correlated refusal reports the + // sibling. Invisible to every scenario whose sibling succeeds or rejects at the transport. + 'new-tab-refusal-order': { + file: 'mobile-new-tab-agent-loader.ts', + before: ` const readSettings = newTabSettingsRead.interpret(settingsResponse) + if (!detectedResponse.ok) { + throw new Error((detectedResponse as RpcFailure).error.message) + }`, + after: ` if (!detectedResponse.ok) { + throw new Error((detectedResponse as RpcFailure).error.message) + } + const readSettings = newTabSettingsRead.interpret(settingsResponse)` + }, + // Publishes an unaccepted read, blanking settings a refusal should have left alone. Invisible + // to any scenario that refuses before the screen ever held data. + 'workspace-context-refusal-blanks': { + file: 'use-new-workspace-runtime-context.ts', + before: ` if (settingsValue) { + setRuntimeSettings(settingsValue) + }`, + after: ' setRuntimeSettings(settingsValue)' + }, + // Publishes the settings envelope as the refreshed task runtime settings. + 'task-workspace-envelope': { + file: 'use-mobile-tasks-workspace-create-actions.tsx', + before: 'latestRuntimeTaskSettings = (settingsResult.value ?? {}) as RuntimeTaskSettings', + after: 'latestRuntimeTaskSettings = (settingsReply.result ?? {}) as RuntimeTaskSettings' + } +} as const satisfies Record + +export type Mutation = keyof typeof OPERATION_MUTATIONS + +/** + * Appended to a mounted module after transpile, keyed by file suffix. An adapter drives a real + * operation the product keeps module-private; exposing it here beats editing the pinned source. + */ +export const OPERATION_EXPOSURES: readonly (readonly [string, string])[] = [ + [ + 'MobileAgentSessionHistoryPanel.tsx', + '\nexports.loadMobileResumeMetadata = loadMobileResumeMetadata;' + ] +] diff --git a/mobile/src/test-support/rpc-recording/pilot-mount-adapters.ts b/mobile/src/test-support/rpc-recording/pilot-mount-adapters.ts new file mode 100644 index 00000000000..a1dd2b61174 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/pilot-mount-adapters.ts @@ -0,0 +1,231 @@ +import { observableModel } from './observable-model' +import { hostedReviewMountAdapters } from './hosted-review-mount-adapters' +import { settingsMountAdapters } from './settings-mount-adapters' +import { sourceControlMountAdapters } from './source-control-mount-adapters' +import { workspaceSettingsMounts } from './workspace-settings-mounts' +import type { MountAdapter } from './recording-scenario' +import { hookMount, performHookAction } from './hook-mount' +import { operationModuleLoader, type Mutation } from './operation-module-loader' + +export function pilotMountAdapters( + root: string, + options: { reference?: boolean; mutation?: Mutation } = {} +) { + const modules = operationModuleLoader(root, options.mutation) + const adapters: Record = { + ...settingsMountAdapters(modules), + ...workspaceSettingsMounts(modules), + ...sourceControlMountAdapters(modules), + ...hostedReviewMountAdapters(modules), + 'workspace.file-inventory': ({ client }) => { + const useSearch = modules.load< + typeof import('../../session/use-mobile-native-chat-file-search') + >('mobile/src/session/use-mobile-native-chat-file-search.ts').useMobileNativeChatFileSearch + const operations = options.reference + ? modules + .load('mobile/src/session/native-host-session-native-chat-operations.ts') + .nativeHostSessionNativeChatOperations(client) + : undefined + let workspace = 'A' + let state: ReturnType + const hook = hookMount(() => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the recorder supplies only the members the hook reads. + state = useSearch({ client, operations, worktreeId: workspace } as Parameters< + typeof useSearch + >[0]) + }) + return { + action(name, args) { + if (name === 'mount' || name === 'remount') { + return hook.mount() + } + if (name === 'unmount') { + return hook.unmount() + } + if (name === 'select') { + workspace = String(args.workspace) + return hook.update() + } + if (name === 'reset') { + const previous = workspace + workspace = `${workspace}-reset` + hook.update() + workspace = previous + return hook.update() + } + if (name === 'query') { + return performHookAction(() => state.loadNativeChatFiles(String(args.query))) + } + if (name === 'blur') { + return + } + throw new Error(`Unknown inventory action: ${name}`) + }, + state: () => ({ files: state?.nativeChatFilePaths ?? [] }), + dispose: hook.unmount + } + }, + 'project.update-metadata': (context) => { + const useMetadata = modules.load< + typeof import('../../tasks/use-mobile-tasks-project-metadata-actions') + >( + 'mobile/src/tasks/use-mobile-tasks-project-metadata-actions.tsx' + ).useMobileTasksProjectMetadataActions + const row = { + id: 'item-1', + itemType: 'ISSUE', + content: { repository: 'owner/repo', number: 1, labels: [], assignees: [] } + } + const model = observableModel(context, { + projectMutating: false, + projectRowDetailError: '', + projectRowItem: row, + githubProjectTable: { rows: [row] }, + projectRowDetail: null, + projectFieldDrafts: {} + }) + Object.assign(model, { + client: context.client, + activeGitHubProjectHost: 'github.enterprise.test' + }) + if (options.reference) { + model.taskOperations = { + projectMutation: modules + .load('mobile/src/tasks/native-host-task-project-mutation-operations.ts') + .nativeHostTaskProjectMutationOperations(context.client) + } + } + let actions: ReturnType + const hook = hookMount(() => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the recorder supplies only the members the hook reads. + actions = useMetadata(model as unknown as Parameters[0]) + }) + return { + action(name) { + if (name === 'mount') { + return hook.mount() + } + if (name === 'submit') { + return actions.mutateProjectRowMetadata( + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the scenario supplies the row as JSON, not as a typed model. + row as unknown as Parameters[0], + { addLabels: ['recorded'] } + ) + } + throw new Error(`Unknown project action: ${name}`) + }, + state: () => ({ + mutating: model.projectMutating, + error: model.projectRowDetailError, + row: model.projectRowItem + }), + dispose: hook.unmount + } + }, + 'linear.issue-detail': (context) => { + const useDetail = modules.load< + typeof import('../../tasks/use-mobile-tasks-item-detail-loading') + >('mobile/src/tasks/use-mobile-tasks-item-detail-loading.tsx').useMobileTasksItemDetailLoading + const model = observableModel(context, { + actionItem: { + provider: 'linear', + source: { id: 'issue-1', workspaceId: 'linear-workspace' } + }, + detailLoading: false, + detailError: '', + detailPayload: null, + items: [] + }) + Object.assign(model, { client: context.client, tasksSupported: true, detailRefreshSeq: 0 }) + if (options.reference) { + model.taskOperations = { + detail: modules + .load('mobile/src/tasks/native-host-task-detail-operations.ts') + .nativeHostTaskDetailOperations(context.client) + } + } + const hook = hookMount(() => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the recorder supplies only the members the hook reads. + useDetail(model as unknown as Parameters[0]) + }) + return { + action(name) { + if (name === 'mount' || name === 'remount') { + return hook.mount() + } + if (name === 'unmount') { + return hook.unmount() + } + if (name === 'reset') { + model.detailRefreshSeq = Number(model.detailRefreshSeq) + 1 + return hook.update() + } + if (name === 'blur') { + return + } + throw new Error(`Unknown detail action: ${name}`) + }, + state: () => ({ + loading: model.detailLoading, + error: model.detailError, + payload: model.detailPayload + }), + dispose: hook.unmount + } + }, + 'settings.new-tab-agents': ({ client }) => { + const load = modules.load( + 'mobile/src/session/mobile-new-tab-agent-loader.ts' + ).loadMobileNewTabAgentOptions + return { + action: (_name, args) => + load({ client, worktreeId: String(args.workspace ?? 'repo-1::/folder') }), + state: () => ({}), + dispose: () => {} + } + }, + 'settings.task-preferences': (context) => { + const usePreferences = modules.load< + typeof import('../../tasks/use-mobile-tasks-client-settings-actions') + >( + 'mobile/src/tasks/use-mobile-tasks-client-settings-actions.tsx' + ).useMobileTasksClientSettingsActions + const model = observableModel(context, { + defaultGitHubPreset: 'all', + githubProjectSettings: {} + }) + Object.assign(model, { + client: context.client, + clientRef: { current: context.client }, + repoSelectionHydratedRef: { current: false }, + defaultRepoSelectionRef: { current: null }, + taskUiReady: true, + githubProjectFieldVisibilityScope: null, + taskResumeRef: { current: {} }, + trustedOrcaHooks: {} + }) + let actions: ReturnType + const hook = hookMount(() => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the recorder supplies only the members the hook reads. + actions = usePreferences(model as unknown as Parameters[0]) + }) + return { + action(name, args) { + if (name === 'mount') { + return hook.mount() + } + if (name === 'write') { + return actions.persistDefaultGitHubPreset( + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the preset arrives from the scenario JSON as a string. + args.preset as Parameters[0] + ) + } + throw new Error(`Unknown preferences action: ${name}`) + }, + state: () => ({ preset: model.defaultGitHubPreset }), + dispose: hook.unmount + } + } + } + return { adapters, assertMutationApplied: modules.assertMutationApplied } +} diff --git a/mobile/src/test-support/rpc-recording/pilot-recordings.test.ts b/mobile/src/test-support/rpc-recording/pilot-recordings.test.ts new file mode 100644 index 00000000000..b3ac0688539 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/pilot-recordings.test.ts @@ -0,0 +1,142 @@ +import { readScenarios } from './scenario-input' +import { resolve } from 'node:path' +import { describe, expect, it } from 'vitest' +import { runRecording, runRecordingMutant } from './run-recording' +import { pilotMountAdapters } from './pilot-mount-adapters' +import { vitestRecordingScheduler } from './vitest-recording-scheduler' +import { + compareGolden, + goldenBytes, + goldenRecording, + readGolden, + writeGolden +} from './golden-recording' +import type { Recording } from './recording-scenario' +import type { RecordedValue } from './recording-values' +import type { Mutation } from './operation-mutations' +import { determinismRuns } from './determinism-runs' + +const root = resolve(import.meta.dirname, '../../../..') +const input = readScenarios( + process.env.RPC_FOUNDATION_SCENARIOS ?? + resolve(root, 'mobile/rpc-foundation/pilot-scenarios.json') +) +const goldens = process.env.RPC_FOUNDATION_GOLDENS ?? resolve(root, 'mobile/rpc-foundation/goldens') +// One mutant per adapter family, so every family's state projection is shown to be load-bearing. +const mutants: Record = { + b1: 'race', + b2: 'acceptance', + b3: 'order', + 'settings-bot-overrides-fulfilled': 'bot-overrides-envelope', + 'settings-workspace-context-fulfilled': 'workspace-context-envelope', + 'settings-home-providers-fulfilled': 'home-providers-linear', + 'settings-repo-metadata-fulfilled': 'repo-metadata-platform', + 'settings-task-hydration-fulfilled': 'task-hydration-envelope', + 'settings-task-write': 'task-preferences-optimistic', + 'settings-workspace-submit-fulfilled': 'workspace-submit-envelope', + 'settings-task-workspace-fulfilled': 'task-workspace-envelope' +} +/** + * The archived tree's visible state, pinned per seed: b1 serves the poisoned empty inventory, b2 + * accepts the null envelope and applies the label anyway, and b3 reports the issue error instead of + * the comments error. An unrelated refactor of those files can no longer keep this green by merely + * differing; the mutants remain the defect evidence and this run corroborates them. + */ +const referenceStates: Record = { + b1: { files: [] }, + b2: { + error: '', + mutating: false, + row: { + content: { + assignees: [], + labels: [{ color: '808080', name: 'recorded' }], + number: 1, + repository: 'owner/repo' + }, + id: 'item-1', + itemType: 'ISSUE' + } + }, + b3: { error: 'issue refused', loading: false, payload: { $rpc: 'null' } } +} + +function visibleState(recording: Recording): RecordedValue { + return recording.checkpoints.at(-1)!.observation.state +} + +describe('RPC main recordings', () => { + for (const scenario of input.scenarios) { + it(`${scenario.id}: frozen main parity and determinism`, async () => { + let first = '' + for (let run = 0; run < determinismRuns(); run++) { + const { adapters } = pilotMountAdapters(root) + const recording = await runRecording( + scenario, + adapters[scenario.operation], + vitestRecordingScheduler() + ) + if (scenario.id === 'b1') { + expect(visibleState(recording)).toEqual({ files: ['third.ts'] }) + } + if (scenario.id === 'b2') { + expect(visibleState(recording)).toMatchObject({ + error: "Cannot read properties of null (reading 'ok')" + }) + } + if (scenario.id === 'b3') { + expect(visibleState(recording)).toMatchObject({ + error: 'comments transport error', + loading: false + }) + } + const golden = goldenRecording(root, input.baseline, scenario, recording) + const bytes = goldenBytes(golden) + if (run) { + expect(bytes).toBe(first) + } + first = bytes + if (process.env.RPC_FOUNDATION_MODE === '--record') { + await writeGolden(goldens, golden, '--record') + } else { + compareGolden(readGolden(goldens, scenario.id), golden) + } + } + }) + const mutation = mutants[scenario.id] + if (!mutation) { + continue + } + it(`${scenario.id}: kills ${mutation}`, async () => { + const { adapters, assertMutationApplied } = pilotMountAdapters(root, { mutation }) + const result = await runRecordingMutant( + scenario, + adapters[scenario.operation], + vitestRecordingScheduler(), + readGolden(goldens, scenario.id).recording, + visibleState + ) + assertMutationApplied() + expect(result.verdict).toBe('killed') + }) + const reference = referenceStates[scenario.id] + if (!reference) { + continue + } + it.skipIf(!process.env.RPC_FOUNDATION_REFERENCE_ROOT)( + `${scenario.id}: rejects bcba08b3e4`, + async () => { + const { adapters } = pilotMountAdapters(process.env.RPC_FOUNDATION_REFERENCE_ROOT!, { + reference: true + }) + const result = await runRecording( + scenario, + adapters[scenario.operation], + vitestRecordingScheduler() + ) + expect(visibleState(result)).toEqual(reference) + expect(reference).not.toEqual(visibleState(readGolden(goldens, scenario.id).recording)) + } + ) + } +}) diff --git a/mobile/src/test-support/rpc-recording/prelude-checkpoints.ts b/mobile/src/test-support/rpc-recording/prelude-checkpoints.ts new file mode 100644 index 00000000000..2f3595b84f6 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/prelude-checkpoints.ts @@ -0,0 +1,53 @@ +import type { RecordingScenario, ScenarioStep } from './recording-scenario' + +/** A generated variant plus the index in its own step list where its distinguishing input lands. */ +export type DivergingScenario = { scenario: RecordingScenario; divergence: number } + +function stepsKey(steps: readonly ScenarioStep[]): string { + // The replacer keeps an explicit-undefined param distinct from an absent one. + return JSON.stringify(steps, (_key, value: unknown) => + value === undefined ? '$undefined' : value + ) +} + +/** + * A checkpoint before a variant's divergence observes steps identical to the base, so every variant + * would record the same value. Record those once in a prelude and let each variant start at its own + * divergence; checkpoints that merely happen to be equal are left alone. + */ +export function hoistPreludeCheckpoints( + base: RecordingScenario, + variants: readonly DivergingScenario[] +): RecordingScenario[] { + if (!variants.length) { + throw new Error(`No variants to hoist: ${base.id}`) + } + for (const { scenario, divergence } of variants) { + if ( + stepsKey(scenario.steps.slice(0, divergence)) !== stepsKey(base.steps.slice(0, divergence)) + ) { + throw new Error(`Variant diverges from the base before its divergence index: ${scenario.id}`) + } + } + const shared = Math.max(...variants.map((variant) => variant.divergence)) + const preludeSteps = base.steps.slice(0, shared) + const scenarios: RecordingScenario[] = [] + if (preludeSteps.some((step) => 'checkpoint' in step)) { + scenarios.push({ + ...base, + id: `${base.id}.prelude`, + schedules: ['prelude'], + steps: preludeSteps + }) + } + for (const { scenario, divergence } of variants) { + const steps = scenario.steps.filter( + (step, index) => !('checkpoint' in step) || index >= divergence + ) + if (!steps.some((step) => 'checkpoint' in step)) { + throw new Error(`Variant has no checkpoint at or after its divergence: ${scenario.id}`) + } + scenarios.push({ ...scenario, steps }) + } + return scenarios +} diff --git a/mobile/src/test-support/rpc-recording/probe-hole-witness.test.ts b/mobile/src/test-support/rpc-recording/probe-hole-witness.test.ts new file mode 100644 index 00000000000..126b713e811 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/probe-hole-witness.test.ts @@ -0,0 +1,67 @@ +import { resolve } from 'node:path' +import { describe, expect, it } from 'vitest' +import { readScenarios } from './scenario-input' +import { readGolden } from './golden-recording' +import { runRecordingMutant } from './run-recording' +import { pilotMountAdapters } from './pilot-mount-adapters' +import { vitestRecordingScheduler } from './vitest-recording-scheduler' +import type { Mutation } from './operation-mutations' + +const root = resolve(import.meta.dirname, '../../../..') +const input = readScenarios( + process.env.RPC_FOUNDATION_SCENARIOS ?? + resolve(root, 'mobile/rpc-foundation/pilot-scenarios.json') +) +const goldens = process.env.RPC_FOUNDATION_GOLDENS ?? resolve(root, 'mobile/rpc-foundation/goldens') + +/** + * Each probe exists because a real mutation survived the whole pre-probe suite. Hole and closure + * are asserted together: if a pre-probe scenario of the same operation also caught the mutation, + * the probe is redundant and this test says so instead of letting it accumulate. + */ +const HOLES: readonly { mutation: Mutation; operation: string; closedBy: readonly string[] }[] = [ + { + mutation: 'new-tab-refusal-order', + operation: 'settings.new-tab-agents', + closedBy: ['probe-new-tab-both-refused'] + }, + { + mutation: 'new-tab-deferred-settings-read', + operation: 'settings.new-tab-agents', + closedBy: ['probe-new-tab-null-sibling-refused'] + }, + { + mutation: 'workspace-context-refusal-blanks', + operation: 'settings.workspace-context', + closedBy: ['settings-workspace-context-refuse-after-data'] + } +] + +async function verdict(id: string, mutation: Mutation): Promise { + const scenario = input.scenarios.find((candidate) => candidate.id === id)! + const { adapters, assertMutationApplied } = pilotMountAdapters(root, { mutation }) + const result = await runRecordingMutant( + scenario, + adapters[scenario.operation], + vitestRecordingScheduler(), + readGolden(goldens, id).recording + ) + assertMutationApplied() + return result.verdict +} + +describe('probe scenarios close holes the pre-probe recordings left open', () => { + for (const hole of HOLES) { + const family = input.scenarios.filter((scenario) => scenario.operation === hole.operation) + for (const id of hole.closedBy) { + it(`${id} kills ${hole.mutation}`, async () => { + expect(await verdict(id, hole.mutation)).toBe('killed') + }) + } + for (const scenario of family.filter(({ id }) => !hole.closedBy.includes(id))) { + it(`${scenario.id} cannot see ${hole.mutation}`, async () => { + expect(await verdict(scenario.id, hole.mutation)).toBe('survived') + }) + } + } +}) diff --git a/mobile/src/test-support/rpc-recording/recorder-digest.ts b/mobile/src/test-support/rpc-recording/recorder-digest.ts new file mode 100644 index 00000000000..af25eb1f5fd --- /dev/null +++ b/mobile/src/test-support/rpc-recording/recorder-digest.ts @@ -0,0 +1,44 @@ +import { createHash } from 'node:crypto' +import { readFileSync, readdirSync } from 'node:fs' +import { join, posix } from 'node:path' + +export const RECORDER_DIRECTORY = 'mobile/src/test-support/rpc-recording' +export const RECORDER_SCENARIO_INPUT = 'mobile/rpc-foundation/pilot-scenarios.json' +const digests = new Map() + +function collect(root: string, relative: string, files: string[]): void { + for (const entry of readdirSync(join(root, relative), { withFileTypes: true }).sort((a, b) => + a.name < b.name ? -1 : 1 + )) { + const child = `${relative}/${entry.name}` + if (entry.isDirectory()) { + collect(root, child, files) + } else if (!entry.name.endsWith('.md')) { + files.push(child) + } + } +} + +/** + * Every executable recorder input, so a golden is attributable to one runner and one scenario file. + * Prose is excluded because it cannot change a recording; a candidate run recomputes this and + * `compareGolden` fails the header, which forces a recorder edit to re-record deliberately. + */ +export function recorderSha256(root: string): string { + const cached = digests.get(root) + if (cached !== undefined) { + return cached + } + const files: string[] = [] + collect(root, RECORDER_DIRECTORY, files) + files.push(RECORDER_SCENARIO_INPUT) + const digest = createHash('sha256') + .update( + files + .map((file) => `${file}:${readFileSync(join(root, ...file.split(posix.sep)))}`) + .join('\n') + ) + .digest('hex') + digests.set(root, digest) + return digest +} diff --git a/mobile/src/test-support/rpc-recording/recording-runner.test.ts b/mobile/src/test-support/rpc-recording/recording-runner.test.ts new file mode 100644 index 00000000000..b81597248ae --- /dev/null +++ b/mobile/src/test-support/rpc-recording/recording-runner.test.ts @@ -0,0 +1,475 @@ +import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { operationModuleLoader } from './operation-module-loader' +import { describe, expect, it } from 'vitest' +import { captureArguments, captureError, captureValue } from './recording-values' +import { RECORDER_DIRECTORY, recorderSha256 } from './recorder-digest' +import { ScriptedRpcTransport } from './scripted-rpc-transport' +import { vitestRecordingScheduler } from './vitest-recording-scheduler' +import { + compareGolden, + GOLDEN_FORMAT_VERSION, + goldenBytes, + PROJECTION_VERSION, + readGolden, + writeGolden, + type GoldenRecording +} from './golden-recording' +import { hoistPreludeCheckpoints } from './prelude-checkpoints' +import { replyMatrixGoldenId, replyMatrixSites } from './reply-matrix' +import { + REPLY_MATRIX_NORMAL_RESULT_INVENTORY, + replyMatrixNormalResult +} from './reply-matrix-normal-result' +import { runRecording } from './run-recording' +import { valueHash, type InternedObservation } from './golden-value-pool' +import type { Observation, RecordingScenario } from './recording-scenario' +import type { RecordedValue } from './recording-values' + +describe('recording boundaries', () => { + it('preserves omitted arguments, explicit undefined, null, order, and tagged-looking objects', () => { + expect(captureArguments(['m'])).not.toEqual(captureArguments(['m', undefined])) + expect(captureArguments(['m', undefined])).not.toEqual(captureArguments(['m', null])) + expect(captureValue({ b: undefined, a: null })).toEqual(captureValue({ a: null, b: undefined })) + expect(captureValue({ $rpc: 'undefined' })).not.toEqual(captureValue(undefined)) + expect(captureValue([1, 2])).not.toEqual(captureValue([2, 1])) + }) + + it('runs the actual stable-client projection and physical serialization', async () => { + const clock = vitestRecordingScheduler() + clock.start() + const transport = new ScriptedRpcTransport(clock.elapsed) + try { + const result = transport.client.sendRequest( + 'worktree.ps', + { omitted: undefined, nullable: null }, + { timeoutMs: 7 } + ) + await clock.flush() + expect(transport.requests[0].args).toEqual( + captureArguments(['worktree.ps', { omitted: undefined, nullable: null }, { timeoutMs: 7 }]) + ) + expect(JSON.parse(transport.payloads[0].json)).toEqual({ + id: 'frame-1', + deviceToken: 'recording-device', + method: 'worktree.ps', + params: { nullable: null, supportsWorktreeVisibilitySourceDefaults: true } + }) + transport.complete( + 'worktree.ps#1', + { omitted: undefined, nullable: null, supportsWorktreeVisibilitySourceDefaults: true }, + { ok: true, result: null } + ) + await result + } finally { + transport.dispose() + await clock.flush() + clock.stop() + } + }) + + it('requires logical bindings plus matching params for concurrent same-method calls', async () => { + const clock = vitestRecordingScheduler() + clock.start() + const transport = new ScriptedRpcTransport(clock.elapsed) + try { + const left = transport.client.sendRequest('files.list', { worktree: 'A' }) + const right = transport.client.sendRequest('files.list', { worktree: 'B' }) + await clock.flush() + expect(() => transport.complete('files.list#1', { worktree: 'A' }, {})).toThrow( + 'logical binding' + ) + expect(() => transport.bind('left', 'files.list#1', { worktree: 'B' })).toThrow( + 'params mismatch' + ) + transport.bind('left', 'files.list#1', { worktree: 'A' }) + transport.bind('right', 'files.list#2', { worktree: 'B' }) + transport.complete('right', { worktree: 'B' }, { ok: true, result: [] }) + transport.complete('left', { worktree: 'A' }, { ok: true, result: [] }) + await Promise.all([left, right]) + } finally { + transport.dispose() + await clock.flush() + clock.stop() + } + }) + + it('records actual deadline ambiguity and leaves peers pending before their deadlines', async () => { + const clock = vitestRecordingScheduler() + clock.start() + const transport = new ScriptedRpcTransport(clock.elapsed) + try { + void transport.client.sendRequest('short', {}, { timeoutMs: 5 }).catch(() => {}) + void transport.client.sendRequest('long', {}, { timeoutMs: 50 }).catch(() => {}) + await clock.advance(5) + // Exact virtual milliseconds: the deadline is recorded at the value the product asked for. + expect(transport.requests[0].settlement).toEqual({ + status: 'rejected', + startedAt: 0, + settledAt: 5, + error: { + category: 'Error', + message: 'Request timed out: short', + isRpcDeliveryUnknown: true + } + }) + expect(transport.requests[1].settlement).toEqual({ status: 'pending', startedAt: 0 }) + } finally { + transport.dispose() + await clock.flush() + clock.stop() + } + }) + + it('never writes from candidate mode and requires both recording authorizations', async () => { + const directory = mkdtempSync(join(tmpdir(), 'rpc-recording-')) + const golden = sampleGolden('test') + const previous = process.env.RPC_FOUNDATION_RECORD + try { + process.env.RPC_FOUNDATION_RECORD = '0' + await expect(writeGolden(directory, golden, '--record')).rejects.toThrow('require') + process.env.RPC_FOUNDATION_RECORD = '1' + await expect(writeGolden(directory, golden, 'candidate')).rejects.toThrow('require') + await writeGolden(directory, golden, '--record') + expect(readGolden(directory, 'test')).toEqual(golden) + expect(() => readGolden(directory, '../escape')).toThrow('Unsafe') + writeFileSync( + join(directory, 'stale.json'), + JSON.stringify({ + ...JSON.parse(readFileSync(join(directory, 'test.json'), 'utf8')), + goldenFormatVersion: 1 + }) + ) + expect(() => readGolden(directory, 'stale')).toThrow( + `format version 1; this reader requires ${GOLDEN_FORMAT_VERSION}` + ) + } finally { + if (previous === undefined) { + delete process.env.RPC_FOUNDATION_RECORD + } else { + process.env.RPC_FOUNDATION_RECORD = previous + } + rmSync(directory, { recursive: true }) + } + }) + + it('stores a growing history once per entry and still resolves every checkpoint', () => { + const golden = sampleGolden('pooled') + golden.recording.checkpoints = [ + { id: 'first', observation: history(['a']) }, + { id: 'second', observation: history(['a', 'b']) }, + { id: 'third', observation: history(['a', 'b', 'c']) } + ] + const file = goldenFile(golden) + // Six observations of three distinct entries: each is stored once, plus the three states. + expect(Object.keys(file.values)).toHaveLength(6) + expect(file.recording.checkpoints.map((checkpoint) => checkpoint.observation.sender)).toEqual([ + ['a'].map(entryHash), + ['a', 'b'].map(entryHash), + ['a', 'b', 'c'].map(entryHash) + ]) + // Whichever checkpoint an entry was first seen in, every later reference resolves to it. + const directory = mkdtempSync(join(tmpdir(), 'rpc-recording-')) + try { + writeFileSync(join(directory, 'pooled.json'), goldenBytes(golden)) + expect(readGolden(directory, 'pooled')).toEqual(golden) + } finally { + rmSync(directory, { recursive: true }) + } + }) + + it('refuses a pooled entry edited in place, and one no checkpoint reads', () => { + const golden = sampleGolden('tampered') + golden.recording.checkpoints = [{ id: 'first', observation: history(['a']) }] + const file = goldenFile(golden) + const hash = entryHash('a') + const directory = mkdtempSync(join(tmpdir(), 'rpc-recording-')) + try { + writeFileSync( + join(directory, 'tampered.json'), + JSON.stringify({ + ...file, + values: { ...file.values, [hash]: { name: 'a', hostile: true } } + }) + ) + expect(() => readGolden(directory, 'tampered')).toThrow( + `Golden value ${hash} does not hash to its pool key` + ) + writeFileSync( + join(directory, 'orphaned.json'), + JSON.stringify({ + ...file, + values: { ...file.values, [valueHash('unread')]: 'unread' } + }) + ) + expect(() => readGolden(directory, 'orphaned')).toThrow( + `Golden pool holds unreferenced values: ${valueHash('unread')}` + ) + } finally { + rmSync(directory, { recursive: true }) + } + }) + + it('interns a field by its declared container, not by the value it happens to hold', () => { + const golden = sampleGolden('shape') + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the point of the test is a field recorded with the wrong container. + golden.recording.checkpoints[0]!.observation.sender = {} as unknown as RecordedValue[] + expect(() => goldenBytes(golden)).toThrow( + 'Observation field settled.sender is declared a list but recorded object' + ) + }) + + it('names the scenario, checkpoint and field, and prints values rather than hashes', () => { + const expected = sampleGolden('diffable') + const actual = sampleGolden('diffable') + actual.recording.checkpoints[0]!.observation.state = { phase: 'busy' } + expect(() => compareGolden(expected, actual)).toThrow( + /Recording differs: diffable checkpoint settled field state\.phase[\s\S]*"idle"[\s\S]*"busy"/ + ) + }) + + it('accepts a dependency bump but still refuses a different baseline', () => { + const expected = sampleGolden('provenance') + const bumped = sampleGolden('provenance') + bumped.lockfileSha256 = 'd'.repeat(64) + expect(() => compareGolden(expected, bumped)).not.toThrow() + const rebased = sampleGolden('provenance') + rebased.baseline = 'e'.repeat(40) + expect(() => compareGolden(expected, rebased)).toThrow( + /Recording differs: provenance header baseline/ + ) + }) + + it('records a shared prefix once and refuses a variant that already diverged', () => { + const base: RecordingScenario = { + id: 'family', + operation: 'op', + version: 1, + family: 'op', + sites: [], + schedules: [], + steps: [ + { action: 'mount', id: 'mount' }, + { checkpoint: 'pending' }, + { complete: 'a#1', params: {}, reply: { ok: true } }, + { checkpoint: 'settled' } + ] + } + const variant = (id: string, reply: unknown): RecordingScenario => ({ + ...base, + id, + steps: base.steps.map((step) => ('complete' in step ? { ...step, reply } : step)) + }) + const hoisted = hoistPreludeCheckpoints(base, [ + { divergence: 2, scenario: variant('family.ok', { ok: true }) }, + { divergence: 2, scenario: variant('family.refused', { ok: false }) } + ]) + expect(hoisted.map((scenario) => scenario.id)).toEqual([ + 'family.prelude', + 'family.ok', + 'family.refused' + ]) + expect(hoisted[0]!.steps.filter((step) => 'checkpoint' in step)).toEqual([ + { checkpoint: 'pending' } + ]) + expect(hoisted[1]!.steps.filter((step) => 'checkpoint' in step)).toEqual([ + { checkpoint: 'settled' } + ]) + expect(() => + hoistPreludeCheckpoints(base, [ + { divergence: 3, scenario: variant('family.late', { ok: false }) } + ]) + ).toThrow('diverges from the base') + }) + + // A matrix that cannot drive a family has to fail. The prefix list it replaced returned no site + // and the loop skipped, which is how ten families lost their matrix without a red test. + it('refuses a family it cannot matrix instead of skipping it', () => { + const base: RecordingScenario = { + id: 'family', + operation: 'op', + version: 1, + family: 'op', + sites: [], + schedules: [], + steps: [{ action: 'mount', id: 'mount' }, { checkpoint: 'settled' }] + } + expect(() => replyMatrixSites(base)).toThrow('No scripted reply to drive a matrix over') + expect(() => + replyMatrixSites({ + ...base, + steps: [ + { complete: 'a#1', params: {}, reply: { ok: true, result: 1 } }, + { complete: 'a#1', params: {}, reply: { ok: true, result: 2 } }, + { checkpoint: 'settled' } + ] + }) + ).toThrow('Matrix sites must be unique') + expect(replyMatrixGoldenId('hostedReview.eligibility', 'hostedReview.create#1')).toBe( + 'matrix-hostedreview.eligibility-hostedreview.create-1' + ) + }) + + it('refuses a matrix site with no recorded success, and a redundant inventory entry', () => { + const scenario = (reply: unknown): RecordingScenario => ({ + id: 'family', + operation: 'op', + version: 1, + family: 'op', + sites: [], + schedules: [], + steps: [{ complete: 'a#1', params: {}, reply }, { checkpoint: 'settled' }] + }) + // Absent and null are partitions of their own, so neither can stand in as the success control. + for (const reply of [{ ok: true }, { ok: true, result: null }, { ok: false }]) { + expect(() => replyMatrixNormalResult('op', [scenario(reply)], 'a#1')).toThrow( + 'No fulfilled reply recorded for matrix site' + ) + } + expect( + replyMatrixNormalResult('op', [scenario({ ok: true, result: { n: 1 } })], 'a#1') + ).toEqual({ + n: 1 + }) + const inventoried = REPLY_MATRIX_NORMAL_RESULT_INVENTORY[0]! + expect(() => + replyMatrixNormalResult( + inventoried.family, + [ + { + ...scenario({ ok: true, result: { n: 1 } }), + steps: [ + { complete: inventoried.request, params: {}, reply: { ok: true, result: { n: 1 } } }, + { checkpoint: 'settled' } + ] + } + ], + inventoried.request + ) + ).toThrow('drop its REPLY_MATRIX_NORMAL_RESULT_INVENTORY entry') + }) + + it('refuses a checkpoint whose clock drifted from the scripted advances', async () => { + const scheduler = vitestRecordingScheduler() + await expect( + runRecording( + { + id: 'drift', + operation: 'op', + version: 1, + family: 'op', + sites: [], + schedules: [], + steps: [{ advance: 10 }, { checkpoint: 'settled' }] + }, + () => ({ action: () => {}, state: () => ({}), dispose: () => {} }), + { ...scheduler, elapsed: () => scheduler.elapsed() + 1 } + ) + ).rejects.toThrow('Checkpoint clock drifted: drift settled at 11, scripted 10') + }) + + it('records an error code and cause, and omits both when the error carries neither', () => { + expect(captureError(new Error('plain'))).toEqual({ + category: 'Error', + message: 'plain', + isRpcDeliveryUnknown: false + }) + const detailed = Object.assign(new TypeError('outer'), { + code: 'refused', + cause: new Error('inner') + }) + expect(captureError(detailed)).toMatchObject({ + code: 'refused', + cause: { category: 'Error', message: 'inner' } + }) + }) + + it('digests every executable recorder input and ignores prose', () => { + const root = mkdtempSync(join(tmpdir(), 'rpc-recorder-')) + try { + const directory = join(root, RECORDER_DIRECTORY) + mkdirSync(directory, { recursive: true }) + mkdirSync(join(root, 'mobile/rpc-foundation'), { recursive: true }) + writeFileSync(join(root, 'mobile/rpc-foundation/pilot-scenarios.json'), '{}') + writeFileSync(join(directory, 'runner.ts'), 'export const runner = 1') + const original = recorderSha256(root) + writeFileSync(join(directory, 'README.md'), 'prose') + expect(recorderSha256(join(root, '.'))).toBe(original) + writeFileSync(join(directory, 'runner.ts'), 'export const runner = 2') + expect(recorderSha256(join(root, './'))).not.toBe(original) + } finally { + rmSync(root, { recursive: true }) + } + }) + + it('refuses a mutation anchor that matches more than once', () => { + const root = mkdtempSync(join(tmpdir(), 'rpc-mutant-')) + try { + const anchor = + "const overrides = settings == null ? undefined : Reflect.get(Object(settings), 'prBotAuthorOverrides')" + mkdirSync(join(root, 'mod'), { recursive: true }) + writeFileSync( + join(root, 'mod/settings-read-operations.ts'), + `const raw = {} as { settings?: unknown }\nconst settings = raw.settings\nexport function first() {\n ${anchor}\n return overrides\n}\nexport function second() {\n ${anchor}\n return overrides\n}\n` + ) + const loader = operationModuleLoader(root, 'bot-overrides-envelope') + expect(() => loader.load('mod/settings-read-operations.ts')).toThrow( + 'matched 2 sites, expected 1' + ) + } finally { + rmSync(root, { recursive: true }) + } + }) +}) + +function entryHash(name: string): string { + return valueHash({ name }) +} + +/** An append-only sender history, the shape every checkpoint after the first re-states. */ +function history(names: readonly string[]): Observation { + return { + ...observation(names.join('-')), + sender: names.map((name) => ({ name })), + settlements: Object.fromEntries(names.map((name) => [name, { name }])) + } +} + +function goldenFile(golden: GoldenRecording): { + values: Record + recording: { checkpoints: { id: string; observation: InternedObservation }[] } +} { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the bytes were just produced by goldenBytes, so the pool and interned checkpoints are present. + return JSON.parse(goldenBytes(golden)) as { + values: Record + recording: { checkpoints: { id: string; observation: InternedObservation }[] } + } +} + +function observation(phase: string): Observation { + return { + sender: [], + payloads: [], + settlements: {}, + state: { phase }, + effects: [] + } +} + +function sampleGolden(id: string): GoldenRecording { + return { + operation: 'op', + family: 'op', + namedDeltas: [], + runnerVersion: 1, + baseline: 'a'.repeat(40), + lockfileSha256: 'b'.repeat(64), + recorderSha256: 'c'.repeat(64), + platform: process.platform, + scenarioVersion: 1, + projectionVersion: PROJECTION_VERSION, + goldenFormatVersion: GOLDEN_FORMAT_VERSION, + recording: { scenario: id, checkpoints: [{ id: 'settled', observation: observation('idle') }] } + } +} diff --git a/mobile/src/test-support/rpc-recording/recording-scenario.ts b/mobile/src/test-support/rpc-recording/recording-scenario.ts new file mode 100644 index 00000000000..ee1fe21814f --- /dev/null +++ b/mobile/src/test-support/rpc-recording/recording-scenario.ts @@ -0,0 +1,59 @@ +import type { RpcClient } from '../../transport/rpc-client' +import type { RecordedValue } from './recording-values' + +export type RpcRequestSender = Pick +export type Rejection = { + message: string + category?: 'Error' | 'TypeError' + deliveryUnknown?: boolean +} +/** + * `optional` belongs to generated steps only: a matrix variant answers one request differently, so + * the requests scripted after it may never be sent. Skipping one that was not sent records what the + * operation actually did; a scripted step the manifest declares is never optional. + */ +export type ScenarioStep = + | { action: string; id: string; args?: Record } + | { complete: string; params: unknown; reply?: unknown; reject?: Rejection; optional?: true } + | { bind: string; request: string; params: unknown; optional?: true } + | { advance: number } + | { checkpoint: string } +export type RecordingScenario = { + id: string + operation: string + version: number + family: string + sites: string[] + schedules: string[] + namedDeltas?: string[] + steps: ScenarioStep[] +} +export type MountedOperation = { + action: (name: string, args: Record) => unknown + state: () => unknown + dispose: () => void | Promise +} +export type MountContext = { + client: RpcClient + effect: (name: string, value: unknown) => void +} +export type MountAdapter = (context: MountContext) => MountedOperation +export type RecordingScheduler = { + start: () => void + flush: () => Promise + advance: (ms: number) => Promise + /** Virtual milliseconds since the pinned recording epoch. */ + elapsed: () => number + stop: () => void +} +export type Observation = { + sender: RecordedValue + payloads: RecordedValue + settlements: RecordedValue + state: RecordedValue + effects: RecordedValue +} +export type Recording = { + scenario: string + checkpoints: { id: string; observation: Observation }[] +} diff --git a/mobile/src/test-support/rpc-recording/recording-values.ts b/mobile/src/test-support/rpc-recording/recording-values.ts new file mode 100644 index 00000000000..dff938bab69 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/recording-values.ts @@ -0,0 +1,94 @@ +import { isRpcDeliveryUnknown } from '../../transport/rpc-delivery-ambiguity' + +export type RecordedValue = + | null + | boolean + | number + | string + | RecordedValue[] + | { + [key: string]: RecordedValue + } + +export function captureValue(value: unknown): RecordedValue { + if (value === undefined) { + return { $rpc: 'undefined' } + } + if (value === null) { + return { $rpc: 'null' } + } + if (Array.isArray(value)) { + return value.map(captureValue) + } + if (typeof value === 'object') { + if (![Object.prototype, null].includes(Object.getPrototypeOf(value))) { + throw new Error('Observation requires an explicit projection for non-plain objects') + } + const entries = Object.keys(value) + .sort() + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the plain-object branch above already narrowed the container. + .map((key) => [key, captureValue((value as Record)[key])] as const) + return '$rpc' in value + ? { $rpc: 'object', entries: entries.map(([key, entry]) => [key, entry]) } + : Object.fromEntries(entries) + } + if (typeof value === 'number' && !Number.isFinite(value)) { + return { $rpc: 'number', value: String(value) } + } + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return value + } + throw new Error(`Unsupported observation: ${typeof value}`) +} + +export function captureArguments(args: readonly unknown[]): RecordedValue { + return ['method', 'params', 'options'].map((name, index) => ({ + name, + value: index < args.length ? captureValue(args[index]) : { $rpc: 'absent' } + })) +} + +/** `code` and `cause` are recorded only when present, so an error without them keeps three fields. */ +export function captureError(error: unknown, depth = 0): RecordedValue { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: code and cause are read defensively; a thrown value carries neither by type. + const detail = error as { code?: unknown; cause?: unknown } + const code = error instanceof Error ? detail.code : undefined + const cause = error instanceof Error && depth < 4 ? detail.cause : undefined + return { + category: error instanceof Error ? error.constructor.name : typeof error, + message: error instanceof Error ? error.message : String(error), + isRpcDeliveryUnknown: isRpcDeliveryUnknown(error), + ...(code === undefined ? {} : { code: captureValue(code) }), + ...(cause === undefined ? {} : { cause: captureError(cause, depth + 1) }) + } +} + +/** + * `startedAt` and `settledAt` are virtual milliseconds on the pinned fake clock. They give the + * observation a temporal dimension: a transition the product schedules for itself, such as a + * request deadline or a debounce, is recorded at the time it actually happens, so any change to + * that duration moves a recorded number rather than needing a scenario placed across it. + */ +export type Settlement = + | { status: 'pending'; startedAt: number } + | { status: 'fulfilled'; startedAt: number; settledAt: number; value: RecordedValue } + | { status: 'rejected'; startedAt: number; settledAt: number; error: RecordedValue } + +export function rejectedSettlement(error: unknown, at: number): Settlement { + return { status: 'rejected', startedAt: at, settledAt: at, error: captureError(error) } +} + +export function observeSettlement( + value: unknown, + now: () => number, + update: (state: Settlement) => void +): void { + const startedAt = now() + update({ status: 'pending', startedAt }) + Promise.resolve(value).then( + (result) => + update({ status: 'fulfilled', startedAt, settledAt: now(), value: captureValue(result) }), + (error: unknown) => + update({ status: 'rejected', startedAt, settledAt: now(), error: captureError(error) }) + ) +} diff --git a/mobile/src/test-support/rpc-recording/reply-matrix-normal-result.ts b/mobile/src/test-support/rpc-recording/reply-matrix-normal-result.ts new file mode 100644 index 00000000000..da29a4a1726 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/reply-matrix-normal-result.ts @@ -0,0 +1,94 @@ +import type { RecordingScenario } from './recording-scenario' + +/** + * The matrix's `normal` partition replays a result the family already records, so no migrator has + * to invent a plausible payload per domain. A few sites have no recorded success to replay, and + * those are inventoried here rather than skipped: a new domain whose scenarios only record failures + * fails the suite until it is given a fulfilled scenario or a line below. Both directions are + * checked — an entry whose family has since recorded a success fails too, and family-recordings + * asserts every entry names a live matrix site — so the list only shrinks. + */ +export type ReplyMatrixNormalResult = { + readonly family: string + readonly request: string + readonly reason: string + readonly result: unknown +} + +export const REPLY_MATRIX_NORMAL_RESULT_INVENTORY: readonly ReplyMatrixNormalResult[] = [ + { + family: 'linear-detail-barrier', + request: 'linear.getIssue#1', + // b3 is a B-seed: its one scenario exists to reproduce main's refused-issue defect, and the + // failing pair is the whole point. The payload is the shape the detail loader reads. + reason: 'the seed records the defect, so the family records no fulfilled issue', + result: { id: 'issue-1', description: 'recorded', labels: [], subIssues: [] } + }, + { + family: 'linear-detail-barrier', + request: 'linear.issueComments#1', + reason: 'same seed: the comments leg is rejected by design', + result: { comments: [] } + }, + { + family: 'project-explicit-false', + request: 'github.project.updateIssueBySlug#1', + // The b2 seed's only recorded success is a null result — the shipped bug it exists to pin — and + // `result-null` is already its own partition, so replaying it would leave the matrix no control. + reason: 'the seed records a null result, which the result-null partition already drives', + result: { ok: true } + }, + { + family: 'settings-best-effort', + request: 'settings.update#1', + // The write is fire-and-forget; the call site never reads the reply body, so no scenario had a + // reason to record one. `{ok: true}` is the shape the host sends for an accepted write. + reason: 'a best-effort write whose reply body no call site reads', + result: { ok: true } + } +] + +function fulfilledResult(reply: unknown): { found: boolean; result: unknown } { + if (reply === null || typeof reply !== 'object' || !('result' in reply)) { + return { found: false, result: undefined } + } + const envelope: { ok?: unknown; result?: unknown } = reply + // Neither an absent/undefined result nor `null` counts: both are partitions of their own, so + // replaying one as `normal` would leave the site with eight shapes and no success control. + return envelope.ok === true && envelope.result !== undefined && envelope.result !== null + ? { found: true, result: envelope.result } + : { found: false, result: undefined } +} + +/** The result the `normal` partition replays at one matrix site. */ +export function replyMatrixNormalResult( + family: string, + scenarios: readonly RecordingScenario[], + request: string +): unknown { + let recorded: { found: boolean; result: unknown } = { found: false, result: undefined } + for (const scenario of scenarios) { + for (const step of scenario.steps) { + if ('complete' in step && step.complete === request && !recorded.found) { + recorded = fulfilledResult(step.reply) + } + } + } + const inventoried = REPLY_MATRIX_NORMAL_RESULT_INVENTORY.find( + (entry) => entry.family === family && entry.request === request + ) + if (inventoried) { + if (recorded.found) { + throw new Error( + `${family} ${request} now records a fulfilled reply; drop its REPLY_MATRIX_NORMAL_RESULT_INVENTORY entry` + ) + } + return inventoried.result + } + if (!recorded.found) { + throw new Error( + `No fulfilled reply recorded for matrix site ${family} ${request}. Add a scenario that fulfils it, or list it in REPLY_MATRIX_NORMAL_RESULT_INVENTORY with the reason it cannot be.` + ) + } + return recorded.result +} diff --git a/mobile/src/test-support/rpc-recording/reply-matrix.ts b/mobile/src/test-support/rpc-recording/reply-matrix.ts new file mode 100644 index 00000000000..5ff898e4f30 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/reply-matrix.ts @@ -0,0 +1,115 @@ +import { hoistPreludeCheckpoints } from './prelude-checkpoints' +import type { RecordingScenario, Rejection, ScenarioStep } from './recording-scenario' + +export type ReplyPartition = { id: string; reply?: unknown; reject?: Rejection } + +/** + * Only shapes a host can send. `successResponse` always sets `result`, so an absent key means the + * handler returned undefined and there is no explicit-undefined shape on a JSON wire; `null` is a + * real result (`linear.getIssue` on a missing issue, and the b2 seed). The GitHub project + * mutations carry an inner `{ok, error}` envelope whose error is a string or an object. Everything + * else a client sees is the dispatcher refusing, not knowing the method, or the transport failing. + * + * Refusal and rejection each appear twice, once with a message and once without. A message is what + * separates the two failure paths a migrated call site has to keep apart: a refusal with none falls + * back to the screen's copy, a transport drop with none surfaces its empty message verbatim. With + * only the message-carrying shapes both paths produce the same text, and collapsing them is + * invisible — which is why every source-control family had a hand-written `*-empty-message` + * scenario. The partition carries that instead of each migrator remembering to write one. + */ +export function replyPartitions(normal: unknown): ReplyPartition[] { + return [ + { id: 'normal', reply: { ok: true, result: normal } }, + { id: 'result-absent', reply: { ok: true } }, + { id: 'result-null', reply: { ok: true, result: null } }, + { id: 'inner-ok-missing', reply: { ok: true, result: { error: 'refused' } } }, + { + id: 'inner-false-string-error', + reply: { ok: true, result: { ok: false, error: 'inner refused' } } + }, + { + id: 'inner-false-object-error', + reply: { ok: true, result: { ok: false, error: { message: 'inner refused' } } } + }, + { + id: 'outer-refused', + reply: { ok: false, error: { code: 'refused', message: 'outer refused' } } + }, + { + id: 'outer-refused-no-message', + reply: { ok: false, error: { code: 'refused', message: '' } } + }, + { + id: 'method-not-found', + reply: { ok: false, error: { code: 'method_not_found', message: 'Unknown method' } } + }, + { id: 'transport-rejection', reject: { message: 'transport failure', deliveryUnknown: true } }, + { id: 'transport-rejection-no-message', reject: { message: '', deliveryUnknown: true } } + ] +} + +/** + * Every reply the base scenario scripts, as a site the matrix drives. + * + * Why all of them and not one: picking the request per family is what let ten families fall out of + * the matrix without saying so, and there is no property of a scenario that identifies the "real" + * request — the settings families answer prerequisites before their own read, the chains answer + * their own steps in order. Driving every completion needs no such judgement and needs no edit when + * a domain is added. A family that scripts no reply at all cannot be matrixed and throws. + */ +export function replyMatrixSites(base: RecordingScenario): string[] { + const sites = base.steps.flatMap((step) => ('complete' in step ? [step.complete] : [])) + if (!sites.length) { + throw new Error(`No scripted reply to drive a matrix over: ${base.id}`) + } + const repeated = sites.filter((name, index) => sites.indexOf(name) !== index) + if (repeated.length) { + // A repeated name would make the divergence ambiguous; the manifest binds concurrent requests. + throw new Error(`Matrix sites must be unique: ${base.id} repeats ${repeated.join(', ')}`) + } + return sites +} + +/** Golden id for one family's matrix at one site, inside the charset `writeGolden` accepts. */ +export function replyMatrixGoldenId(family: string, request: string): string { + return `matrix-${family}-${request}`.toLowerCase().replaceAll('#', '-') +} + +export function driveReplyMatrix( + base: RecordingScenario, + request: string, + normal: unknown +): RecordingScenario[] { + const sites = base.steps.flatMap((step, index) => + 'complete' in step && step.complete === request ? [index] : [] + ) + if (sites.length !== 1) { + throw new Error(`Matrix requires exactly one completion: ${request}`) + } + const divergence = sites[0]! + return hoistPreludeCheckpoints( + base, + replyPartitions(normal).map((partition) => ({ + divergence, + scenario: { + ...base, + id: `${base.id}.${partition.id}`, + steps: base.steps.map((step, index): ScenarioStep => + index === divergence && 'complete' in step + ? { + complete: request, + params: step.params, + ...('reject' in partition + ? { reject: partition.reject } + : { reply: partition.reply }) + } + : index > divergence && ('complete' in step || 'bind' in step) + ? // The diverged reply may have ended the chain, so downstream replies are answered + // only if the operation asked for them. The sender list records which it did. + { ...step, optional: true } + : step + ) + } + })) + ) +} diff --git a/mobile/src/test-support/rpc-recording/run-recording.ts b/mobile/src/test-support/rpc-recording/run-recording.ts new file mode 100644 index 00000000000..9ace2a7a7c0 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/run-recording.ts @@ -0,0 +1,152 @@ +import { recordUnhandledRejections } from './unhandled-recording' +import { + captureValue, + observeSettlement, + rejectedSettlement, + type Settlement, + type RecordedValue +} from './recording-values' +import type { + MountAdapter, + Recording, + RecordingScenario, + RecordingScheduler, + MountedOperation +} from './recording-scenario' +import { ScriptedRpcTransport } from './scripted-rpc-transport' + +export async function runRecording( + scenario: RecordingScenario, + mount: MountAdapter, + scheduler: RecordingScheduler +): Promise { + scheduler.start() + const transport = new ScriptedRpcTransport(scheduler.elapsed) + const effects: { name: string; value: RecordedValue }[] = [] + const settlements: Record = {} + const recording: Recording = { scenario: scenario.id, checkpoints: [] } + const effect = (name: string, value: unknown) => { + effects.push({ name, value: captureValue(value) }) + } + const stopUnhandled = recordUnhandledRejections(effect) + let mounted: MountedOperation | undefined + const ids = new Set() + let advanced = 0 + let cleaned = false + const teardown = async (): Promise => { + cleaned = true + await mounted?.dispose() + transport.dispose() + await scheduler.flush() + } + try { + mounted = mount({ client: transport.client, effect }) + for (const step of scenario.steps) { + if ('action' in step) { + if (ids.has(step.id)) { + throw new Error(`Duplicate action: ${step.id}`) + } + ids.add(step.id) + try { + const value = + step.action === 'disconnect' + ? transport.disconnect() + : step.action === 'cutover' + ? transport.cutover() + : mounted.action(step.action, step.args ?? {}) + observeSettlement(value, scheduler.elapsed, (state) => { + settlements[step.id] = state + }) + } catch (error) { + settlements[step.id] = rejectedSettlement(error, scheduler.elapsed()) + } + } else if ('complete' in step) { + if (!step.optional || transport.outstanding(step.complete)) { + transport.complete(step.complete, step.params, step.reply, step.reject) + } + } else if ('bind' in step) { + if (!step.optional || transport.outstanding(step.request)) { + transport.bind(step.bind, step.request, step.params) + } + } else if ('advance' in step) { + advanced += step.advance + await scheduler.advance(step.advance) + } + await scheduler.flush() + if ('checkpoint' in step) { + // A checkpoint's own clock is the sum of the scripted advances, so recording it would add + // bytes and no signal. Asserted rather than recorded, so a future drift fails loudly. + if (scheduler.elapsed() !== advanced) { + throw new Error( + `Checkpoint clock drifted: ${scenario.id} ${step.checkpoint} at ${scheduler.elapsed()}, scripted ${advanced}` + ) + } + recording.checkpoints.push({ + id: step.checkpoint, + observation: { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a structured clone of recorded requests is recorded data. + sender: structuredClone(transport.requests) as unknown as RecordedValue, + payloads: structuredClone(transport.payloads), + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a structured clone of recorded settlements is recorded data. + settlements: structuredClone(settlements) as unknown as RecordedValue, + state: captureValue(mounted.state()), + effects: structuredClone(effects) + } + }) + } + } + if (!recording.checkpoints.length) { + throw new Error(`No checkpoints: ${scenario.id}`) + } + // Why cleanup runs here and not only in `finally`: each checkpoint clones `effects`, so a + // rejection or state write produced by dispose, transport teardown or the final flush landed + // after the recording was built and never reached a golden. Unmount leaks are exactly what + // this oracle exists to catch, so teardown happens on the recorded path and anything it + // observes becomes its own checkpoint. `state` is captured before dispose because the + // operation is gone afterwards. + const beforeCleanup = effects.length + const stateAtCleanup = captureValue(mounted.state()) + await teardown() + if (effects.length !== beforeCleanup) { + recording.checkpoints.push({ + id: 'cleanup', + observation: { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a structured clone of recorded requests is recorded data. + sender: structuredClone(transport.requests) as unknown as RecordedValue, + payloads: structuredClone(transport.payloads), + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a structured clone of recorded settlements is recorded data. + settlements: structuredClone(settlements) as unknown as RecordedValue, + state: stateAtCleanup, + effects: structuredClone(effects) + } + }) + } + return recording + } finally { + try { + if (!cleaned) { + await teardown() + } + } finally { + stopUnhandled() + scheduler.stop() + } + } +} + +export async function runRecordingMutant( + scenario: RecordingScenario, + mutatedMount: MountAdapter, + scheduler: RecordingScheduler, + baseline: Recording, + project: (recording: Recording) => unknown = (recording) => recording +): Promise<{ verdict: 'killed' | 'survived'; recording: Recording }> { + const recording = await runRecording(scenario, mutatedMount, scheduler) + return { + verdict: + JSON.stringify(project(recording)) === JSON.stringify(project(baseline)) + ? 'survived' + : 'killed', + recording + } +} diff --git a/mobile/src/test-support/rpc-recording/scenario-input.ts b/mobile/src/test-support/rpc-recording/scenario-input.ts new file mode 100644 index 00000000000..22dfeb9a5b9 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/scenario-input.ts @@ -0,0 +1,34 @@ +import { readFileSync } from 'node:fs' +import type { RecordingScenario } from './recording-scenario' + +function decode(value: unknown): unknown { + if (Array.isArray(value)) { + return value.map(decode) + } + if (value && typeof value === 'object') { + if (Object.keys(value).length === 1 && '$undefined' in value && value.$undefined === true) { + return undefined + } + return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, decode(entry)])) + } + return value +} +export function readScenarios(path: string): { baseline: string; scenarios: RecordingScenario[] } { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the manifest shape is validated on the next lines. + const input = decode(JSON.parse(readFileSync(path, 'utf8'))) as { + baseline: string + scenarios: RecordingScenario[] + } + if ( + !/^[a-f0-9]{40}$/.test(input.baseline) || + !Array.isArray(input.scenarios) || + !input.scenarios.length + ) { + throw new Error('Invalid recording manifest') + } + const ids = input.scenarios.map((scenario) => scenario.id) + if (new Set(ids).size !== ids.length) { + throw new Error('Duplicate scenario ids') + } + return input +} diff --git a/mobile/src/test-support/rpc-recording/schedule-driver.ts b/mobile/src/test-support/rpc-recording/schedule-driver.ts new file mode 100644 index 00000000000..3aeb11a1513 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/schedule-driver.ts @@ -0,0 +1,127 @@ +import { hoistPreludeCheckpoints, type DivergingScenario } from './prelude-checkpoints' +import type { RecordingScenario, ScenarioStep } from './recording-scenario' + +type Completion = Extract +export const REQUIRED_SCHEDULES = [ + 'forward', + 'reverse', + 'reset-before-first', + 'reset-after-first', + 'reset-before-second', + 'reset-after-second', + 'a-b-a', + 'stale-inflight-cleanup', + 'unmount-remount', + 'blur-retained-route', + 'client-cutover', + 'timeout', + 'disconnect', + 'both-reject-forward', + 'both-reject-reverse', + 'reject-peer-pending' +] as const + +export function siblingSchedules( + base: RecordingScenario, + first: Completion, + second: Completion +): RecordingScenario[] { + const firstIndex = base.steps.indexOf(first) + const secondIndex = base.steps.indexOf(second) + if (firstIndex === -1 || secondIndex < firstIndex) { + throw new Error('Sibling completions must be ordered members of the base scenario') + } + const prefix = base.steps.slice(0, firstIndex).filter((step) => !('checkpoint' in step)) + const suffix = base.steps.slice(secondIndex + 1).filter((step) => !('checkpoint' in step)) + const checkpoint = { checkpoint: 'sibling-pending' } + const rejected = (step: Completion): Completion => ({ + complete: step.complete, + params: step.params, + reject: { message: `${step.complete} rejected`, deliveryUnknown: true } + }) + const variants: Record = { + forward: [first, checkpoint, second], + reverse: [second, checkpoint, first], + 'both-reject-forward': [rejected(first), checkpoint, rejected(second)], + 'both-reject-reverse': [rejected(second), checkpoint, rejected(first)], + 'reject-peer-pending': [rejected(first), checkpoint], + timeout: [{ advance: 30_000 }], + disconnect: [{ action: 'disconnect', id: 'disconnect' }], + 'client-cutover': [{ action: 'cutover', id: 'cutover' }] + } + return Object.entries(variants).map(([schedule, steps]) => ({ + ...base, + id: `${base.id}.${schedule}`, + schedules: [schedule], + steps: [...prefix, ...steps, ...suffix, { checkpoint: 'settled' }] + })) +} + +/** Completions are rebound so a lifecycle boundary can land between a request and its reply. */ +export function bindCompletions(steps: readonly ScenarioStep[]): ScenarioStep[] { + return steps.flatMap((step): ScenarioStep[] => + 'complete' in step + ? [ + { bind: `lifecycle-${step.complete}`, request: step.complete, params: step.params }, + { ...step, complete: `lifecycle-${step.complete}` } + ] + : [step] + ) +} + +export function lifecycleSchedules( + base: RecordingScenario, + action: 'reset' | 'unmount' | 'blur' +): DivergingScenario[] { + const completions = base.steps.flatMap((step, index) => ('complete' in step ? [index] : [])) + return completions.flatMap((index, occurrence) => + ['before', 'after'].map((side) => { + const insertion = index + (side === 'after' ? 1 : 0) + const steps = [...base.steps] + steps.splice( + insertion, + 0, + { action, id: `lifecycle-${action}` }, + { checkpoint: 'lifecycle-boundary' } + ) + if (action === 'unmount') { + steps.push({ action: 'remount', id: 'remount' }, { checkpoint: 'remounted' }) + } + return { + divergence: bindCompletions(base.steps.slice(0, insertion)).length, + scenario: { + ...base, + id: `${base.id}.${action}-${side}-${occurrence + 1}`, + schedules: [`${action}-${side}-${occurrence + 1}`], + steps: bindCompletions(steps) + } + } + }) + ) +} + +export function interruptionSchedules(base: RecordingScenario): RecordingScenario[] { + const completion = base.steps.findLastIndex((step) => 'complete' in step) + if (completion === -1) { + throw new Error('Interruption schedule needs an in-flight request') + } + return hoistPreludeCheckpoints( + base, + ['timeout', 'disconnect', 'cutover'].map((interruption) => ({ + divergence: completion, + scenario: { + ...base, + id: `${base.id}.${interruption}`, + schedules: [interruption], + steps: [ + ...base.steps.slice(0, completion), + interruption === 'timeout' + ? { advance: 30_000 } + : { action: interruption, id: interruption }, + { checkpoint: 'interrupted' }, + ...base.steps.slice(completion) + ] + } + })) + ) +} diff --git a/mobile/src/test-support/rpc-recording/scripted-rpc-transport.ts b/mobile/src/test-support/rpc-recording/scripted-rpc-transport.ts new file mode 100644 index 00000000000..0ae741dfb52 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/scripted-rpc-transport.ts @@ -0,0 +1,182 @@ +import type { ConnectionState, RpcResponse } from '../../transport/types' +import type { RpcClient } from '../../transport/rpc-client' +import { RpcClientRequestTracker } from '../../transport/rpc-client-request-tracker' +import { createStableLogicalRpcClient } from '../../transport/stable-logical-rpc-client' +import { markRpcDeliveryUnknown } from '../../transport/rpc-delivery-ambiguity' +import { + captureArguments, + captureValue, + observeSettlement, + type Settlement +} from './recording-values' +import type { Rejection } from './recording-scenario' + +export class ScriptedRpcTransport { + readonly requests: { + name: string + args: ReturnType + settlement: Settlement + }[] = [] + readonly payloads: { name: string; json: string }[] = [] + readonly client: RpcClient + readonly logical + private counts = new Map() + private bindings = new Map() + private aliases = new Map() + private activeName = '' + private frameCount = 0 + private state: ConnectionState = 'connected' + private listeners = new Set<(state: ConnectionState) => void>() + private rejects = new Map void>() + private tracker = new RpcClientRequestTracker({ + nextId: () => `frame-${++this.frameCount}`, + getState: () => this.state, + waitForConnected: async () => { + if (this.state !== 'connected') { + throw new Error('Scripted transport disconnected') + } + }, + deviceToken: 'recording-device', + sendEncrypted: (value) => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the physical client publishes the frame this transport just serialized. + const payload = value as { id: string; method: string; params: unknown } + const name = this.wireNames.shift() + if (!name) { + throw new Error('Unbound physical request') + } + this.bindings.set(name, { id: payload.id, params: payload.params, completed: false }) + this.payloads.push({ name, json: JSON.stringify(value) }) + return true + } + }) + private wireNames: string[] = [] + + /** `now` is the recording scheduler's virtual clock; every settlement is stamped from it. */ + constructor(private readonly now: () => number = () => 0) { + const session = this.session() + this.logical = createStableLogicalRpcClient(session, 'lan') + this.client = { + ...this.logical, + sendRequest: (...args: Parameters) => { + const occurrence = (this.counts.get(args[0]) ?? 0) + 1 + this.counts.set(args[0], occurrence) + const name = `${args[0]}#${occurrence}` + this.activeName = name + const request = { + name, + args: captureArguments(args), + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a pending settlement has no settledAt yet. + settlement: { status: 'pending', startedAt: this.now() } as Settlement + } + this.requests.push(request) + const promise = this.logical.sendRequest(...args) + observeSettlement(promise, this.now, (state) => { + request.settlement = state + }) + return promise + } + } + } + + private session(): RpcClient { + return { + sendRequest: (...args) => { + const name = this.activeName + this.wireNames.push(name) + return new Promise((resolve, reject) => { + this.rejects.set(name, reject) + this.tracker.sendRequest(...args).then(resolve, reject) + }) + }, + subscribe: () => { + throw new Error('Subscriptions are outside this request-only runner') + }, + updateTerminalSubscriptionViewport: () => {}, + getState: () => this.state, + getReconnectAttempt: () => 0, + getLastConnectedAt: () => 0, + onStateChange: (listener) => { + this.listeners.add(listener) + return () => { + this.listeners.delete(listener) + } + }, + notifyForeground: () => {}, + close: () => { + this.tracker.rejectAll('Connection closed', { deliveryUnknown: true }) + } + } + } + + /** Whether a scripted name names a request that was sent and is still waiting for its reply. */ + outstanding(name: string): boolean { + const binding = this.bindings.get(this.aliases.get(name) ?? name) + return binding !== undefined && !binding.completed + } + + bind(alias: string, name: string, params: unknown): void { + name = this.aliases.get(name) ?? name + const binding = this.bindings.get(name) + if (!binding || this.aliases.has(alias)) { + throw new Error(`Invalid request binding: ${alias}`) + } + if (JSON.stringify(captureValue(binding.params)) !== JSON.stringify(captureValue(params))) { + throw new Error(`Binding params mismatch: ${alias}`) + } + this.aliases.set(alias, name) + } + + complete(name: string, params: unknown, reply: unknown, rejection?: Rejection): void { + const alias = this.aliases.get(name) + const requestedName = alias ?? name + const method = requestedName.split('#')[0] + if ( + !alias && + [...this.bindings].filter(([key, value]) => key.split('#')[0] === method && !value.completed) + .length > 1 + ) { + throw new Error(`Concurrent requests require a logical binding: ${name}`) + } + name = requestedName + const binding = this.bindings.get(name) + if (!binding || binding.completed) { + throw new Error(`Missing or completed request: ${name}`) + } + if (JSON.stringify(captureValue(binding.params)) !== JSON.stringify(captureValue(params))) { + throw new Error(`Request params mismatch: ${name}`) + } + binding.completed = true + if (rejection) { + const error = + rejection.category === 'TypeError' + ? new TypeError(rejection.message) + : new Error(rejection.message) + if (rejection.deliveryUnknown) { + markRpcDeliveryUnknown(error) + } + // Resolve the physical tracker to cancel its deadline before injecting the scripted rejection. + this.rejects.get(name)?.(error) + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the scenario asked for a null result, which is a reply shape a host can send. + this.tracker.resolve({ id: binding.id, ok: true, result: null } as RpcResponse) + } else { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the scenario supplies the reply as JSON; the wire id is the transport’s. + this.tracker.resolve({ ...(reply as object), id: binding.id } as RpcResponse) + } + } + + disconnect(): void { + this.state = 'disconnected' + this.tracker.rejectAll('Connection lost', { deliveryUnknown: true }) + for (const listener of this.listeners) { + listener(this.state) + } + } + + async cutover(): Promise { + await this.logical.migrateTo(this.session(), 'relay') + } + + dispose(): void { + this.logical.close() + } +} diff --git a/mobile/src/test-support/rpc-recording/settings-mount-adapters.ts b/mobile/src/test-support/rpc-recording/settings-mount-adapters.ts new file mode 100644 index 00000000000..f453c16ef13 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/settings-mount-adapters.ts @@ -0,0 +1,187 @@ +import type { MountAdapter } from './recording-scenario' +import { hookMount } from './hook-mount' +import { observableModel, projectObservable } from './observable-model' +import { operationModuleLoader } from './operation-module-loader' + +export function settingsMountAdapters( + modules: ReturnType +): Record { + return { + 'settings.bot-overrides': ({ client }) => { + const useOverrides = modules.load( + 'mobile/src/session/use-pr-bot-author-overrides.ts' + ).usePRBotAuthorOverrides + let state: ReadonlySet = new Set() + let revision = 1 + const hook = hookMount(() => { + state = useOverrides(client, 'connected', revision) + }) + return { + action(name) { + if (name === 'mount' || name === 'remount') { + return hook.mount() + } + if (name === 'unmount') { + return hook.unmount() + } + if (name === 'reset') { + revision++ + return hook.update() + } + if (name === 'blur') { + return + } + throw new Error(`Unknown overrides action: ${name}`) + }, + state: () => [...state], + dispose: hook.unmount + } + }, + 'settings.workspace-context': ({ client }) => { + const useContext = modules.load< + typeof import('../../components/use-new-workspace-runtime-context') + >('mobile/src/components/use-new-workspace-runtime-context.ts').useNewWorkspaceRuntimeContext + let state: ReturnType + let visible = true + const hook = hookMount(() => { + state = useContext(client, visible, 'host-1') + }) + return { + action(name) { + if (name === 'mount' || name === 'remount') { + return hook.mount() + } + if (name === 'unmount') { + return hook.unmount() + } + if (name === 'blur') { + visible = false + return hook.update() + } + if (name === 'reset') { + visible = true + return hook.update() + } + throw new Error(`Unknown context action: ${name}`) + }, + state: () => ({ + settings: state?.runtimeSettings, + trust: state?.trustedOrcaHooks, + providers: state?.availableProviders + }), + dispose: hook.unmount + } + }, + 'settings.home-providers': (context) => { + const load = modules.load( + 'mobile/src/home/mobile-home-host-requests.ts' + ).fetchMobileHomeTaskProviders + let providers: unknown = {} + let disposed = false + return { + action(name) { + if (name === 'unmount') { + disposed = true + return + } + load( + context.client, + 'host-1', + (update: (value: unknown) => unknown) => { + providers = update(providers) + context.effect('providers', providers) + }, + () => disposed + ) + }, + state: () => providers, + dispose: () => { + disposed = true + } + } + }, + 'settings.resume-metadata': ({ client }) => { + const load = modules.load( + 'mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx' + ).loadMobileResumeMetadata + return { action: () => load(client), state: () => ({}), dispose: () => {} } + }, + 'settings.repo-metadata': (context) => { + const useMetadata = modules.load( + 'mobile/src/host-screen/use-host-repo-metadata.ts' + ).useHostRepoMetadata + const state = observableModel(context, { + clientRef: { current: context.client }, + fetchRepoMetadataInFlightRef: { current: new Set() }, + fetchRepoMetadataPendingRef: { current: new Set() }, + repoMetadataFetchedAtRef: { current: 0 } + }) + let load: ReturnType + const hook = hookMount(() => { + load = useMetadata({ + client: context.client, + connState: 'connected', + hostId: 'host-1', + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the recorder supplies only the members the hook reads. + state: state as unknown as Parameters[0]['state'] + }) + }) + return { + action(name) { + if (name === 'mount') { + return hook.mount() + } + return load({ force: name !== 'load-cached' }) + }, + state: () => + projectObservable( + Object.fromEntries(Object.entries(state).filter(([key]) => !key.endsWith('Ref'))) + ), + dispose: hook.unmount + } + }, + 'settings.task-hydration': (context) => { + const useHydration = modules.load< + typeof import('../../tasks/use-mobile-tasks-runtime-hydration') + >('mobile/src/tasks/use-mobile-tasks-runtime-hydration.tsx').useMobileTasksRuntimeHydration + const model = observableModel(context, { + client: context.client, + connState: 'connected', + defaultLinearTeamSelectionRef: { current: null }, + defaultRepoSelectionRef: { current: null }, + repoSelectionHydratedRef: { current: false }, + taskResumeRef: { current: {} }, + runtimeTaskSettings: {}, + taskStateHydrated: false, + provider: 'github', + repoList: { state: { status: 'loading' } }, + repos: [], + requestedTaskSource: undefined, + resetGitHubItemsState: () => context.effect('reset-items', null), + resetWorkspaceCreateState: () => context.effect('reset-workspace', null), + visibleProviders: ['github'] + }) + const hook = hookMount(() => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the recorder supplies only the members the hook reads. + useHydration(model as unknown as Parameters[0]) + }) + return { + action(name) { + if (name === 'mount' || name === 'remount') { + return hook.mount() + } + if (name === 'unmount') { + return hook.unmount() + } + throw new Error(`Unknown hydration action: ${name}`) + }, + state: () => + projectObservable({ + settings: model.runtimeTaskSettings, + hydrated: model.taskStateHydrated + }), + dispose: hook.unmount + } + } + } +} diff --git a/mobile/src/test-support/rpc-recording/source-control-mount-adapters.ts b/mobile/src/test-support/rpc-recording/source-control-mount-adapters.ts new file mode 100644 index 00000000000..81d2db75eb1 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/source-control-mount-adapters.ts @@ -0,0 +1,125 @@ +import type { MountAdapter } from './recording-scenario' +import { operationModuleLoader } from './operation-module-loader' + +const WORKTREE = 'repo42::/p' + +/** + * Source-control senders mounted as plain functions: each one is an exported async call that + * takes a client, so no React host is needed and the recorded state is the function's own answer. + */ +export function sourceControlMountAdapters( + modules: ReturnType +): Record { + return { + 'source-control.branch-base-ref': ({ client }) => { + const resolve = modules.load( + 'mobile/src/source-control/mobile-branch-base-ref.ts' + ).resolveMobileBranchCompareBaseRef + let baseRef: unknown = 'unresolved' + return { + action: (_name, args) => + resolve(client, String(args.workspace ?? WORKTREE)).then((value) => { + baseRef = value + return value + }), + state: () => ({ baseRef }), + dispose: () => {} + } + }, + 'source-control.git-history': ({ client }) => { + const history = modules.load( + 'mobile/src/source-control/mobile-git-history.ts' + ) + let rows: unknown = 'unloaded' + return { + action: () => + history.fetchMobileGitHistory(client, WORKTREE).then((result) => { + rows = history.mapMobileCommitRows(result, Date.now()) + return rows + }), + state: () => ({ rows }), + dispose: () => {} + } + }, + 'source-control.commit-message': ({ client }) => { + const ai = modules.load( + 'mobile/src/source-control/mobile-commit-message-ai.ts' + ) + let generated: unknown = 'ungenerated' + return { + action(name) { + if (name === 'cancel') { + return ai.cancelMobileCommitMessage(client, WORKTREE) + } + return ai.requestMobileCommitMessage(client, WORKTREE).then((result) => { + generated = result + return result + }) + }, + state: () => ({ generated }), + dispose: () => {} + } + }, + 'source-control.pr-link': ({ client }) => { + const link = modules.load( + 'mobile/src/source-control/mobile-pr-link.ts' + ) + let outcome: unknown = 'unlinked' + let linkedPR: unknown = 'unread' + return { + action(name) { + if (name === 'read') { + return link.fetchWorktreeLinkedPR(client, WORKTREE).then((value) => { + linkedPR = value + return value + }) + } + const request = + name === 'unlink' + ? link.unlinkMobilePr(client, WORKTREE) + : name === 'link-review' + ? link.linkMobileHostedReview(client, WORKTREE, 'gitlab', 12, { + baseRef: ' origin/release ' + }) + : link.linkMobilePr(client, WORKTREE, 12) + return request.then((value) => { + outcome = value + return value + }) + }, + state: () => ({ outcome, linkedPR }), + dispose: () => {} + } + }, + 'source-control.session-diff-reveal': ({ client }) => { + const reveal = modules.load< + typeof import('../../source-control/reveal-mobile-source-control-session-diff') + >( + 'mobile/src/source-control/reveal-mobile-source-control-session-diff.ts' + ).revealMobileSourceControlSessionDiff + let result: unknown = 'unrevealed' + let current = true + return { + action(name, args) { + if (name === 'cancel') { + current = false + return + } + return reveal({ + client, + worktreeId: WORKTREE, + relativePath: 'src/app.ts', + tabMode: args.tabMode === 'edit' ? 'edit' : 'diff', + staged: args.staged === true, + isCurrent: () => current + }).then((value) => { + result = value + return value + }) + }, + state: () => ({ result }), + dispose: () => {} + } + } + } +} diff --git a/mobile/src/test-support/rpc-recording/unhandled-recording.ts b/mobile/src/test-support/rpc-recording/unhandled-recording.ts new file mode 100644 index 00000000000..a4bd0e033d4 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/unhandled-recording.ts @@ -0,0 +1,23 @@ +import { captureError } from './recording-values' + +let active = false + +// Main's detached effects can reject without a caller promise; record that observable failure too. +export function recordUnhandledRejections( + effect: (name: string, value: unknown) => void +): () => void { + if (active) { + throw new Error('Recordings must run sequentially in each process') + } + active = true + const previous = process.rawListeners('unhandledRejection') + process.removeAllListeners('unhandledRejection') + process.on('unhandledRejection', (error) => effect('unhandled-rejection', captureError(error))) + return () => { + active = false + process.removeAllListeners('unhandledRejection') + for (const listener of previous) { + process.on('unhandledRejection', listener) + } + } +} diff --git a/mobile/src/test-support/rpc-recording/vitest-recording-scheduler.ts b/mobile/src/test-support/rpc-recording/vitest-recording-scheduler.ts new file mode 100644 index 00000000000..d7bab0334d2 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/vitest-recording-scheduler.ts @@ -0,0 +1,64 @@ +import { act } from 'react-test-renderer' +import { vi } from 'vitest' +import type { RecordingScheduler } from './recording-scenario' + +const RECORDING_EPOCH = new Date('2026-01-01T00:00:00Z') + +export function vitestRecordingScheduler(): RecordingScheduler { + async function flush() { + await act(async () => { + // Drain promise continuations and due timers without advancing request deadlines. + await vi.advanceTimersByTimeAsync(0) + }) + } + return { + start() { + vi.useFakeTimers({ + toFake: [ + 'Date', + 'setTimeout', + 'clearTimeout', + 'setInterval', + 'clearInterval', + 'performance' + ] + }) + vi.setSystemTime(RECORDING_EPOCH) + let seed = 1 + const random = () => { + seed = (Math.imul(seed, 1664525) + 1013904223) >>> 0 + return seed / 4294967296 + } + vi.spyOn(Math, 'random').mockImplementation(random) + if (globalThis.crypto !== undefined) { + let id = 0 + vi.spyOn(globalThis.crypto, 'randomUUID').mockImplementation( + () => `00000000-0000-4000-8000-${(++id).toString(16).padStart(12, '0')}` + ) + } + if (globalThis.crypto !== undefined) { + vi.spyOn(globalThis.crypto, 'getRandomValues').mockImplementation((array) => { + if (array) { + const bytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength) + for (let i = 0; i < bytes.length; i++) { + bytes[i] = Math.floor(random() * 256) + } + } + return array + }) + } + }, + flush, + elapsed: () => Date.now() - RECORDING_EPOCH.getTime(), + advance: async (ms) => { + await act(async () => { + await vi.advanceTimersByTimeAsync(ms) + }) + }, + stop() { + vi.clearAllTimers() + vi.useRealTimers() + vi.restoreAllMocks() + } + } +} diff --git a/mobile/src/test-support/rpc-recording/workspace-settings-mounts.ts b/mobile/src/test-support/rpc-recording/workspace-settings-mounts.ts new file mode 100644 index 00000000000..d37c3d40935 --- /dev/null +++ b/mobile/src/test-support/rpc-recording/workspace-settings-mounts.ts @@ -0,0 +1,120 @@ +import type { MountAdapter } from './recording-scenario' +import { hookMount, performHookAction } from './hook-mount' +import { observableModel, projectObservable } from './observable-model' +import { operationModuleLoader } from './operation-module-loader' + +export function workspaceSettingsMounts( + modules: ReturnType +): Record { + return { + 'settings.workspace-submit': (context) => { + const useSubmit = modules.load< + typeof import('../../components/use-new-workspace-create-submit') + >('mobile/src/components/use-new-workspace-create-submit.ts').useNewWorkspaceCreateSubmit + const model = observableModel(context, { + client: context.client, + selectedRepo: { id: 'repo-1', displayName: 'Repo' }, + selectedAgent: { id: 'claude', label: 'Claude' }, + runtimeSettings: { disabledTuiAgents: ['claude'] }, + detectedAgentIds: new Set(['codex']), + sshGate: { requiresConnection: false }, + composer: { name: 'recorded', createSelection: null, isNameAutoManaged: false }, + note: '', + retiredWorktreeNames: {}, + setupCommand: null, + setupTrust: null, + setupRunPolicy: 'never', + setupDecisionChoice: null, + runSetup: false, + trustedOrcaHooks: {}, + getWorktreeCreateCutoverSupport: async () => false, + transitionDrawer: (view: unknown) => context.effect('drawer', view), + onCreated: (id: unknown, name: unknown) => context.effect('created', { id, name }), + onClose: () => context.effect('close', null) + }) + let state: ReturnType + const hook = hookMount(() => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the recorder supplies only the members the hook reads. + state = useSubmit(model as unknown as Parameters[0]) + }) + return { + action(name) { + if (name === 'mount') { + return hook.mount() + } + if (name === 'submit') { + return performHookAction(() => state.create()) + } + throw new Error(`Unknown submit action: ${name}`) + }, + state: () => + projectObservable({ + creating: state?.creating, + settings: model.runtimeSettings, + error: model.error + }), + dispose: hook.unmount + } + }, + 'settings.task-workspace': (context) => { + const useCreate = modules.load< + typeof import('../../tasks/use-mobile-tasks-workspace-create-actions') + >( + 'mobile/src/tasks/use-mobile-tasks-workspace-create-actions.tsx' + ).useMobileTasksWorkspaceCreateActions + const model = observableModel(context, { + client: context.client, + hostId: 'host-1', + tasksSupported: true, + taskStateHydrated: true, + runtimeTaskSettings: { disabledTuiAgents: ['claude'] }, + trustedOrcaHooks: {}, + workspaceDetectedAgentIds: new Set(['codex']), + workspaceLastAutoName: '', + ensureWorkspaceSshReady: async () => {}, + getWorkspaceTargetRepo: () => ({ + id: 'repo-1', + displayName: 'Repo', + connectionId: 'ssh-1' + }), + resolveCreateSetupDecision: async () => ({ + kind: 'prompt', + command: 'setup', + source: 'repo' + }), + router: { push: (value: unknown) => context.effect('navigation', value) } + }) + let actions: ReturnType + const hook = hookMount(() => { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the recorder supplies only the members the hook reads. + actions = useCreate(model as unknown as Parameters[0]) + }) + return { + action(name) { + if (name === 'mount') { + return hook.mount() + } + if (name === 'submit') { + return actions.createWorkspace( + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the scenario supplies the action item as JSON, not as a typed model. + { key: 'linear:1', provider: 'linear', source: { id: 'issue-1' } } as Parameters< + typeof actions.createWorkspace + >[0], + undefined, + undefined, + 'claude' + ) + } + throw new Error(`Unknown task workspace action: ${name}`) + }, + state: () => + projectObservable({ + settings: model.runtimeTaskSettings, + error: model.error, + creating: model.creatingKey + }), + dispose: hook.unmount + } + } + } +} diff --git a/mobile/src/transport/rpc-client-delivery-ambiguity.test.ts b/mobile/src/transport/rpc-client-delivery-ambiguity.test.ts index 5cdaf75b945..29456c2eaa1 100644 --- a/mobile/src/transport/rpc-client-delivery-ambiguity.test.ts +++ b/mobile/src/transport/rpc-client-delivery-ambiguity.test.ts @@ -1,6 +1,11 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { connect } from './rpc-client' import { isRpcDeliveryUnknown } from './rpc-delivery-ambiguity' +import { + createStableLogicalRpcClient, + isLogicalClientCutoverError, + LogicalClientCutoverError +} from './stable-logical-rpc-client' vi.mock('./e2ee', () => ({ generateKeyPair: () => ({ @@ -72,7 +77,7 @@ function hasSentRequest(socket: MockWebSocket, method: string): boolean { function connectAuthenticated(): { client: ReturnType; socket: MockWebSocket } { const client = connect('ws://desktop.invalid', 'token', 'server-key') - const socket = mockSockets[0]! + const socket = mockSockets[mockSockets.length - 1]! socket.open() socket.receive(JSON.stringify({ type: 'e2ee_ready' })) socket.receive('encrypted:{"type":"e2ee_authenticated"}') @@ -94,6 +99,52 @@ describe('mobile rpc-client delivery ambiguity marking', () => { globalThis.WebSocket = originalWebSocket }) + it.each([true, false])( + 'preserves physical delivery evidence at the cutover caller (sent=%s)', + async (sent) => { + const physical = sent + ? connectAuthenticated() + : { + client: connect('ws://desktop.invalid', 'token', 'server-key'), + socket: mockSockets[0]! + } + const client = createStableLogicalRpcClient(physical.client, 'lan') + const replacement = connectAuthenticated() + const requestError = client + .sendRequest('worktree.create', { name: 'new' }) + .catch((error: unknown) => error) + await Promise.resolve() + expect(hasSentRequest(physical.socket, 'worktree.create')).toBe(sent) + + await client.migrateTo(replacement.client, 'relay') + + const error = await requestError + expect(isLogicalClientCutoverError(error)).toBe(true) + expect(isRpcDeliveryUnknown(error)).toBe(sent) + expect(error).toBeInstanceOf(LogicalClientCutoverError) + expect(isRpcDeliveryUnknown(error instanceof Error ? error.cause : null)).toBe(sent) + expect(hasSentRequest(replacement.socket, 'worktree.create')).toBe(false) + expect( + physical.socket.sent.filter((payload) => payload.includes('worktree.create')) + ).toHaveLength(sent ? 1 : 0) + client.close() + } + ) + + it('recognizes a cutover by class even when its message changes', () => { + const error = new LogicalClientCutoverError() + error.message = 'wrapped migration' + expect(isLogicalClientCutoverError(error)).toBe(true) + }) + + it('recognizes a cutover message from another bundle copy', () => { + expect(isLogicalClientCutoverError(new Error('RPC interrupted by connection migration'))).toBe( + true + ) + expect(isLogicalClientCutoverError(new Error('Client closed'))).toBe(false) + expect(isLogicalClientCutoverError('RPC interrupted by connection migration')).toBe(false) + }) + it('marks in-flight requests as delivery-unknown when the socket drops', async () => { const { client, socket } = connectAuthenticated() const requestError = client.sendRequest('terminal.send', { terminal: 't' }).then( diff --git a/mobile/src/transport/rpc-client.ts b/mobile/src/transport/rpc-client.ts index 38941483c4d..05fdbbac8fa 100644 --- a/mobile/src/transport/rpc-client.ts +++ b/mobile/src/transport/rpc-client.ts @@ -32,6 +32,19 @@ export type RpcClient = UnvalidatedRpcRequestPort & { getLastInboundAt?: () => number | null onStateChange: (listener: (state: ConnectionState) => void) => () => void notifyForeground: (reason?: ForegroundNudgeReason) => void + /** + * Must settle every pending `sendRequest` promise before returning. + * + * `StableLogicalRpcClient.migrateTo` no longer rejects pendings itself — the physical + * sender is the only layer that knows whether a request reached the wire, so + * `previous.close()` is the sole settlement path for the retiring generation. An + * implementation that leaves a request pending strands its caller for good. + * + * Requests that did reach the wire must reject with a delivery-unknown error + * (`markRpcDeliveryUnknown`), since the host may already have executed them. Pinned + * against the real clients in `rpc-client-delivery-ambiguity.test.ts` (direct) and + * `mobile-relay-rpc-session.test.ts` (relay) — a new implementation needs its own case. + */ close: () => void } diff --git a/mobile/src/transport/rpc-reader-payload.ts b/mobile/src/transport/rpc-reader-payload.ts new file mode 100644 index 00000000000..07cdebc16a5 --- /dev/null +++ b/mobile/src/transport/rpc-reader-payload.ts @@ -0,0 +1,27 @@ +import type { RpcCompatibleReader, RpcReadResult } from './rpc-operation-contract' + +const NOTHING_DROPPED = { droppedPaths: [], droppedCount: 0 } as const + +/** A reader answer for a payload no schema rejects: the call site it replaces cast, not parsed. */ +export function rpcReadUnchecked( + variant: Variant, + value: Value +): RpcReadResult { + return { compatible: true, variant, value, salvage: NOTHING_DROPPED } +} + +/** + * One property off a reply payload, preserving the native property-read exception on + * null/undefined that `(response.result as T).field` threw before the read moved here. + */ +export function rpcPayloadMember(raw: unknown, key: string): unknown { + const boxed: Record | null | undefined = raw == null ? raw : Object(raw) + return boxed![key] +} + +/** The whole payload, unchecked. The common shape for a reply a call site only re-typed. */ +export function rpcUncheckedPayloadReader( + variant: Variant +): RpcCompatibleReader { + return (raw) => rpcReadUnchecked(variant, raw) +} diff --git a/mobile/src/transport/rpc-refusal-message.ts b/mobile/src/transport/rpc-refusal-message.ts new file mode 100644 index 00000000000..ceb17792746 --- /dev/null +++ b/mobile/src/transport/rpc-refusal-message.ts @@ -0,0 +1,25 @@ +/** + * A refused operation's message, or the screen's own copy when the host sent none. + * + * Call sites spelled this as `response.error?.message || fallback`. Once the refusal arrives as + * the acceptance policy's thrown Error, the `||` has to live somewhere — and it must not also + * cover a transport rejection, whose message main surfaced verbatim, empty string included. So + * a migrated call site keeps two catches where it had two paths, and only the refusal one calls + * this. + */ +export function refusedRpcMessageOrFallback(error: unknown, fallback: string): string { + return (error instanceof Error ? error.message : '') || fallback +} + +/** + * An error a host reported inside an accepted reply, or the screen's copy when it sent none. + * + * Exactly `result?.error || fallback`, including for a truthy non-string: main passed that value + * through under a `string` annotation, and a downstream `.replace` then threw. Stringifying it + * here would be an improvement, but an unannounced one inside a migration whose contract is that + * no behaviour changes — so the pass-through stays and the latent throw is ticketed separately. + */ +export function hostReplyErrorTextOrFallback(value: unknown, fallback: string): string { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: reproduces main's own annotation of an unvalidated host field. + return ((value as string | undefined) || fallback) as string +} diff --git a/mobile/src/transport/settings-read-operations.test.ts b/mobile/src/transport/settings-read-operations.test.ts index 3a81da9942f..07f4ff771d4 100644 --- a/mobile/src/transport/settings-read-operations.test.ts +++ b/mobile/src/transport/settings-read-operations.test.ts @@ -8,7 +8,8 @@ import { settingsRead, optionalSettingsRead, botOverridesRead, - newTabSettingsRead + newTabSettingsRead, + terminalCopyTrimsGutterRead } from './settings-read-operations' import type { RpcResponse } from './types' @@ -91,6 +92,24 @@ describe('settings historical acceptance', () => { expect(botOverridesRead.interpret(empty)).toEqual({ accepted: true, value: [] }) }) + it('reads the gutter-trim preference, treating an older host as opted in', async () => { + const off = await terminalCopyTrimsGutterRead.request( + replyWith(success({ settings: { terminalCopyTrimsGutter: false } })) + ) + expect(terminalCopyTrimsGutterRead.interpret(off)).toEqual({ accepted: true, value: false }) + const on = await terminalCopyTrimsGutterRead.request( + replyWith(success({ settings: { terminalCopyTrimsGutter: true } })) + ) + expect(terminalCopyTrimsGutterRead.interpret(on)).toEqual({ accepted: true, value: true }) + // A host predating the setting sends no key; the desktop default is on. + const absent = await terminalCopyTrimsGutterRead.request(replyWith(success({ settings: {} }))) + expect(terminalCopyTrimsGutterRead.interpret(absent)).toEqual({ accepted: true, value: true }) + const empty = await terminalCopyTrimsGutterRead.request(replyWith(success(null))) + expect(terminalCopyTrimsGutterRead.interpret(empty)).toEqual({ accepted: true, value: true }) + const refused = await terminalCopyTrimsGutterRead.request(replyWith(refusal())) + expect(terminalCopyTrimsGutterRead.interpret(refused)).toEqual({ accepted: false }) + }) + it('does not read a stale payload until its caller permits interpretation', async () => { const read = vi.fn(() => ({})) const reply = await settingsRead.request( diff --git a/mobile/src/transport/settings-read-operations.ts b/mobile/src/transport/settings-read-operations.ts index f33471dcaf2..c98c87798b3 100644 --- a/mobile/src/transport/settings-read-operations.ts +++ b/mobile/src/transport/settings-read-operations.ts @@ -82,6 +82,30 @@ export const newTabSettingsRead = bindDeferredRpcOperation( }) ) +const copyTrimsGutterReader: RpcCompatibleReader = (raw) => { + const settings = raw == null ? undefined : settingsMember(raw) + const trims: unknown = + settings == null ? undefined : Reflect.get(Object(settings), 'terminalCopyTrimsGutter') + return { + compatible: true, + variant: 'copy-trims-gutter', + // Why `!== false`: a host predating the setting sends no key, and the + // desktop default is on, so absence must read as on. + value: trims !== false, + salvage: { droppedPaths: [], droppedCount: 0 } + } +} + +export const terminalCopyTrimsGutterRead = bindDeferredRpcOperation( + defineRpcOperation({ + name: 'settings.terminal-copy-trims-gutter-or-skip', + method: 'settings.get', + acceptance: 'success-result-or-skip', + barrier: 'after-caller-barrier', + read: copyTrimsGutterReader + }) +) + export const botOverridesRead = bindDeferredRpcOperation( defineRpcOperation({ name: 'settings.bot-logins-or-skip', diff --git a/mobile/src/transport/stable-logical-rpc-client.test.ts b/mobile/src/transport/stable-logical-rpc-client.test.ts index cbbf01ada2a..6a22b3654a2 100644 --- a/mobile/src/transport/stable-logical-rpc-client.test.ts +++ b/mobile/src/transport/stable-logical-rpc-client.test.ts @@ -90,6 +90,7 @@ describe('stable logical RPC client', () => { const nextSession = new FakeSession('connecting') const pending = deferred() oldSession.sendRequest.mockReturnValue(pending.promise) + oldSession.close.mockImplementation(() => pending.reject(new Error('Client closed'))) nextSession.sendRequest.mockResolvedValue(success('next')) const client = createStableLogicalRpcClient(oldSession, 'lan') const stream = vi.fn() diff --git a/mobile/src/transport/stable-logical-rpc-client.ts b/mobile/src/transport/stable-logical-rpc-client.ts index 3a896af6f5b..769481aa80c 100644 --- a/mobile/src/transport/stable-logical-rpc-client.ts +++ b/mobile/src/transport/stable-logical-rpc-client.ts @@ -7,12 +7,16 @@ import { import { waitForAuthenticated } from './replacement-session-authentication' import { projectMobileRpcRequestParams } from './mobile-rpc-request-projection' import { LogicalClientConnectionPath } from './logical-client-connection-path' +import { isRpcDeliveryUnknown, markRpcDeliveryUnknown } from './rpc-delivery-ambiguity' export type MobileConnectionPath = 'lan' | 'tailscale' | 'relay' export class LogicalClientCutoverError extends Error { - constructor() { - super('RPC interrupted by connection migration') + constructor(cause?: unknown) { + super('RPC interrupted by connection migration', { cause }) + if (isRpcDeliveryUnknown(cause)) { + markRpcDeliveryUnknown(this) + } } } @@ -33,10 +37,6 @@ type SubscriptionRecord = { cancelled: boolean } -type PendingRequest = { - reject: (error: Error) => void -} - export type StableLogicalRpcClient = RpcClient & { migrateTo( session: RpcClient, @@ -75,7 +75,6 @@ export function createStableLogicalRpcClient( let nextSubscriptionId = 0 let activeStateUnsubscribe: (() => void) | null = null const subscriptions = new Map() - const pendingRequests = new Set() const stateListeners = new Set<(state: ConnectionState) => void>() let state = initialSession.getState() const connectionPath = new LogicalClientConnectionPath(() => state === 'connected') @@ -90,22 +89,23 @@ export function createStableLogicalRpcClient( if (suspended) { return Promise.reject(new Error('Client suspended')) } + const requestGeneration = generation const session = activeSession return new Promise((resolve, reject) => { - const pending = { reject } - pendingRequests.add(pending) void session .sendRequest(method, projectMobileRpcRequestParams(method, params), options) .then( (response) => { - pendingRequests.delete(pending) // A correlated response is definitive even if close/cutover won the // callback race after the physical promise had already settled. resolve(response) }, (error: unknown) => { - pendingRequests.delete(pending) - reject(error) + // Why: the retiring physical session settles this, so keep its error as the + // cause — it is the only evidence of whether the frame reached the wire. + reject( + requestGeneration !== generation ? new LogicalClientCutoverError(error) : error + ) } ) }) @@ -260,15 +260,12 @@ export function createStableLogicalRpcClient( suspended = false previousStateUnsubscribe?.() bindActiveState(nextSession, nextGeneration) - for (const pending of pendingRequests) { - pending.reject(new LogicalClientCutoverError()) - } - pendingRequests.clear() state = nextSession.getState() connectionPath.clearAfterConnected() for (const listener of stateListeners) { listener(state) } + // Only the physical sender knows whether a pending request reached the wire. previous.close() }, diff --git a/mobile/src/transport/unvalidated-rpc-request-port-inventory.ts b/mobile/src/transport/unvalidated-rpc-request-port-inventory.ts index dba48bbf3c8..3e09655c5a1 100644 --- a/mobile/src/transport/unvalidated-rpc-request-port-inventory.ts +++ b/mobile/src/transport/unvalidated-rpc-request-port-inventory.ts @@ -37,7 +37,11 @@ export const UNVALIDATED_RPC_REQUEST_PORT_OWNERS: readonly UnvalidatedRpcRequest // The typed boundary itself — the one module that turns a reply into a declared type. { file: 'src/transport/rpc-operation.ts', references: 5 }, // Forwards the port across a physical-client cutover. - { file: 'src/transport/stable-logical-rpc-client.ts', references: 2 } + { file: 'src/transport/stable-logical-rpc-client.ts', references: 2 }, + // Names the port as the recording oracle's sender contract; a non-test file for the same reason. + { file: 'src/test-support/rpc-recording/recording-scenario.ts', references: 1 }, + // Scripts the port for the recording oracle, over the real tracker and logical client. + { file: 'src/test-support/rpc-recording/scripted-rpc-transport.ts', references: 5 } ] /** Call sites awaiting migration to a typed operation. Grouped by the feature area that owns them. */ @@ -148,21 +152,12 @@ export const UNVALIDATED_RPC_REQUEST_PORT_PENDING: readonly UnvalidatedRpcReques // src/settings/ — notification display probe { file: 'src/settings/notification-display-test.tsx', references: 1 }, - // src/source-control/ — source control: review, commit, branch - { file: 'src/source-control/mobile-branch-base-ref.ts', references: 3 }, - { file: 'src/source-control/mobile-commit-message-ai.ts', references: 4 }, - { file: 'src/source-control/mobile-git-history.ts', references: 2 }, - { file: 'src/source-control/mobile-hosted-review-create-intent-runner.ts', references: 1 }, - { file: 'src/source-control/mobile-hosted-review-create-intent.ts', references: 3 }, - { file: 'src/source-control/mobile-hosted-review-git-preparation.ts', references: 6 }, - { file: 'src/source-control/mobile-hosted-review-remote-prerequisite.ts', references: 1 }, - { file: 'src/source-control/mobile-hosted-review-service.ts', references: 8 }, - { file: 'src/source-control/mobile-pr-link.ts', references: 8 }, - { file: 'src/source-control/MobileGitHistoryList.tsx', references: 1 }, - { file: 'src/source-control/reveal-mobile-source-control-session-diff.ts', references: 2 }, + // src/source-control/ — one dynamic dispatcher left; the other 13 files migrated in step 4. + // Its single reference multiplexes git.commit, git.status, git.upstreamStatus, git.fetch, + // git.pull, git.push and every `{ method, params }` action step five other hooks hand it, so + // it cannot drop below one until that step model is typed. See mobile-git-read-operations.ts + // and mobile-git-mutation-operations.ts for the operations the rest of the domain now sends. { file: 'src/source-control/use-mobile-git-requests.ts', references: 1 }, - { file: 'src/source-control/use-mobile-source-control-loaders.ts', references: 2 }, - { file: 'src/source-control/use-mobile-source-control-openers.ts', references: 3 }, // src/tasks/ — task lists, filters and mutations { file: 'src/tasks/composer-source-base-resolve.ts', references: 2 }, diff --git a/mobile/src/worktree/home-host-worktree-fetch.test.ts b/mobile/src/worktree/home-host-worktree-fetch.test.ts index 5799de96366..6238554769a 100644 --- a/mobile/src/worktree/home-host-worktree-fetch.test.ts +++ b/mobile/src/worktree/home-host-worktree-fetch.test.ts @@ -39,7 +39,11 @@ function fakeSession(): FakeSession { getLastConnectedAt: () => null, onStateChange: () => () => {}, notifyForeground: () => {}, - close: () => {} + close: () => { + for (const settle of pending.splice(0)) { + settle(new Error('Client closed')) + } + } } } return fake diff --git a/package.json b/package.json index ca0b2eca73c..e48079f8a1c 100644 --- a/package.json +++ b/package.json @@ -170,6 +170,7 @@ "@floating-ui/dom": "1.7.6", "@linear/sdk": "^82.1.0", "@parcel/watcher": "^2.5.6", + "@streamparser/json": "0.0.26", "@xterm/addon-serialize": "0.15.0-beta.300", "@xterm/headless": "6.1.0-beta.302", "agent-browser": "~0.27.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d86a167957..586c9449212 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -137,6 +137,9 @@ importers: '@parcel/watcher': specifier: ^2.5.6 version: 2.5.6 + '@streamparser/json': + specifier: 0.0.26 + version: 0.0.26 '@xterm/addon-serialize': specifier: 0.15.0-beta.300 version: 0.15.0-beta.300(patch_hash=851eac3d75e6d8c013b9f4c053e61d824b23965cb19ecc28e335e05059f3a294)(@xterm/xterm@6.1.0-beta.303(patch_hash=1f36ce689bc50c703ae09aeda0e064f107e18e4a5ecba19e746fa5edc4b02ef4)) @@ -2675,6 +2678,9 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@streamparser/json@0.0.26': + resolution: {integrity: sha512-46597LNFI+MFdUnzX2QJWwmdTRdq0XVD+vVNJTtGVzIrnCuhG9pFo1OAzbNBqci8UJgk/X5KJZ6LcV+y7PTuDQ==} + '@swc/core-darwin-arm64@1.15.46': resolution: {integrity: sha512-IsISIT22EfktVJrlvIpnAxG2u/A9aob9l99HMlx80x72WlFmFPk1V3UhkEzx86eJP8hw049KTFv/RISho2cq2Q==} engines: {node: '>=10'} @@ -9010,6 +9016,8 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@streamparser/json@0.0.26': {} + '@swc/core-darwin-arm64@1.15.46': optional: true diff --git a/src/cli/specs/orchestration.test.ts b/src/cli/specs/orchestration.test.ts index cd69aa50708..cea858a9cfd 100644 --- a/src/cli/specs/orchestration.test.ts +++ b/src/cli/specs/orchestration.test.ts @@ -64,7 +64,7 @@ describe('orchestration check command spec', () => { expect(checkSpec?.notes).toEqual( expect.arrayContaining([ - '--types is the wake condition for --wait; a returned Delivery is always the whole FIFO batch, so it is never filtered by type. Only --peek and --all filter their rows.' + '--types is the wake condition for --wait; a returned Delivery is always the whole FIFO batch, so it is never filtered by type. Without --wait it has no effect on consuming checks. Only --peek and --all filter their rows.' ]) ) }) diff --git a/src/cli/specs/orchestration.ts b/src/cli/specs/orchestration.ts index d75123ee6b7..458afa2e525 100644 --- a/src/cli/specs/orchestration.ts +++ b/src/cli/specs/orchestration.ts @@ -111,9 +111,9 @@ export const ORCHESTRATION_COMMAND_SPECS: CommandSpec[] = [ ], notes: [ 'On Windows PowerShell, quote comma-separated type filters, e.g. --types "worker_done,escalation".', - '--types is the wake condition for --wait; a returned Delivery is always the whole FIFO batch, so it is never filtered by type. Only --peek and --all filter their rows.', + '--types is the wake condition for --wait; a returned Delivery is always the whole FIFO batch, so it is never filtered by type. Without --wait it has no effect on consuming checks. Only --peek and --all filter their rows.', '--format renders the returned rows as local text only; it never writes to another terminal.', - 'A bound Run replays the same Delivery until --ack; process every message before acknowledging.' + 'A bound Run replays the same Delivery until --ack or all its messages are marked read, even with --types; process every message before acknowledging.' ] }, { diff --git a/src/main/agent-hooks/grok-replay-guard.test.ts b/src/main/agent-hooks/grok-replay-guard.test.ts new file mode 100644 index 00000000000..1da54f287d2 --- /dev/null +++ b/src/main/agent-hooks/grok-replay-guard.test.ts @@ -0,0 +1,136 @@ +import { spawnSync } from 'node:child_process' +import { chmodSync, existsSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { describe, expect, it, vi } from 'vitest' + +vi.mock('electron', () => ({ + app: { + getPath: () => '/tmp/userData' + } +})) + +import { getManagedScript as getClaudeManagedScript } from '../claude/hook-service' +import { getManagedScript as getCursorManagedScript } from '../cursor/hook-script' + +const POSIX_GROK_GUARD = 'if [ -n "$GROK_HOOK_EVENT" ]; then' +const WINDOWS_GROK_GUARD = 'if not "%GROK_HOOK_EVENT%"=="" goto :orca_agent_hook_drain_stdin' +const CLAUDE_SCRIPT_OPTIONS = { + skipWhenDevinImportsClaude: true, + skipWhenGrokImportsClaude: true +} + +function withPlatform(platform: NodeJS.Platform, run: () => T): T { + const descriptor = Object.getOwnPropertyDescriptor(process, 'platform')! + Object.defineProperty(process, 'platform', { value: platform, configurable: true }) + try { + return run() + } finally { + Object.defineProperty(process, 'platform', descriptor) + } +} + +function expectGuardBeforeTransport( + script: string, + guard: string, + response: string, + spool?: string +): void { + const guardIndex = script.indexOf(guard) + expect(guardIndex).toBeGreaterThan(script.indexOf(response)) + expect(guardIndex).toBeLessThan(script.indexOf('curl')) + if (spool) { + expect(guardIndex).toBeLessThan(script.indexOf(spool)) + } +} + +function runPosixHook( + script: string, + grokHookEvent: string +): { + curlCalled: boolean + stdout: string +} { + const dir = mkdtempSync(join(tmpdir(), 'orca-grok-replay-')) + const scriptPath = join(dir, 'hook.sh') + const curlPath = join(dir, 'curl') + const curlLog = join(dir, 'curl.log') + try { + writeFileSync(scriptPath, script) + writeFileSync( + curlPath, + '#!/bin/sh\n{ command -p cat 2>/dev/null || cat; } >/dev/null\nprintf "called\\n" >> "$CURL_LOG"\n' + ) + chmodSync(scriptPath, 0o755) + chmodSync(curlPath, 0o755) + + const result = spawnSync('/bin/sh', [scriptPath], { + encoding: 'utf8', + input: '{"hook_event_name":"Stop"}', + env: { + ...process.env, + PATH: `${dir}:${process.env.PATH ?? ''}`, + CURL_LOG: curlLog, + GROK_HOOK_EVENT: grokHookEvent, + ORCA_AGENT_HOOK_ENDPOINT: '', + ORCA_AGENT_HOOK_PORT: '1234', + ORCA_AGENT_HOOK_TOKEN: 'token', + ORCA_PANE_KEY: 'tab:leaf' + } + }) + + expect(result.error).toBeUndefined() + expect(result.status).toBe(0) + return { curlCalled: existsSync(curlLog), stdout: result.stdout } + } finally { + rmSync(dir, { recursive: true, force: true }) + } +} + +describe('Grok vendor hook replay guard', () => { + it('precedes spooling and HTTP in the generated POSIX Claude and Cursor scripts', () => { + const claude = getClaudeManagedScript('posix', CLAUDE_SCRIPT_OPTIONS) + const cursor = getCursorManagedScript('posix') + + expectGuardBeforeTransport(claude, POSIX_GROK_GUARD, 'printf "{}\\n"', 'spool_hook_event') + expectGuardBeforeTransport(cursor, POSIX_GROK_GUARD, 'printf "{}\\n"', 'spool_hook_event') + }) + + it('precedes HTTP while preserving fail-open output in generated Windows scripts', () => { + const { claude, cursor } = withPlatform('win32', () => ({ + claude: getClaudeManagedScript('local', CLAUDE_SCRIPT_OPTIONS), + cursor: getCursorManagedScript('local') + })) + + expectGuardBeforeTransport(claude, WINDOWS_GROK_GUARD, 'echo {}') + expectGuardBeforeTransport(cursor, WINDOWS_GROK_GUARD, '(echo {})') + const backgroundWorkerGuardIndex = claude.indexOf('CLAUDE_JOB_DIR') + expect(backgroundWorkerGuardIndex).toBeGreaterThan(-1) + expect(backgroundWorkerGuardIndex).toBeLessThan(claude.indexOf(WINDOWS_GROK_GUARD)) + }) + + it.skipIf(process.platform === 'win32')( + 'drops Grok-replayed hooks without suppressing their protocol response', + () => { + for (const script of [ + getClaudeManagedScript('posix', CLAUDE_SCRIPT_OPTIONS), + getCursorManagedScript('posix') + ]) { + const result = runPosixHook(script, 'Stop') + expect(result.curlCalled).toBe(false) + expect(result.stdout).toBe('{}\n') + } + } + ) + + it.skipIf(process.platform === 'win32')('leaves non-Grok hook delivery unchanged', () => { + for (const script of [ + getClaudeManagedScript('posix', CLAUDE_SCRIPT_OPTIONS), + getCursorManagedScript('posix') + ]) { + const result = runPosixHook(script, '') + expect(result.curlCalled).toBe(true) + expect(result.stdout).toBe('{}\n') + } + }) +}) diff --git a/src/main/agent-hooks/grok-replay-guard.ts b/src/main/agent-hooks/grok-replay-guard.ts new file mode 100644 index 00000000000..6309ed6e584 --- /dev/null +++ b/src/main/agent-hooks/grok-replay-guard.ts @@ -0,0 +1,14 @@ +import { WINDOWS_HOOK_STDIN_DRAIN_LABEL } from './hook-stdin-contract' + +export function buildPosixGrokReplayGuardLines(): string[] { + return [ + // Why: Grok imports vendor hooks; only its native hook may report the event as Grok. + 'if [ -n "$GROK_HOOK_EVENT" ]; then', + ' exit 0', + 'fi' + ] +} + +export function buildWindowsGrokReplayGuardLines(): string[] { + return [`if not "%GROK_HOOK_EVENT%"=="" goto :${WINDOWS_HOOK_STDIN_DRAIN_LABEL}`] +} diff --git a/src/main/agent-hooks/installer-utils.test.ts b/src/main/agent-hooks/installer-utils.test.ts index cbe29ee1ca1..e68e3cc3554 100644 --- a/src/main/agent-hooks/installer-utils.test.ts +++ b/src/main/agent-hooks/installer-utils.test.ts @@ -36,6 +36,7 @@ import { WINDOWS_POWERSHELL_HOOK_ENVIRONMENT_GUARD } from './hook-stdin-contract' import { wrapRuntimeHomeHookCommand } from './runtime-home-hook-command' +import { findBareHookCommandVariables } from './managed-hook-command-env.test-fixture' let tmpDir: string let configPath: string @@ -765,8 +766,7 @@ describe('wrapRuntimeHomeHookCommand', () => { const command = wrapRuntimeHomeHookCommand('claude-hook', options) expect(command).toContain('"${SYSTEMROOT-}/System32/WindowsPowerShell/v1.0/powershell.exe"') - expect(command).not.toMatch(/\$(?!\{)[A-Za-z_]/) - expect(command).not.toMatch(/\$\{[A-Za-z_][A-Za-z0-9_]*\}/) + expect(findBareHookCommandVariables(command)).toEqual([]) } ) diff --git a/src/main/agent-hooks/local-agent-cli-presence.test.ts b/src/main/agent-hooks/local-agent-cli-presence.test.ts index 15f474a9cc7..d8bb85bc405 100644 --- a/src/main/agent-hooks/local-agent-cli-presence.test.ts +++ b/src/main/agent-hooks/local-agent-cli-presence.test.ts @@ -41,6 +41,7 @@ describe('detectLocalManagedAgentCliPresence', () => { ) expect(result.codex?.state).toBe('found') + expect(result.codex).toEqual({ state: 'found', executablePath: '/bin/codex' }) expect(result.claude?.state).toBe('missing') expect(probe.mock.calls.map(([filePath]) => filePath)).toEqual([ '/bin/codex', @@ -63,6 +64,7 @@ describe('detectLocalManagedAgentCliPresence', () => { ) expect(result.codex?.state).toBe('found') + expect(result.codex).toEqual({ state: 'found', executablePath: '/custom/bin/codex' }) expect(probe).toHaveBeenCalledWith('/custom/bin/codex') }) @@ -81,6 +83,7 @@ describe('detectLocalManagedAgentCliPresence', () => { ) expect(result.claude?.state).toBe('found') + expect(result.claude).toEqual({ state: 'found', executablePath: overridePath }) expect(probe).toHaveBeenCalledWith(overridePath) }) diff --git a/src/main/agent-hooks/local-agent-cli-presence.ts b/src/main/agent-hooks/local-agent-cli-presence.ts index 5810362c27a..897e4c08b50 100644 --- a/src/main/agent-hooks/local-agent-cli-presence.ts +++ b/src/main/agent-hooks/local-agent-cli-presence.ts @@ -14,7 +14,10 @@ import { hydrateShellPath, mergePathSegments } from '../startup/hydrate-shell-pa export type LocalCliPresenceState = 'found' | 'missing' | 'unknown' export type LocalCliPresenceByAgent = Partial< - Record + Record< + AgentHookTarget, + { state: 'found'; executablePath: string } | { state: Exclude } + > > type FileProbe = { @@ -113,18 +116,18 @@ async function probePathCandidate( platform: NodeJS.Platform, fileProbe: FileProbe, pathExt?: string -): Promise { +): Promise { if (!isSafeExecutableBasename(candidate)) { - return false + return null } for (const dir of dirs) { for (const fileName of candidateFileNames(candidate, platform, pathExt)) { if (await fileProbe.isExecutableFile(pathApiForPlatform(platform).join(dir, fileName))) { - return true + return pathApiForPlatform(platform).join(dir, fileName) } } } - return false + return null } function isPlatformAbsolutePath(candidate: string, platform: NodeJS.Platform): boolean { @@ -171,10 +174,17 @@ export async function detectLocalManagedAgentCliPresence( candidates.add(override) } } - const found = new Set() + const found = new Map() for (const candidate of candidates) { - if (await probePathCandidate(candidate, dirs, platform, fileProbe, options.pathExt)) { - found.add(candidate) + const executablePath = await probePathCandidate( + candidate, + dirs, + platform, + fileProbe, + options.pathExt + ) + if (executablePath) { + found.set(candidate, executablePath) } } const result: LocalCliPresenceByAgent = {} @@ -187,13 +197,16 @@ export async function detectLocalManagedAgentCliPresence( continue } result[target.agent] = (await fileProbe.isExecutableFile(expanded)) - ? { state: 'found' } + ? { state: 'found', executablePath: expanded } : { state: 'missing' } continue } const targetCandidates = [...target.executableCandidates, ...(override ? [override] : [])] - result[target.agent] = targetCandidates.some((candidate) => found.has(candidate)) - ? { state: 'found' } + const executablePath = targetCandidates + .map((candidate) => found.get(candidate)) + .find((candidate): candidate is string => candidate !== undefined) + result[target.agent] = executablePath + ? { state: 'found', executablePath } : { state: 'missing' } } return result diff --git a/src/main/agent-hooks/managed-agent-hook-controls.test.ts b/src/main/agent-hooks/managed-agent-hook-controls.test.ts index dd77b5e8d20..625cc06f505 100644 --- a/src/main/agent-hooks/managed-agent-hook-controls.test.ts +++ b/src/main/agent-hooks/managed-agent-hook-controls.test.ts @@ -11,13 +11,18 @@ const mocks = vi.hoisted(() => ({ statusClaude: vi.fn(), statusCodex: vi.fn(), refreshClaude: vi.fn(), - refreshCodex: vi.fn() + refreshCodex: vi.fn(), + probeClaudeVersion: vi.fn() })) vi.mock('./local-agent-cli-presence', () => ({ detectLocalManagedAgentCliPresence: mocks.detect })) +vi.mock('../claude/claude-session-end-hook-capability', () => ({ + probeClaudeCliVersion: mocks.probeClaudeVersion +})) + vi.mock('./managed-agent-hook-registry', () => ({ MANAGED_AGENT_HOOK_INSTALLERS: [ ['claude', mocks.installClaude], @@ -71,6 +76,7 @@ describe('managed agent hook controls', () => { mocks.removeCodexAsync.mockResolvedValue(status('codex', 'not_installed')) mocks.refreshClaude.mockResolvedValue(undefined) mocks.refreshCodex.mockResolvedValue(undefined) + mocks.probeClaudeVersion.mockResolvedValue(null) }) it('installs only agents with positively detected CLIs', async () => { @@ -159,6 +165,19 @@ describe('managed agent hook controls', () => { ]) }) + it('forwards the detected Claude version to its installer', async () => { + mocks.detect.mockResolvedValue({ + claude: { state: 'found', executablePath: '/opt/bin/claude' }, + codex: { state: 'missing' } + }) + mocks.probeClaudeVersion.mockResolvedValue('2.1.261') + + await installManagedAgentHooks({ agentCmdOverrides: {} }) + + expect(mocks.probeClaudeVersion).toHaveBeenCalledWith('/opt/bin/claude') + expect(mocks.installClaude).toHaveBeenCalledWith({ cliVersion: '2.1.261' }) + }) + it('only refreshes scripts for the selected agents', async () => { mocks.detect.mockResolvedValue({ codex: { state: 'found' } }) diff --git a/src/main/agent-hooks/managed-agent-hook-controls.ts b/src/main/agent-hooks/managed-agent-hook-controls.ts index 6c875257089..7edfd94c7c8 100644 --- a/src/main/agent-hooks/managed-agent-hook-controls.ts +++ b/src/main/agent-hooks/managed-agent-hook-controls.ts @@ -5,6 +5,7 @@ import { } from '../../shared/managed-agent-hook-targets' import { normalizeDisabledTuiAgents } from '../../shared/tui-agent-selection' import type { GlobalSettings } from '../../shared/global-settings-types' +import { probeClaudeCliVersion } from '../claude/claude-session-end-hook-capability' import { detectLocalManagedAgentCliPresence } from './local-agent-cli-presence' import { MANAGED_AGENT_HOOK_ASYNC_REMOVERS, @@ -12,7 +13,8 @@ import { MANAGED_AGENT_HOOK_REMOVERS, MANAGED_AGENT_HOOK_SCRIPT_REFRESHERS, MANAGED_AGENT_HOOK_STATUS_READERS, - type ManagedAgentHookInstaller + type ManagedAgentHookInstaller, + type ManagedAgentHookInstallOptions } from './managed-agent-hook-registry' export { MANAGED_AGENT_HOOK_INSTALLERS } from './managed-agent-hook-registry' @@ -112,11 +114,11 @@ function selectedInstallers(options: InstallOptions): readonly ManagedAgentHookI async function runInstaller( entry: ManagedAgentHookInstaller, onInstallError: InstallOptions['onInstallError'], - userInitiated?: boolean + options: ManagedAgentHookInstallOptions ): Promise { const [agent, install] = entry try { - return await install({ userInitiated }) + return await install(options) } catch (error) { console.error(`[agent-hooks] Failed to install ${agent} managed hooks:`, error) try { @@ -200,7 +202,16 @@ export async function installManagedAgentHooks( ) continue } - results.push(await runInstaller(entry, options.onInstallError, options.userInitiated)) + const cliVersion = + agent === 'claude' && presence.executablePath + ? await probeClaudeCliVersion(presence.executablePath) + : null + results.push( + await runInstaller(entry, options.onInstallError, { + ...(options.userInitiated !== undefined ? { userInitiated: options.userInitiated } : {}), + ...(cliVersion ? { cliVersion } : {}) + }) + ) } return results } diff --git a/src/main/agent-hooks/managed-agent-hook-registry.ts b/src/main/agent-hooks/managed-agent-hook-registry.ts index 5c462f1794a..49fdcadda42 100644 --- a/src/main/agent-hooks/managed-agent-hook-registry.ts +++ b/src/main/agent-hooks/managed-agent-hook-registry.ts @@ -18,7 +18,7 @@ import { openClaudeHookService } from '../openclaude/hook-service' // Why (#16441): Codex's installer awaits a codex app-server trust-grant session // instead of blocking the main thread on spawnSync. Widening the tuple keeps the // other thirteen agent services synchronous — the shared loop already awaits. -export type ManagedAgentHookInstallOptions = { userInitiated?: boolean } +export type ManagedAgentHookInstallOptions = { userInitiated?: boolean; cliVersion?: string } export type ManagedAgentHookInstaller = readonly [ HookInstallAgent, ( @@ -37,7 +37,7 @@ export type ManagedAgentHookAsyncRemover = readonly [ export type ManagedAgentHookStatusReader = readonly [HookInstallAgent, () => AgentHookInstallStatus] export const MANAGED_AGENT_HOOK_INSTALLERS: readonly ManagedAgentHookInstaller[] = [ - ['claude', () => claudeHookService.install()], + ['claude', (options) => claudeHookService.install({ claudeVersion: options?.cliVersion })], ['openclaude', () => openClaudeHookService.install()], ['codex', () => codexHookService.install()], ['gemini', () => geminiHookService.install()], diff --git a/src/main/agent-hooks/managed-hook-command-contract.test.ts b/src/main/agent-hooks/managed-hook-command-contract.test.ts new file mode 100644 index 00000000000..72b522e8ff5 --- /dev/null +++ b/src/main/agent-hooks/managed-hook-command-contract.test.ts @@ -0,0 +1,220 @@ +import { afterEach, describe, expect, it, vi } from 'vitest' +import { + CLAUDE_HOOK_SETTINGS, + OPENCLAUDE_HOOK_SETTINGS, + getManagedLifecycleHook, + getRemoteManagedCommand as getClaudeRemoteCommand +} from '../claude/hook-settings' +import { + getManagedCommand as getCodexCommand, + wrapReadablePosixHookCommand +} from '../codex/codex-hook-definition' +import { ANTIGRAVITY_EVENTS, ANTIGRAVITY_PRE_TOOL_USE_DECISION } from '../antigravity/hook-events' +import { CURSOR_EVENTS } from '../cursor/hook-events' +import { + getManagedCommand as getCursorCommand, + getPosixManagedCommand as getCursorRemoteCommand +} from '../cursor/hook-script' +import { + COPILOT_EVENTS, + getManagedCommand as getCopilotCommand +} from '../copilot/copilot-managed-hook-definitions' +import { getDevinManagedCommand, getDevinRemoteManagedCommand } from '../devin/hook-settings' +import { getGrokManagedCommand } from '../grok/grok-hook-script' +import { + wrapPosixHookCommand, + wrapWindowsCmdHookCommand, + wrapWindowsHookCommand +} from './installer-utils' +import { MANAGED_AGENT_HOOK_INSTALLERS } from './managed-agent-hook-registry' +import { REMOTE_MANAGED_HOOK_INSTALLER_AGENTS } from './remote-managed-hook-installers' +import { + findBareHookCommandVariables, + GROK_PROVIDED_HOOK_VARIABLES +} from './managed-hook-command-env.test-fixture' + +vi.mock('electron', () => ({ app: { getPath: () => process.cwd() } })) + +afterEach(() => vi.restoreAllMocks()) + +type CommandBuilders = { + local: (scriptPath: string) => string[] + remote: (scriptPath: string) => string[] +} + +// Why: Gemini/Droid/Command Code keep their thin builders private; exercise the wrappers they call. +const standardCommands: CommandBuilders = { + local: (path) => [ + process.platform === 'win32' ? wrapWindowsHookCommand(path) : wrapPosixHookCommand(path) + ], + remote: (path) => [wrapPosixHookCommand(path)] +} + +function antigravityPosixCommands(path: string): string[] { + return ANTIGRAVITY_EVENTS.map((event) => + wrapPosixHookCommand( + path, + { ORCA_ANTIGRAVITY_EVENT: event.eventName }, + event.eventName === 'PreToolUse' ? { fallbackStdout: ANTIGRAVITY_PRE_TOOL_USE_DECISION } : {} + ) + ) +} + +const buildersByAgent = new Map([ + [ + 'claude', + { + local: (path) => + [true, false].map( + (gitBashAvailable) => + getManagedLifecycleHook(path, CLAUDE_HOOK_SETTINGS, { gitBashAvailable }).command + ), + remote: (path) => [getClaudeRemoteCommand(path)] + } + ], + [ + 'openclaude', + { + local: (path) => [getManagedLifecycleHook(path, OPENCLAUDE_HOOK_SETTINGS).command], + remote: (path) => [getClaudeRemoteCommand(path)] + } + ], + [ + 'codex', + { + local: (path) => [getCodexCommand(path), wrapReadablePosixHookCommand(path)], + remote: (path) => [wrapPosixHookCommand(path), wrapReadablePosixHookCommand(path)] + } + ], + ['gemini', standardCommands], + [ + 'antigravity', + { + local: (path) => + process.platform === 'win32' + ? ANTIGRAVITY_EVENTS.map((event) => + wrapWindowsCmdHookCommand( + path.replace('antigravity-hook.cmd', event.windowsWrapperFileName) + ) + ) + : antigravityPosixCommands(path), + remote: antigravityPosixCommands + } + ], + [ + 'cursor', + { + local: (path) => CURSOR_EVENTS.map((event) => getCursorCommand(path, event)), + remote: (path) => CURSOR_EVENTS.map((event) => getCursorRemoteCommand(path, event)) + } + ], + ['droid', standardCommands], + ['command-code', standardCommands], + [ + 'grok', + { + local: (path) => [getGrokManagedCommand(path)], + // Why: grok-hook-remote-install.ts calls this wrapper directly, with the pane guard. + remote: (path) => [wrapPosixHookCommand(path, {}, { requiredEnvVar: 'ORCA_PANE_KEY' })] + } + ], + [ + 'copilot', + { + local: (path) => COPILOT_EVENTS.map((event) => getCopilotCommand(path, event)), + remote: (path) => + COPILOT_EVENTS.map((event) => + wrapPosixHookCommand(path, { ORCA_COPILOT_HOOK_EVENT: event }) + ) + } + ], + [ + 'devin', + { + local: (path) => [getDevinManagedCommand(path)], + remote: (path) => [getDevinRemoteManagedCommand(path)] + } + ], + [ + 'kimi', + { + local: (path) => [wrapPosixHookCommand(path.replaceAll('\\', '/'))], + remote: (path) => [wrapPosixHookCommand(path)] + } + ] +]) + +// Why: as in MANAGED_AGENT_HOOK_SCRIPT_REFRESHERS, native plugin source has no shell command to scan. +const exemptionsByAgent = new Map([ + ['amp', 'Native TypeScript plugin source; no shell hook command'], + ['hermes', 'Native Python plugin source; no shell hook command'] +]) + +describe('managed hook command contract', () => { + it.each([ + ['local', MANAGED_AGENT_HOOK_INSTALLERS.map(([agent]) => agent)], + ['remote', REMOTE_MANAGED_HOOK_INSTALLER_AGENTS] + ] as const)('covers the %s installer registry in both directions', (_target, agents) => { + // Why: mirror the remote installer coverage ratchet (#7253); a new provider cannot opt out silently. + for (const agent of agents) { + expect( + Number(buildersByAgent.has(agent)) + Number(exemptionsByAgent.has(agent)), + `${agent} needs exactly one command builder or documented native-plugin exemption` + ).toBe(1) + } + const registered = new Set(agents) + for (const agent of [...buildersByAgent.keys(), ...exemptionsByAgent.keys()]) { + expect(registered.has(agent), `${agent} is absent from the installer registry`).toBe(true) + } + }) + + describe.each(['darwin', 'linux', 'win32'] as const)('%s host', (platform) => { + it.each([...buildersByAgent])('%s emits no bare variable references', (agent, builders) => { + vi.spyOn(process, 'platform', 'get').mockReturnValue(platform) + const extension = platform === 'win32' && agent !== 'kimi' ? 'cmd' : 'sh' + const homes = + platform === 'win32' ? ['C:/Users/test', 'C:/Users/test user'] : ['/home/test user'] + const paths = homes.map((home) => `${home}/.orca/agent-hooks/${agent}-hook.${extension}`) + const commands = [ + ...paths.flatMap((path) => builders.local(path)), + ...builders.remote(`/home/remote user/.orca/agent-hooks/${agent}-hook.sh`) + ] + expect(commands.length).toBeGreaterThan(0) + for (const command of commands) { + expect(command.length).toBeGreaterThan(0) + expect(findBareHookCommandVariables(command), command).toEqual([]) + } + }) + }) +}) + +describe('Grok variable scanner contract', () => { + it.each(['$NAME', '${NAME}', "'$NAME'", "'${NAME}'", '\\$NAME', '$lower_9', '${_NAME9}'])( + 'rejects bare references without shell quoting state: %s', + (command) => expect(findBareHookCommandVariables(command)).toHaveLength(1) + ) + + it.each([ + '${NAME-}', + '${NAME:-}', + '${NAME:+}', + '${NAME#x}', + '${NAME:0:5}', + '${NAME+x}', + '${NAME=x}', + '${NAME?x}', + '${NAME%x}', + '${NAME/x/y}', + '$1', + '$$', + '$?', + '$(true)' + ])('allows modifiers and non-variable dollar forms: %s', (command) => { + expect(findBareHookCommandVariables(command)).toEqual([]) + }) + + it.each(GROK_PROVIDED_HOOK_VARIABLES)('exempts only the exact provided name %s', (name) => { + expect(findBareHookCommandVariables(`$${name} \${${name}}`)).toEqual([]) + expect(findBareHookCommandVariables(`$${name}_OTHER \${${name}_OTHER}`)).toHaveLength(2) + }) +}) diff --git a/src/main/agent-hooks/managed-hook-command-env.test-fixture.ts b/src/main/agent-hooks/managed-hook-command-env.test-fixture.ts new file mode 100644 index 00000000000..77c73534c3f --- /dev/null +++ b/src/main/agent-hooks/managed-hook-command-env.test-fixture.ts @@ -0,0 +1,19 @@ +export const GROK_PROVIDED_HOOK_VARIABLES = [ + 'GROK_HOOK_EVENT', + 'GROK_HOOK_NAME', + 'GROK_SESSION_ID', + 'GROK_WORKSPACE_ROOT', + 'CLAUDE_PROJECT_DIR' +] as const + +const providedVariables = new Set(GROK_PROVIDED_HOOK_VARIABLES) + +export function findBareHookCommandVariables(command: string): string[] { + // Why: Grok scans dollar bytes without shell quoting state, even inside single quotes. + // These are the two runtime-home assertions from installer-utils.test.ts, shared across builders. + const references = [ + ...command.matchAll(/\$(?!\{)([A-Za-z_][A-Za-z0-9_]*)/g), + ...command.matchAll(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g) + ] + return references.filter((match) => !providedVariables.has(match[1])).map((match) => match[0]) +} diff --git a/src/main/agent-hooks/managed-hook-detection-commands.test.ts b/src/main/agent-hooks/managed-hook-detection-commands.test.ts index abcb24d3969..15f4c041860 100644 --- a/src/main/agent-hooks/managed-hook-detection-commands.test.ts +++ b/src/main/agent-hooks/managed-hook-detection-commands.test.ts @@ -21,4 +21,13 @@ describe('managed hook detection commands', () => { it('maps detected TUI ids back to managed hook targets', () => { expect(detectedManagedHookAgents(['codex', 'opencode', 'droid'])).toEqual(['codex', 'droid']) }) + + it('requests a version only for Claude capability detection', () => { + const commands = buildManagedHookDetectionCommands(null, 'linux') + + expect(commands.find((command) => command.id === 'claude')).toMatchObject({ + reportVersion: true + }) + expect(commands.find((command) => command.id === 'codex')?.reportVersion).toBeUndefined() + }) }) diff --git a/src/main/agent-hooks/managed-hook-detection-commands.ts b/src/main/agent-hooks/managed-hook-detection-commands.ts index 2200d183c2e..b5183af7ec0 100644 --- a/src/main/agent-hooks/managed-hook-detection-commands.ts +++ b/src/main/agent-hooks/managed-hook-detection-commands.ts @@ -7,6 +7,7 @@ import { MANAGED_AGENT_HOOK_TARGETS } from '../../shared/managed-agent-hook-targ import { normalizeDisabledTuiAgents } from '../../shared/tui-agent-selection' import type { GlobalSettings } from '../../shared/global-settings-types' import type { TuiAgentDetectionCommand } from '../ipc/tui-agent-detection-commands' +import { parseClaudeCliVersion } from '../claude/claude-session-end-hook-capability' export type ManagedHookDetectionSettings = Partial< Pick @@ -26,7 +27,11 @@ export function buildManagedHookDetectionCommands( if (override && isSafeOverrideExecutableToken(override)) { commands.add(override) } - return [...commands].map((cmd) => ({ id: target.tuiAgent, cmd })) + return [...commands].map((cmd) => ({ + id: target.tuiAgent, + cmd, + ...(target.agent === 'claude' ? { reportVersion: true as const } : {}) + })) } ) } @@ -40,3 +45,22 @@ export function detectedManagedHookAgents(values: unknown): AgentHookTarget[] { (target) => target.agent ) } + +export function readManagedHookDetectionResult(value: unknown): { + agents: AgentHookTarget[] + claudeVersion: string | null +} { + if (value === null || typeof value !== 'object') { + return { agents: [], claudeVersion: null } + } + const agents = detectedManagedHookAgents(Reflect.get(value, 'agents')) + const versions = Reflect.get(value, 'versions') + const rawClaudeVersion = + versions !== null && typeof versions === 'object' ? Reflect.get(versions, 'claude') : null + return { + agents, + claudeVersion: parseClaudeCliVersion( + typeof rawClaudeVersion === 'string' ? rawClaudeVersion : null + ) + } +} diff --git a/src/main/agent-hooks/managed-hook-runtime.ts b/src/main/agent-hooks/managed-hook-runtime.ts index e995467ee7d..99a2c68be89 100644 --- a/src/main/agent-hooks/managed-hook-runtime.ts +++ b/src/main/agent-hooks/managed-hook-runtime.ts @@ -77,6 +77,7 @@ export async function installManagedHooks(options?: { signal?: AbortSignal hostKeyFingerprint?: string agents?: readonly AgentHookTarget[] + claudeVersion?: string }): Promise { options?.signal?.throwIfAborted() // Why: empty/omitted allowlist fails closed before any home/host probes. @@ -101,7 +102,8 @@ export async function installManagedHooks(options?: { { grokHomeDir, signal: options?.signal, - agents + agents, + ...(options?.claudeVersion ? { claudeVersion: options.claudeVersion } : {}) } ) return { diff --git a/src/main/agent-hooks/posix-hook-command.ts b/src/main/agent-hooks/posix-hook-command.ts index 728fc30bf18..23d8f1acba8 100644 --- a/src/main/agent-hooks/posix-hook-command.ts +++ b/src/main/agent-hooks/posix-hook-command.ts @@ -21,13 +21,10 @@ export function wrapPosixHookCommand( options.fallbackStdout === undefined ? POSIX_HOOK_STDIN_DRAIN_COMMAND : `printf '%s\\n' ${quotePosixShellString(options.fallbackStdout)}; ${POSIX_HOOK_STDIN_DRAIN_COMMAND}` - // Why an env guard and not just a file test: the managed script always exists, so without this - // the agent spawns a shell for it on every event and the script only then discovers Orca is not - // listening and exits. The spawn has already happened by that point, which is the whole cost a - // standalone session was paying. `requiredEnvVar` names a variable Orca sets on the panes it - // launches, so a session Orca did not start short-circuits before spawning anything. + // Why: default form avoids Grok rejecting unset vars or splicing values into shell quotes at load + // time; the child shell checks the current pane env before spawning the managed script. const guards = [ - ...(options.requiredEnvVar ? [`[ -n "$${options.requiredEnvVar}" ]`] : []), + ...(options.requiredEnvVar ? [`[ -n "\${${options.requiredEnvVar}-}" ]`] : []), `[ -f ${quoted} ]`, `[ -r ${quoted} ]`, `[ -x ${quoted} ]` diff --git a/src/main/agent-hooks/remote-hook-service-installers.test.ts b/src/main/agent-hooks/remote-hook-service-installers.test.ts index a1168326ac2..2e4cbb06496 100644 --- a/src/main/agent-hooks/remote-hook-service-installers.test.ts +++ b/src/main/agent-hooks/remote-hook-service-installers.test.ts @@ -410,6 +410,7 @@ describe('remote hook service installers', () => { 'SessionStart', 'UserPromptSubmit', 'Stop', + 'StopCancelled', 'StopFailure', 'SessionEnd', 'PreToolUse', @@ -420,7 +421,7 @@ describe('remote hook service installers', () => { const definition = grokConfig.hooks[eventName]?.[0] const command = definition?.hooks?.[0]?.command expect(command).toContain('/home/dev/.orca/agent-hooks/grok-hook.sh') - expect(command).toMatch(/^if \[ -n "\$ORCA_PANE_KEY" \] && /) + expect(command).toMatch(/^if \[ -n "\$\{ORCA_PANE_KEY-\}" \] && /) } // Why: Grok tool matchers are real regexes; bare `*` is invalid match-all. expect(grokConfig.hooks.PreToolUse?.[0]?.matcher).toBe('.*') diff --git a/src/main/agent-hooks/remote-managed-hook-installers.ts b/src/main/agent-hooks/remote-managed-hook-installers.ts index bf97436f8f8..a335e8ccc77 100644 --- a/src/main/agent-hooks/remote-managed-hook-installers.ts +++ b/src/main/agent-hooks/remote-managed-hook-installers.ts @@ -22,6 +22,8 @@ export type RemoteManagedHookInstallOptions = { deferTrustUntilConfigToml?: boolean /** Explicit GROK_HOME for remote runtimes that redirect Grok's config. */ grokHomeDir?: string + /** Version reported by Claude on this execution host. */ + claudeVersion?: string /** Stops before starting the next installer when the owning relay request * is cancelled. Individual filesystem mutations remain atomic. */ signal?: AbortSignal @@ -40,7 +42,13 @@ type RemoteManagedHookInstaller = readonly [ ] const REMOTE_MANAGED_HOOK_INSTALLERS: readonly RemoteManagedHookInstaller[] = [ - ['claude', (sftp, remoteHome) => claudeHookService.installRemote(sftp, remoteHome)], + [ + 'claude', + (sftp, remoteHome, options) => + claudeHookService.installRemote(sftp, remoteHome, { + claudeVersion: options?.claudeVersion + }) + ], ['openclaude', (sftp, remoteHome) => openClaudeHookService.installRemote(sftp, remoteHome)], [ 'codex', diff --git a/src/main/agent-hooks/server-grok-background-status.test.ts b/src/main/agent-hooks/server-grok-background-status.test.ts new file mode 100644 index 00000000000..452eb7882b2 --- /dev/null +++ b/src/main/agent-hooks/server-grok-background-status.test.ts @@ -0,0 +1,202 @@ +import { mkdtempSync, rmSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { AgentHookServer, _internals } from './server' +import { buildBody, PANE } from './server.test-fixtures' + +const { getCohortAtEmitMock, trackMock } = vi.hoisted(() => ({ + getCohortAtEmitMock: vi.fn(), + trackMock: vi.fn() +})) + +vi.mock('../telemetry/client', () => ({ track: trackMock })) +vi.mock('../telemetry/cohort-classifier', () => ({ getCohortAtEmit: getCohortAtEmitMock })) + +beforeEach(() => { + _internals.resetCachesForTests() + trackMock.mockReset() + getCohortAtEmitMock.mockReset() + getCohortAtEmitMock.mockReturnValue({ nth_repo_added: 2 }) +}) + +afterEach(() => vi.restoreAllMocks()) + +async function postGrokHook( + server: AgentHookServer, + payload: Record +): Promise { + const env = server.buildPtyEnv() + const response = await fetch(`http://127.0.0.1:${env.ORCA_AGENT_HOOK_PORT}/hook/grok`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Orca-Agent-Hook-Token': env.ORCA_AGENT_HOOK_TOKEN + }, + body: JSON.stringify(buildBody(payload)) + }) + expect(response.status).toBe(204) +} + +describe('Grok background status ownership', () => { + it('keeps the host-owned row working while finite background work remains', async () => { + const server = new AgentHookServer() + await server.start({ env: 'production' }) + try { + await postGrokHook(server, { + hookEventName: 'user_prompt_submit', + sessionId: 'session-1', + promptId: 'prompt-1', + prompt: 'run a background task' + }) + await postGrokHook(server, { + hookEventName: 'stop', + sessionId: 'session-1', + promptId: 'prompt-1', + reason: 'end_turn', + stopHookActive: false, + backgroundTasks: [{ id: 'task-1', type: 'shell', status: 'running' }] + }) + + expect(server.getStatusSnapshot()).toEqual([ + expect.objectContaining({ + paneKey: PANE, + state: 'working', + workingMode: 'monitoring', + agentType: 'grok' + }) + ]) + + await postGrokHook(server, { + hookEventName: 'user_prompt_submit', + sessionId: 'session-1', + promptId: 'task-completed-task-1', + prompt: 'the background task completed' + }) + await postGrokHook(server, { + hookEventName: 'stop', + sessionId: 'session-1', + promptId: 'task-completed-task-1', + reason: 'end_turn', + stopHookActive: false, + backgroundTasks: [] + }) + + expect(server.getStatusSnapshot()).toEqual([ + expect.objectContaining({ paneKey: PANE, state: 'done', agentType: 'grok' }) + ]) + } finally { + server.stop() + } + }) + + it('rejects a delayed remote cancellation from the turn replaced by a newer prompt', () => { + const server = new AgentHookServer() + server.ingestRemote( + { + paneKey: PANE, + tabId: 'tab-1', + worktreeId: 'wt-1', + source: 'grok', + hookEventName: 'UserPromptSubmit', + providerPromptId: 'prompt-new', + providerSession: { key: 'session_id', id: 'session-1' }, + payload: { state: 'working', prompt: 'new turn', agentType: 'grok' } + }, + 'conn-1' + ) + server.ingestRemote( + { + paneKey: PANE, + tabId: 'tab-1', + worktreeId: 'wt-1', + source: 'grok', + hookEventName: 'StopCancelled', + providerPromptId: 'prompt-old', + providerSession: { key: 'session_id', id: 'session-1' }, + payload: { + state: 'done', + prompt: 'old turn', + agentType: 'grok', + interrupted: true + } + }, + 'conn-1' + ) + + expect(server._getStateForTests().lastStatusByPaneKey.get(PANE)).toMatchObject({ + providerPromptId: 'prompt-new', + payload: { state: 'working', prompt: 'new turn' } + }) + }) + + it('retains an id-less Grok turn fence across status hydration', async () => { + const userDataPath = mkdtempSync(join(tmpdir(), 'orca-grok-status-')) + const firstServer = new AgentHookServer() + const restoredServer = new AgentHookServer() + try { + await firstServer.start({ env: 'production', userDataPath }) + firstServer.ingestRemote( + { + paneKey: PANE, + tabId: 'tab-1', + worktreeId: 'wt-1', + source: 'grok', + hookEventName: 'UserPromptSubmit', + grokPromptBoundary: true, + providerSession: { key: 'session_id', id: 'session-1' }, + payload: { state: 'working', prompt: 'new turn', agentType: 'grok' } + }, + 'conn-1' + ) + firstServer.flushStatusPersistSync() + firstServer.stop() + + await restoredServer.start({ env: 'production', userDataPath }) + restoredServer.ingestRemote( + { + paneKey: PANE, + tabId: 'tab-1', + worktreeId: 'wt-1', + source: 'grok', + hookEventName: 'StopCancelled', + providerPromptId: 'prompt-old', + providerSession: { key: 'session_id', id: 'session-1' }, + payload: { + state: 'done', + prompt: 'old turn', + agentType: 'grok', + interrupted: true + } + }, + 'conn-1' + ) + + expect(restoredServer._getStateForTests().lastStatusByPaneKey.get(PANE)).toMatchObject({ + grokPromptBoundary: true, + payload: { state: 'working', prompt: 'new turn' } + }) + + restoredServer.ingestRemote( + { + paneKey: PANE, + tabId: 'tab-1', + worktreeId: 'wt-1', + source: 'grok', + hookEventName: 'Stop', + grokPromptBoundary: true, + providerSession: { key: 'session_id', id: 'session-1' }, + payload: { state: 'done', prompt: 'new turn', agentType: 'grok' } + }, + 'conn-1' + ) + expect(restoredServer.getStatusSnapshot()).toEqual([ + expect.objectContaining({ state: 'done', prompt: 'new turn', agentType: 'grok' }) + ]) + } finally { + firstServer.stop() + restoredServer.stop() + rmSync(userDataPath, { recursive: true, force: true }) + } + }) +}) diff --git a/src/main/agent-hooks/server/server-grok-status-rules.ts b/src/main/agent-hooks/server/server-grok-status-rules.ts new file mode 100644 index 00000000000..732f119ccc6 --- /dev/null +++ b/src/main/agent-hooks/server/server-grok-status-rules.ts @@ -0,0 +1,27 @@ +import type { AgentHookEventPayload } from '../../../shared/agent-hook-listener/listener-event' +import { isGrokEvent } from '../../../shared/agent-hook-listener/provider-event-names' +import type { EnrichedAgentHookEventPayload } from './server-types' + +export function isStaleGrokTurnEnd( + previous: EnrichedAgentHookEventPayload | undefined, + incoming: AgentHookEventPayload +): boolean { + if ( + previous?.source !== 'grok' || + previous.payload.state === 'done' || + incoming.source !== 'grok' || + !isGrokEvent(incoming.hookEventName, 'stop', 'stop_failure', 'stop_cancelled') || + !incoming.providerPromptId + ) { + return false + } + if (!previous.providerPromptId) { + return previous.grokPromptBoundary === true + } + const differentSession = Boolean( + previous.providerSession?.id && + incoming.providerSession?.id && + previous.providerSession.id !== incoming.providerSession.id + ) + return differentSession || previous.providerPromptId !== incoming.providerPromptId +} diff --git a/src/main/agent-hooks/server/server-ingest-remote.ts b/src/main/agent-hooks/server/server-ingest-remote.ts index fae24c93b41..7f2008114f1 100644 --- a/src/main/agent-hooks/server/server-ingest-remote.ts +++ b/src/main/agent-hooks/server/server-ingest-remote.ts @@ -5,6 +5,7 @@ import { isAgentHookSource, restoreShedStatusFields } from '../../../shared/agen import { MAX_PANE_KEY_LEN, normalizeClaudePromptId, + normalizeGrokPromptId, warnOnHookEnvOrVersionMismatch } from '../../../shared/agent-hook-listener/listener-limits' import { @@ -34,6 +35,7 @@ export abstract class AgentHookServerIngestRemote extends AgentHookServerIngestS hookEventName?: string source?: unknown providerPromptId?: unknown + grokPromptBoundary?: unknown compactTrigger?: unknown toolUseId?: string toolAgentId?: string @@ -104,7 +106,13 @@ export abstract class AgentHookServerIngestRemote extends AgentHookServerIngestS : undefined const source = isAgentHookSource(envelope.source) ? envelope.source : undefined const providerPromptId = - source === 'claude' ? normalizeClaudePromptId(envelope.providerPromptId) : undefined + source === 'claude' + ? normalizeClaudePromptId(envelope.providerPromptId) + : source === 'grok' + ? normalizeGrokPromptId(envelope.providerPromptId) + : undefined + const grokPromptBoundary = + source === 'grok' && envelope.grokPromptBoundary === true ? true : undefined const compactTrigger = source === 'claude' && (envelope.compactTrigger === 'manual' || envelope.compactTrigger === 'auto') @@ -240,7 +248,7 @@ export abstract class AgentHookServerIngestRemote extends AgentHookServerIngestS env: envelope.env, expectedEnv: this.env }) - const event = { + const event: AgentHookEventPayload = { paneKey, source, launchToken: statusDisposition === 'restart' ? undefined : envelope.launchToken, @@ -251,6 +259,7 @@ export abstract class AgentHookServerIngestRemote extends AgentHookServerIngestS promptInteractionKey, hookEventName, providerPromptId, + grokPromptBoundary, compactTrigger, toolUseId, toolAgentId, @@ -264,7 +273,7 @@ export abstract class AgentHookServerIngestRemote extends AgentHookServerIngestS ? envelope.claudeRunningNonAgentTask : undefined, payload: normalizedPayload - } as AgentHookEventPayload + } this.recordCurrentAuthorityObservation(event) this.applyNormalizedStatus( event, diff --git a/src/main/agent-hooks/server/server-persistence-validation.ts b/src/main/agent-hooks/server/server-persistence-validation.ts index 6c0136aaa51..d47fe0cddeb 100644 --- a/src/main/agent-hooks/server/server-persistence-validation.ts +++ b/src/main/agent-hooks/server/server-persistence-validation.ts @@ -6,7 +6,10 @@ import { type ParsedAgentStatusPayload } from '../../../shared/agent-status-types' import { isAgentHookSource } from '../../../shared/agent-hook-relay' -import { normalizeClaudePromptId } from '../../../shared/agent-hook-listener/listener-limits' +import { + normalizeClaudePromptId, + normalizeGrokPromptId +} from '../../../shared/agent-hook-listener/listener-limits' import { parsePaneKey } from '../../../shared/stable-pane-id' import type { AgentHookAuthorityEvidence, EnrichedAgentHookEventPayload } from './server-types' import { isValidPaneKey, isValidPiProviderSessionOnly } from './server-status-identity' @@ -100,7 +103,11 @@ export function sanitizeHydratedEntry( } const source = isAgentHookSource(record.source) ? record.source : undefined const providerPromptId = - source === 'claude' ? normalizeClaudePromptId(record.providerPromptId) : undefined + source === 'claude' + ? normalizeClaudePromptId(record.providerPromptId) + : source === 'grok' + ? normalizeGrokPromptId(record.providerPromptId) + : undefined const compactTrigger = source === 'claude' && (record.compactTrigger === 'manual' || record.compactTrigger === 'auto') ? record.compactTrigger @@ -114,6 +121,7 @@ export function sanitizeHydratedEntry( hasExplicitPrompt: record.hasExplicitPrompt === true ? true : undefined, hookEventName: typeof record.hookEventName === 'string' ? record.hookEventName : undefined, providerPromptId, + grokPromptBoundary: source === 'grok' && record.grokPromptBoundary === true ? true : undefined, compactTrigger, toolUseId: typeof record.toolUseId === 'string' ? record.toolUseId : undefined, toolAgentId: typeof record.toolAgentId === 'string' ? record.toolAgentId : undefined, diff --git a/src/main/agent-hooks/server/server-status-update.ts b/src/main/agent-hooks/server/server-status-update.ts index 5ea3b07739b..fb165ce1c83 100644 --- a/src/main/agent-hooks/server/server-status-update.ts +++ b/src/main/agent-hooks/server/server-status-update.ts @@ -16,6 +16,7 @@ import { invalidateClaudeChildOnlyBoundary, shouldKeepClaudePermissionVisible } from './server-claude-status-rules' +import { isStaleGrokTurnEnd } from './server-grok-status-rules' import { isToolProgressWorkingAfterInterrupt } from './server-status-identity' import { AgentHookServerStatusApplication } from './server-status-application' @@ -42,6 +43,11 @@ export abstract class AgentHookServerStatusUpdate extends AgentHookServerStatusA : undefined) const terminalOwnedPayload = terminalHandle === payload.terminalHandle ? payload : { ...payload, terminalHandle } + if (previous && isStaleGrokTurnEnd(previous, terminalOwnedPayload)) { + // Why: Grok turn-end hooks may arrive after the next prompt, including across relay restart. + this.commitStatusRowMutation(rowBefore, previous) + return previous + } const connectionClearWatermark = terminalOwnedPayload.connectionId ? this.connectionTimestampWatermarkById.get(terminalOwnedPayload.connectionId) : undefined diff --git a/src/main/agent-hooks/wsl-hook-fs-adapter.ts b/src/main/agent-hooks/wsl-hook-fs-adapter.ts index ce2e9dd75f7..71699f57d28 100644 --- a/src/main/agent-hooks/wsl-hook-fs-adapter.ts +++ b/src/main/agent-hooks/wsl-hook-fs-adapter.ts @@ -8,7 +8,7 @@ import type { SFTPWrapper } from 'ssh2' import type { installRemoteManagedAgentHooks } from './remote-managed-hook-installers' import { buildManagedHookDetectionCommands, - detectedManagedHookAgents, + readManagedHookDetectionResult, type ManagedHookDetectionSettings } from './managed-hook-detection-commands' import type { SshChannelMultiplexer } from '../ssh/ssh-channel-multiplexer' @@ -30,11 +30,15 @@ export async function installWslGuestHooks(options: { const { mux, guestHome, codexHomePath, distro, installHooks, settings, warn, installCodex } = options let agents + let claudeVersion: string | null = null try { - const detected = (await mux.request('preflight.detectAgents', { - commands: buildManagedHookDetectionCommands(settings, 'linux') - })) as { agents?: unknown } - agents = detectedManagedHookAgents(detected?.agents) + const detected = readManagedHookDetectionResult( + await mux.request('preflight.detectAgents', { + commands: buildManagedHookDetectionCommands(settings, 'linux') + }) + ) + agents = detected.agents + claudeVersion = detected.claudeVersion } catch (error) { warn( `[agent-hooks] WSL agent detection for '${distro}' failed: ${ @@ -64,7 +68,8 @@ export async function installWslGuestHooks(options: { // runtime-host writer above; the relay adapter owns all other agents. const remoteAgents = agents.filter((agent) => agent !== 'codex') const results = await installHooks(createWslHookSftpAdapter(mux), guestHome, { - agents: remoteAgents + agents: remoteAgents, + ...(claudeVersion ? { claudeVersion } : {}) }) const failed = results.filter((r) => r.state === 'error').length if (failed > 0) { diff --git a/src/main/agent-hooks/wsl-hook-relay-manager.test.ts b/src/main/agent-hooks/wsl-hook-relay-manager.test.ts index 9d92f5d131a..4f4607f423d 100644 --- a/src/main/agent-hooks/wsl-hook-relay-manager.test.ts +++ b/src/main/agent-hooks/wsl-hook-relay-manager.test.ts @@ -180,9 +180,13 @@ describe('WslHookRelayManager', () => { } function guestTransport( - options: { registerInstallPlugins?: boolean; detectedAgents?: string[] } = {} + options: { + registerInstallPlugins?: boolean + detectedAgents?: string[] + claudeVersion?: string + } = {} ): MultiplexerTransport { - const { registerInstallPlugins = true, detectedAgents = ['codex'] } = options + const { registerInstallPlugins = true, detectedAgents = ['codex'], claudeVersion } = options const harness = createGuestHarness() harnesses.push(harness) registerWslHookFsHandlers(harness.guestDispatcher, home) @@ -190,7 +194,8 @@ describe('WslHookRelayManager', () => { replayed: 0 })) harness.guestDispatcher.onRequest('preflight.detectAgents', async () => ({ - agents: detectedAgents + agents: detectedAgents, + ...(claudeVersion ? { versions: { claude: claudeVersion } } : {}) })) // A guest bundle predating the plugin overlay omits this handler (-32601). if (registerInstallPlugins) { @@ -281,6 +286,22 @@ describe('WslHookRelayManager', () => { manager.disposeAll() }) + it('forwards the WSL guest Claude version to the shared remote installer', async () => { + const waitForSentinel = vi.fn(async () => + guestTransport({ detectedAgents: ['claude'], claudeVersion: '2.1.261 (Claude Code)' }) + ) + const { manager, deps } = createManager({ waitForSentinel }) + + manager.ensureForDistro('Ubuntu') + await vi.waitFor(() => expect(deps.installHooks).toHaveBeenCalledTimes(1)) + + expect(deps.installHooks).toHaveBeenCalledWith(expect.anything(), home, { + agents: ['claude'], + claudeVersion: '2.1.261' + }) + manager.disposeAll() + }) + it('reinstalls into a newly resolved runtime home without restarting the relay', async () => { const { manager, deps } = createManager({}) manager.ensureForDistro('Ubuntu', codexHome) diff --git a/src/main/ai-vault-search/session-search-file-id.test.ts b/src/main/ai-vault-search/session-search-file-id.test.ts new file mode 100644 index 00000000000..f09240643a5 --- /dev/null +++ b/src/main/ai-vault-search/session-search-file-id.test.ts @@ -0,0 +1,103 @@ +import { afterEach, beforeEach, expect, it } from 'vitest' +import { SessionSearchIndexConsumer } from './session-search-index-consumer' +import { + openSessionSearchIndexFile, + syntheticCandidate, + syntheticSession, + SYNTHETIC_TRANSCRIPT, + type SessionSearchIndexFile +} from './session-search-index-test-fixture' +import { sessionSearchReadDecision } from './session-search-read-decision' +import { SessionSearchStore } from './session-search-store' + +const LARGE_ID = 25_614_222_884_620_952 +let index: SessionSearchIndexFile +let store: SessionSearchStore +let errors: unknown[] + +beforeEach(async () => { + index = await openSessionSearchIndexFile('ss-file-id') + errors = [] + store = new SessionSearchStore(index.path, (error) => errors.push(error)) +}) + +afterEach(async () => { + store.close() + await index.close() +}) + +it('reads an unsafe INTEGER through the append cursor lookup', () => { + index.db + .prepare('INSERT INTO files(path, dev, ino, byte_offset, mtime_ms) VALUES (?, 1, ?, 100, 0)') + .run(SYNTHETIC_TRANSCRIPT, BigInt(LARGE_ID)) + expect(store.indexedFile(SYNTHETIC_TRANSCRIPT, { dev: 1, ino: LARGE_ID })?.byteOffset).toBe(100) +}) + +it.each([ + { dev: 1, ino: LARGE_ID }, + { dev: LARGE_ID, ino: 1 }, + { dev: Number.MAX_SAFE_INTEGER, ino: Number.MAX_SAFE_INTEGER }, + { dev: 0, ino: 0 }, + { dev: 1, ino: 2 ** 63 } +])('round-trips numeric stat identity across reopen: %j', (identity) => { + const candidate = syntheticCandidate(identity) + const write = store.beginWrite(candidate, 'replace', 0) + expect(write?.commit({ session: syntheticSession(), byteOffset: 4096, incomplete: false })).toBe( + true + ) + store.close() + store = new SessionSearchStore(index.path, (error) => errors.push(error)) + + const row = store.files()[0] + expect(row?.identity).toEqual(identity) + const cursor = store.indexedFile(SYNTHETIC_TRANSCRIPT, identity) + expect(cursor).toEqual({ byteOffset: 4096, mtimeMs: candidate.file.mtimeMs, sizeBytes: 4096 }) + expect(sessionSearchReadDecision({ candidate, row, cursor, cutoffMs: null })).toBe('skip') + + const consumer = new SessionSearchIndexConsumer(store) + const append = consumer.beginRead({ candidate, mode: 'append', previousByteOffset: 4096 }) + expect(append).not.toBeNull() + append?.finish({ session: syntheticSession(), byteOffset: 8192, incomplete: false }) + expect(store.indexedFile(SYNTHETIC_TRANSCRIPT, identity)?.byteOffset).toBe(8192) + + for (const replacement of [ + { ...identity, ino: identity.ino + 4096 }, + { ...identity, dev: identity.dev + 4096 } + ]) { + const replaced = syntheticCandidate(replacement) + const replacementCursor = store.indexedFile(SYNTHETIC_TRANSCRIPT, replacement) + expect(replacementCursor).toBeNull() + expect( + sessionSearchReadDecision({ + candidate: replaced, + row, + cursor: replacementCursor, + cutoffMs: null + }) + ).toBe('whole') + expect( + consumer.beginRead({ candidate: replaced, mode: 'append', previousByteOffset: 8192 }) + ).toBeNull() + } + expect(errors).toEqual([]) +}) + +it.each([ + { dev: BigInt(LARGE_ID), ino: 1n }, + { dev: 1n, ino: BigInt(LARGE_ID) }, + { dev: null, ino: BigInt(LARGE_ID) }, + { dev: BigInt(LARGE_ID), ino: null }, + { dev: null, ino: null } +])('reads already-written INTEGER identities and incomplete pairs: $dev / $ino', ({ dev, ino }) => { + index.db + .prepare('INSERT INTO files(path, dev, ino, byte_offset, mtime_ms) VALUES (?, ?, ?, 100, 0)') + .run(SYNTHETIC_TRANSCRIPT, dev, ino) + + expect(store.files()[0]?.identity).toEqual( + dev !== null && ino !== null ? { dev: Number(dev), ino: Number(ino) } : null + ) + const identity = { dev: Number(dev), ino: Number(ino) } + expect(store.indexedFile(SYNTHETIC_TRANSCRIPT, identity)?.byteOffset).toBe(100) + expect(store.indexedFile(SYNTHETIC_TRANSCRIPT, null)?.byteOffset).toBe(100) + expect(errors).toEqual([]) +}) diff --git a/src/main/ai-vault-search/session-search-index-writer.ts b/src/main/ai-vault-search/session-search-index-writer.ts index a5c981b5bb2..5e29f2004af 100644 --- a/src/main/ai-vault-search/session-search-index-writer.ts +++ b/src/main/ai-vault-search/session-search-index-writer.ts @@ -109,9 +109,12 @@ export class SessionSearchIndexWriter { * and the decline would be the only thing that ever forced the whole read. */ indexedFile(path: string, identity: SessionSearchFileIdentity): SessionSearchIndexedFile | null { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The files schema defines FileRow; REAL casts return numeric IDs or null. const row = this.db .prepare( - 'SELECT dev, ino, byte_offset, mtime_ms, size_bytes, session_row_id FROM files WHERE path = ?' + // REAL recovers the original numeric stat IDs, including existing oversized INTEGER rows. + `SELECT CAST(dev AS REAL) AS dev, CAST(ino AS REAL) AS ino, + byte_offset, mtime_ms, size_bytes, session_row_id FROM files WHERE path = ?` ) .get(path) as FileRow | undefined if (!row) { diff --git a/src/main/ai-vault-search/session-search-store.ts b/src/main/ai-vault-search/session-search-store.ts index daa9267561b..435fa16ce8a 100644 --- a/src/main/ai-vault-search/session-search-store.ts +++ b/src/main/ai-vault-search/session-search-store.ts @@ -198,28 +198,33 @@ export class SessionSearchStore { */ files(): SessionSearchFileRow[] { return ( - this.db - .prepare( - `SELECT path, dev, ino, mtime_ms AS mtimeMs, size_bytes AS sizeBytes, + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The files schema and SELECT aliases define this row; REAL casts return numeric IDs or null. + ( + this.db + .prepare( + // Numeric stat IDs may exceed SQLite's safe INTEGER-to-number read range. + `SELECT path, CAST(dev AS REAL) AS dev, CAST(ino AS REAL) AS ino, + mtime_ms AS mtimeMs, size_bytes AS sizeBytes, state, fail_count AS failCount, failed_mtime_ms AS failedMtimeMs FROM files` - ) - .all() as (Omit & { - dev: number | null - ino: number | null - })[] - ).map((row) => ({ - path: row.path, - identity: - typeof row.dev === 'number' && typeof row.ino === 'number' - ? { dev: row.dev, ino: row.ino } - : null, - mtimeMs: row.mtimeMs, - sizeBytes: row.sizeBytes, - state: row.state, - failCount: row.failCount, - failedMtimeMs: row.failedMtimeMs - })) + ) + .all() as (Omit & { + dev: number | null + ino: number | null + })[] + ).map((row) => ({ + path: row.path, + identity: + typeof row.dev === 'number' && typeof row.ino === 'number' + ? { dev: row.dev, ino: row.ino } + : null, + mtimeMs: row.mtimeMs, + sizeBytes: row.sizeBytes, + state: row.state, + failCount: row.failCount, + failedMtimeMs: row.failedMtimeMs + })) + ) } /** diff --git a/src/main/ai-vault/remote-session-content-lines.ts b/src/main/ai-vault/remote-session-content-lines.ts index c20c6ec10ac..d62e8988018 100644 --- a/src/main/ai-vault/remote-session-content-lines.ts +++ b/src/main/ai-vault/remote-session-content-lines.ts @@ -1,6 +1,9 @@ +import { splitTranscriptStreamLines } from '../native-chat/transcript-stream-lines' import { setImmediate as yieldToEventLoop } from 'node:timers/promises' import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' +export type RemoteSessionContent = string | AsyncIterable + const REMOTE_CONTENT_YIELD_LINE_COUNT = 200 const REMOTE_CONTENT_YIELD_CHAR_COUNT = 256 * 1024 @@ -9,9 +12,12 @@ const REMOTE_CONTENT_YIELD_CHAR_COUNT = 256 * 1024 * cancelled scan stops mid-transcript instead of parsing megabytes for a caller * that already left. */ export function remoteSessionContentLines( - content: string, + content: RemoteSessionContent, signal?: AbortSignal ): Iterable | AsyncIterable { + if (typeof content !== 'string') { + return content + } return signal ? cancellableContentLines(content, signal) : content.split(/\r?\n/) } @@ -61,3 +67,32 @@ async function yieldUnlessCancelled(signal: AbortSignal): Promise { await yieldToEventLoop() throwIfAiVaultScanCancelled(signal) } + +export class BinarySessionTranscriptError extends Error { + constructor() { + super('Binary session transcript') + } +} + +export async function* streamedSessionContentLines( + bytes: AsyncIterable, + signal?: AbortSignal +): AsyncGenerator { + let count = 0 + let chars = 0 + for await (const record of splitTranscriptStreamLines(bytes)) { + throwIfAiVaultScanCancelled(signal) + const line = + record.line.endsWith('\r') && (record.terminated || signal) + ? record.line.slice(0, -1) + : record.line + yield line + chars += line.length + if (++count >= REMOTE_CONTENT_YIELD_LINE_COUNT || chars >= REMOTE_CONTENT_YIELD_CHAR_COUNT) { + await yieldToEventLoop() + throwIfAiVaultScanCancelled(signal) + count = 0 + chars = 0 + } + } +} diff --git a/src/main/ai-vault/remote-session-document-parsers.ts b/src/main/ai-vault/remote-session-document-parsers.ts new file mode 100644 index 00000000000..1dcd78ba08b --- /dev/null +++ b/src/main/ai-vault/remote-session-document-parsers.ts @@ -0,0 +1,51 @@ +import type { AiVaultAgent } from '../../shared/ai-vault-types' +import { parseDevinSessionDocument } from './session-scanner-devin-parser' +import { parseHermesSessionDocument } from './session-scanner-hermes-parser' +import { + parseGeminiSessionDocument, + parseGeminiJsonlSessionLines +} from './session-scanner-gemini-parsers' +import type { RemoteSessionSource } from './remote-session-scanner-types' + +export function remoteSessionDocumentParsers( + agent: AiVaultAgent +): Pick { + const parse = + agent === 'hermes' + ? parseHermesSessionDocument + : agent === 'devin' + ? parseDevinSessionDocument + : agent === 'gemini' + ? parseGeminiSessionDocument + : null + if (!parse) { + return {} + } + return { + parseDocument: (file, bytes, context) => + parse( + file, + bytes, + context.hostPlatform.os, + { + executionHostId: context.executionHostId, + executionHostPlatform: context.hostPlatform.os + }, + context.signal + ), + ...(agent === 'gemini' + ? { + parseLines: (file, lines, context) => + parseGeminiJsonlSessionLines({ + file, + lines, + platform: context.hostPlatform.os, + options: { + executionHostId: context.executionHostId, + executionHostPlatform: context.hostPlatform.os + } + }) + } + : {}) + } +} diff --git a/src/main/ai-vault/remote-session-large-transcripts.test.ts b/src/main/ai-vault/remote-session-large-transcripts.test.ts new file mode 100644 index 00000000000..62d8b8c5ed1 --- /dev/null +++ b/src/main/ai-vault/remote-session-large-transcripts.test.ts @@ -0,0 +1,188 @@ +import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join, dirname } from 'node:path' +import { describe, it, expect } from 'vitest' +import { createRelayAiVaultFilesystemProvider } from '../../relay/ai-vault-service-filesystem' +import { scanRemoteAiVaultSessions } from './remote-session-scanner' +import { getRemoteHostPlatform } from '../ssh/ssh-remote-platform' + +const platform = getRemoteHostPlatform( + process.platform === 'win32' + ? 'win32-x64' + : process.platform === 'darwin' + ? 'darwin-arm64' + : 'linux-x64' +) +const jsonl = (rows: unknown[]) => `${rows.map((row) => JSON.stringify(row)).join('\n')}\n` +const filler = jsonl([{ type: 'irrelevant_event', payload: 'x'.repeat(1024) }]).repeat(11000) + +describe('large remote history through real relay filesystem', () => { + it('lists a large Codex rollout with middle messages and usage intact', async () => { + const home = await mkdtemp(join(tmpdir(), 'orca-history-17744-')) + try { + const path = join(home, '.codex', 'sessions', 'large.jsonl') + await mkdir(dirname(path), { recursive: true }) + await writeFile( + path, + jsonl([ + { + type: 'session_meta', + timestamp: '2026-09-13T01:00:00Z', + payload: { id: 'large', cwd: '/repo' } + }, + { + type: 'response_item', + timestamp: '2026-09-13T01:00:01Z', + payload: { + type: 'message', + role: 'user', + content: [{ type: 'input_text', text: 'Keep my history' }] + } + } + ]) + + filler.slice(0, filler.length / 2) + + jsonl([ + { + type: 'response_item', + timestamp: '2026-09-13T01:02:00Z', + payload: { + type: 'message', + role: 'assistant', + content: [{ type: 'output_text', text: 'Middle answer' }] + } + }, + { + type: 'event_msg', + timestamp: '2026-09-13T01:03:00Z', + payload: { + type: 'token_count', + info: { + total_token_usage: { input_tokens: 123, output_tokens: 45, total_tokens: 168 } + } + } + } + ]) + + filler.slice(filler.length / 2) + ) + const result = await scanRemoteAiVaultSessions({ + provider: createRelayAiVaultFilesystemProvider(), + executionHostId: 'ssh:synthetic-17744', + remoteHome: home, + hostPlatform: platform, + unlimited: true + }) + expect(result.issues).toEqual([]) + expect(result.sessions).toHaveLength(1) + expect(result.sessions[0]).toMatchObject({ + sessionId: 'large', + messageCount: 2, + totalTokens: 168, + title: 'Keep my history' + }) + } finally { + await rm(home, { recursive: true, force: true }) + } + }) + + it.each(['hermes', 'devin', 'gemini', 'cline'] as const)( + 'lists large %s documents with every message counted', + async (agent) => { + const home = await mkdtemp(join(tmpdir(), 'orca-history-17744-document-')) + try { + const messages = Array.from({ length: 11000 }, () => ({ + role: 'assistant', + content: 'x'.repeat(1024) + })) + messages.splice(5000, 0, { role: 'user', content: 'A middle user turn' }) + let path: string, record: unknown + if (agent === 'hermes') { + path = join(home, '.hermes', 'sessions', 'large.json') + record = { session_id: 'large', cwd: '/repo', model: 'test-model', messages } + } else if (agent === 'devin') { + path = join(home, '.local', 'share', 'devin', 'cli', 'transcripts', 'large.json') + record = { + session_id: 'large', + working_directory: '/repo', + steps: messages.map((message) => ({ + ...message, + metadata: { + is_user_input: message.role === 'user', + metrics: { input_tokens: 2, output_tokens: 1 } + } + })) + } + } else if (agent === 'gemini') { + path = join(home, '.gemini', 'tmp', 'large.json') + record = { + sessionId: 'large', + messages: messages.map((message) => ({ + type: message.role === 'assistant' ? 'gemini' : 'user', + content: message.content + })) + } + } else { + path = join(home, '.cline', 'data', 'sessions', 'large', 'large.json') + record = { session_id: 'large', cwd: '/repo' } + await mkdir(dirname(path), { recursive: true }) + await writeFile(path.replace('.json', '.messages.json'), JSON.stringify({ messages })) + } + await mkdir(dirname(path), { recursive: true }) + await writeFile(path, JSON.stringify(record)) + const result = await scanRemoteAiVaultSessions({ + provider: createRelayAiVaultFilesystemProvider(), + executionHostId: `ssh:large-${agent}`, + remoteHome: home, + hostPlatform: platform, + unlimited: true + }) + expect(result.issues).toEqual([]) + expect(result.sessions).toHaveLength(1) + expect(result.sessions[0]).toMatchObject({ agent, sessionId: 'large', messageCount: 11001 }) + if (agent === 'devin') { + expect(result.sessions[0].totalTokens).toBe(33003) + } + } finally { + await rm(home, { recursive: true, force: true }) + } + } + ) + it('keeps normal-size reads on their existing path and supports providers without streaming', async () => { + const home = await mkdtemp(join(tmpdir(), 'orca-history-legacy-')) + try { + const directory = join(home, '.codex', 'sessions') + await mkdir(directory, { recursive: true }) + const content = jsonl([{ type: 'session_meta', payload: { id: 'small', cwd: '/repo' } }]) + await writeFile(join(directory, 'small.jsonl'), content) + const provider = createRelayAiVaultFilesystemProvider() + provider.readTranscriptBytes = () => { + throw new Error('Small file must keep its existing read path') + } + const small = await scanRemoteAiVaultSessions({ + provider, + executionHostId: 'ssh:small-original', + remoteHome: home, + hostPlatform: platform, + unlimited: true + }) + expect(small.issues).toEqual([]) + expect(small.sessions.map((session) => session.sessionId)).toEqual(['small']) + await writeFile(join(directory, 'large.jsonl'), content + filler) + const legacy = { readDir: provider.readDir, readFile: provider.readFile, stat: provider.stat } + const fallback = await scanRemoteAiVaultSessions({ + provider: legacy, + executionHostId: 'ssh:legacy-original', + remoteHome: home, + hostPlatform: platform, + unlimited: true + }) + expect(fallback.sessions.map((session) => session.sessionId)).toEqual(['small']) + expect( + fallback.issues.some( + (issue) => issue.path.endsWith('large.jsonl') && issue.message.includes('10MB limit') + ) + ).toBe(true) + } finally { + await rm(home, { recursive: true, force: true }) + } + }) +}) diff --git a/src/main/ai-vault/remote-session-scan-concurrency.ts b/src/main/ai-vault/remote-session-scan-concurrency.ts index 77b8e371b51..e74375259f5 100644 --- a/src/main/ai-vault/remote-session-scan-concurrency.ts +++ b/src/main/ai-vault/remote-session-scan-concurrency.ts @@ -16,7 +16,32 @@ export function limitRemoteScanFilesystemConcurrency( return { readDir: (dirPath) => gate(() => provider.readDir(dirPath)), readFile: (filePath) => gate(() => provider.readFile(filePath)), - stat: (filePath) => gate(() => provider.stat(filePath)) + stat: (filePath) => gate(() => provider.stat(filePath)), + ...(provider.readTranscriptBytes + ? { + readTranscriptBytes: async function* (path: string, signal?: AbortSignal) { + let enter!: () => void + let release!: () => void + const entered = new Promise((resolve) => { + enter = resolve + }) + const released = new Promise((resolve) => { + release = resolve + }) + const held = gate(async () => { + enter() + await released + }) + await entered + try { + yield* provider.readTranscriptBytes!(path, signal) + } finally { + release() + await held + } + } + } + : {}) } } diff --git a/src/main/ai-vault/remote-session-scanner-cline-source.ts b/src/main/ai-vault/remote-session-scanner-cline-source.ts index f2f79089f9a..f568aa06ce9 100644 --- a/src/main/ai-vault/remote-session-scanner-cline-source.ts +++ b/src/main/ai-vault/remote-session-scanner-cline-source.ts @@ -6,6 +6,7 @@ import type { RemoteSessionSource } from './remote-session-scanner-types' import { clineMessagesPathForMetadata, isClineSessionMetadataPath, + parseClineSessionDocuments, parseClineSessionContent } from './session-scanner-cline-parser' @@ -20,6 +21,22 @@ export function remoteClineSource( filePredicate: isClineSessionMetadataPath, contentDependencyPath: clineMessagesPathForMetadata, directoryPredicate: (_name, depth) => depth === 0, + parseDocument: (file, bytes, context) => + parseClineSessionDocuments( + file, + bytes, + () => + context.provider.readTranscriptBytes!( + clineMessagesPathForMetadata(file.path), + context.signal + ), + context.hostPlatform.os, + { + executionHostId: context.executionHostId, + executionHostPlatform: context.hostPlatform.os + }, + context.signal + ), parse: async (file, content, context) => { let messagesContent: string | null = null try { diff --git a/src/main/ai-vault/remote-session-scanner-sources.ts b/src/main/ai-vault/remote-session-scanner-sources.ts index 2c21a93db9a..92b9e9b4dc5 100644 --- a/src/main/ai-vault/remote-session-scanner-sources.ts +++ b/src/main/ai-vault/remote-session-scanner-sources.ts @@ -1,3 +1,5 @@ +import { remoteSessionDocumentParsers } from './remote-session-document-parsers' +import type { RemoteSessionContent } from './remote-session-content-lines' import type { AiVaultAgent, AiVaultSession } from '../../shared/ai-vault-types' import type { RemoteHostPlatform } from '../ssh/ssh-remote-platform' import { joinRemotePath } from '../ssh/ssh-remote-platform' @@ -24,9 +26,9 @@ import type { RemoteSessionSource } from './remote-session-scanner-types' -type RemoteContentParser = ( +type RemoteContentParser = ( file: FileWithMtime, - content: string, + content: T, platform: NodeJS.Platform, options: RemoteParserOptions, // Line-based parsers iterate cancellably; whole-document parsers ignore it. @@ -134,22 +136,28 @@ function remoteAntigravitySource( ): RemoteSessionSource { const cliRoot = joinRemotePath(hostPlatform, remoteHome, '.gemini', 'antigravity-cli') const historyPath = joinRemotePath(hostPlatform, cliRoot, 'history.jsonl') + const parse = async ( + file: FileWithMtime, + content: RemoteSessionContent, + context: RemoteScannerContext + ) => { + const session = await parseAntigravitySessionContent( + file, + content, + context.hostPlatform.os, + parserOptions(context), + context.signal + ) + return session ? context.antigravityWorkspaceResolver.enrich(session, historyPath) : null + } return { agent: 'antigravity', rootDir: joinRemotePath(hostPlatform, cliRoot, 'brain'), extensions: ['.jsonl'], filePredicate: isAntigravityTranscriptPath, fixedChildFileSegments: ['.system_generated', 'logs', 'transcript.jsonl'], - parse: async (file, content, context) => { - const session = await parseAntigravitySessionContent( - file, - content, - context.hostPlatform.os, - parserOptions(context), - context.signal - ) - return session ? context.antigravityWorkspaceResolver.enrich(session, historyPath) : null - } + parse, + parseLines: parse } } @@ -169,6 +177,7 @@ function source( extensions, filePredicate, directoryPredicate, + ...remoteSessionDocumentParsers(agent), parse: (file, content, context) => Promise.resolve( parseContent(file, content, context.hostPlatform.os, parserOptions(context), context.signal) @@ -181,10 +190,16 @@ function jsonlSource( remoteHome: string, hostPlatform: RemoteHostPlatform, segments: readonly string[], - parseContent: RemoteContentParser, + parseContent: RemoteContentParser, filePredicate?: (path: string) => boolean ): RemoteSessionSource { - return source(agent, remoteHome, hostPlatform, segments, ['.jsonl'], parseContent, filePredicate) + return { + ...source(agent, remoteHome, hostPlatform, segments, ['.jsonl'], parseContent, filePredicate), + parseLines: (file, lines, context) => + Promise.resolve( + parseContent(file, lines, context.hostPlatform.os, parserOptions(context), context.signal) + ) + } } function remoteCodexSources( @@ -202,12 +217,12 @@ function remoteCodexSources( 'codex-runtime-home', 'home' ) - ].map((codexHome) => ({ - agent: 'codex', - rootDir: joinRemotePath(hostPlatform, codexHome, 'sessions'), - codexHome, - extensions: ['.jsonl'], - parse: (file, content, context) => + ].map((codexHome) => { + const parse = ( + file: FileWithMtime, + content: RemoteSessionContent, + context: RemoteScannerContext + ) => parseCodexSessionContent({ file, content, @@ -218,7 +233,15 @@ function remoteCodexSources( signal: context.signal, readIndexedTitle: remoteCodexIndexedTitleReader(codexHome, context) }) - })) + return { + agent: 'codex', + rootDir: joinRemotePath(hostPlatform, codexHome, 'sessions'), + codexHome, + extensions: ['.jsonl'], + parse, + parseLines: parse + } + }) } function remoteOpenClawSources( @@ -246,7 +269,7 @@ function parserOptions(context: RemoteScannerContext): RemoteParserOptions { function piParser( file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform, options: RemoteParserOptions, signal?: AbortSignal @@ -256,7 +279,7 @@ function piParser( function ompParser( file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform, options: RemoteParserOptions, signal?: AbortSignal @@ -266,7 +289,7 @@ function ompParser( function primeAgentParser( file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform, options: RemoteParserOptions, signal?: AbortSignal @@ -276,7 +299,7 @@ function primeAgentParser( function openClawParser( file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform, options: RemoteParserOptions, signal?: AbortSignal diff --git a/src/main/ai-vault/remote-session-scanner-types.ts b/src/main/ai-vault/remote-session-scanner-types.ts index 405ea7f4626..7f78cbb5d60 100644 --- a/src/main/ai-vault/remote-session-scanner-types.ts +++ b/src/main/ai-vault/remote-session-scanner-types.ts @@ -18,7 +18,10 @@ export type RemoteScannerContext = { export type RemoteSessionFilesystemProvider = Pick< IFilesystemProvider, 'readDir' | 'readFile' | 'stat' -> +> & { + /** Available only beside the execution host's disk; never opens a client path. */ + readTranscriptBytes?: (path: string, signal?: AbortSignal) => AsyncIterable +} export type RemoteParserOptions = { executionHostId: ExecutionHostId @@ -42,6 +45,16 @@ export type RemoteSessionSource = { // artifact dir): count subagent transcripts from the walked listing and drop // them from candidates instead of indexing them as sessions. partitionSubagentTranscripts?: (paths: readonly string[]) => SubagentTranscriptPartition + parseDocument?: ( + file: FileWithMtime, + bytes: AsyncIterable, + context: RemoteScannerContext + ) => Promise + parseLines?: ( + file: FileWithMtime, + lines: AsyncIterable, + context: RemoteScannerContext + ) => Promise parse: ( file: FileWithMtime, content: string, diff --git a/src/main/ai-vault/remote-session-scanner.ts b/src/main/ai-vault/remote-session-scanner.ts index 259c84d66ef..971bc20f70e 100644 --- a/src/main/ai-vault/remote-session-scanner.ts +++ b/src/main/ai-vault/remote-session-scanner.ts @@ -1,3 +1,5 @@ +import { parseRemoteSessionTranscript } from './remote-session-transcript-read' +import { BinarySessionTranscriptError } from './remote-session-content-lines' import type { AiVaultListResult, AiVaultScanIssue, @@ -239,14 +241,7 @@ async function parseRemoteSessionCandidate( const session = await parseRemoteSessionFileCached({ candidate, hostKey: remoteSessionParseHostKey(context), - parse: async () => { - const read = await context.provider.readFile(candidate.file.path) - throwIfAiVaultScanCancelled(context.signal) - if (read.isBinary) { - return null - } - return await candidate.source.parse(candidate.file, read.content, context) - }, + parse: () => parseRemoteSessionTranscript(candidate, context), refreshReusedSession: reusedCodexTitleRefresh(candidate, context) }) throwIfAiVaultScanCancelled(context.signal) @@ -260,6 +255,9 @@ async function parseRemoteSessionCandidate( return session } catch (err) { throwIfAiVaultScanCancelled(context.signal) + if (err instanceof BinarySessionTranscriptError) { + return null + } recordSessionScanIssue(issues, { executionHostId: context.executionHostId, agent: candidate.source.agent, diff --git a/src/main/ai-vault/remote-session-stream-lifecycle.test.ts b/src/main/ai-vault/remote-session-stream-lifecycle.test.ts new file mode 100644 index 00000000000..46668e3574e --- /dev/null +++ b/src/main/ai-vault/remote-session-stream-lifecycle.test.ts @@ -0,0 +1,95 @@ +import { describe, it, expect, vi } from 'vitest' +import { streamedSessionContentLines } from './remote-session-content-lines' +import { readStreamedSessionDocument } from './session-document-stream' +import { limitRemoteScanFilesystemConcurrency } from './remote-session-scan-concurrency' + +describe('stream lifetime and retained document work', () => { + it('releases the source when a line consumer finishes early', async () => { + let closed = false + async function* bytes() { + try { + yield Buffer.from('one\ntwo\n') + yield Buffer.from('three\n') + } finally { + closed = true + } + } + for await (const line of streamedSessionContentLines(bytes())) { + expect(line).toBe('one') + break + } + await vi.waitFor(() => expect(closed).toBe(true)) + }) + it('propagates disk failure and closes the source', async () => { + let closed = false + async function* bytes() { + try { + yield Buffer.from('one\n') + throw new Error('disk read failed') + } finally { + closed = true + } + } + await expect( + (async () => { + for await (const _ of streamedSessionContentLines(bytes())) { + /* consume */ + } + })() + ).rejects.toThrow('disk read failed') + expect(closed).toBe(true) + }) + it('cancellation discards a document fold and releases its source', async () => { + const controller = new AbortController() + let closed = false + async function* bytes() { + try { + yield Buffer.from('{"messages":[{"role":"user"}') + controller.abort() + yield Buffer.from(']}') + } finally { + closed = true + } + } + await expect( + readStreamedSessionDocument({ + bytes: bytes(), + arrayKey: 'messages', + fields: [], + create: () => ({ count: 0 }), + consume: (state) => { + state.count++ + }, + signal: controller.signal + }) + ).rejects.toThrow() + expect(closed).toBe(true) + }) + it('holds one filesystem slot for the stream lifetime and releases it on return', async () => { + let entered = 0 + async function* bytes() { + entered++ + yield Buffer.from('a') + yield Buffer.from('b') + } + const provider = limitRemoteScanFilesystemConcurrency( + { + readDir: async () => [], + readFile: async () => ({ content: '', isBinary: false }), + stat: async () => ({ size: 0, type: 'file', mtime: 0 }), + readTranscriptBytes: bytes + }, + 1 + ) + const first = provider.readTranscriptBytes!('/one')[Symbol.asyncIterator](), + second = provider.readTranscriptBytes!('/two')[Symbol.asyncIterator]() + await first.next() + const pending = second.next() + await Promise.resolve() + expect(entered).toBe(1) + await first.return!() + await pending + expect(entered).toBe(2) + await second.return!() + }) +}) diff --git a/src/main/ai-vault/remote-session-transcript-read.ts b/src/main/ai-vault/remote-session-transcript-read.ts new file mode 100644 index 00000000000..42ea29af409 --- /dev/null +++ b/src/main/ai-vault/remote-session-transcript-read.ts @@ -0,0 +1,49 @@ +import { streamedSessionContentLines } from './remote-session-content-lines' +import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' +import type { RemoteSessionCandidate, RemoteScannerContext } from './remote-session-scanner-types' +import type { AiVaultSession } from '../../shared/ai-vault-types' + +const LEGACY_SESSION_TEXT_LIMIT_BYTES = 10 * 1024 * 1024 + +export async function parseRemoteSessionTranscript( + candidate: RemoteSessionCandidate, + context: RemoteScannerContext +): Promise { + const sidecar = candidate.file.sidecar + const exceedsWholeReadLimit = + (candidate.file.sizeBytes ?? 0) > LEGACY_SESSION_TEXT_LIMIT_BYTES || + (typeof sidecar === 'object' && sidecar.sizeBytes > LEGACY_SESSION_TEXT_LIMIT_BYTES) + if ( + exceedsWholeReadLimit && + candidate.source.parseDocument && + !candidate.file.path.endsWith('.jsonl') && + context.provider.readTranscriptBytes + ) { + return candidate.source.parseDocument( + candidate.file, + context.provider.readTranscriptBytes(candidate.file.path, context.signal), + context + ) + } + if ( + exceedsWholeReadLimit && + candidate.file.path.endsWith('.jsonl') && + candidate.source.parseLines && + context.provider.readTranscriptBytes + ) { + return candidate.source.parseLines( + candidate.file, + streamedSessionContentLines( + context.provider.readTranscriptBytes(candidate.file.path, context.signal), + context.signal + ), + context + ) + } + const read = await context.provider.readFile(candidate.file.path) + throwIfAiVaultScanCancelled(context.signal) + if (read.isBinary) { + return null + } + return await candidate.source.parse(candidate.file, read.content, context) +} diff --git a/src/main/ai-vault/session-document-stream-boundaries.test.ts b/src/main/ai-vault/session-document-stream-boundaries.test.ts new file mode 100644 index 00000000000..67901707cbd --- /dev/null +++ b/src/main/ai-vault/session-document-stream-boundaries.test.ts @@ -0,0 +1,106 @@ +import { describe, it, expect } from 'vitest' +import { + parseHermesSessionContent, + parseHermesSessionDocument +} from './session-scanner-hermes-parser' +import { + parseClineSessionContent, + parseClineSessionDocuments +} from './session-scanner-cline-parser' +import { + remoteSessionContentLines, + streamedSessionContentLines +} from './remote-session-content-lines' + +const file = { + path: '/fixture/session/session.json', + mtimeMs: 0, + modifiedAt: new Date(0).toISOString() +} +const options = { + executionHostId: 'ssh:independent-review' as const, + executionHostPlatform: 'linux' as const +} +async function* bytes(data: Buffer | string, size = 3) { + const b = typeof data === 'string' ? Buffer.from(data) : data + for (let i = 0; i < b.length; i += size) { + yield b.subarray(i, i + size) + } +} +async function outcome(run: () => unknown) { + try { + return { value: await run() } + } catch (error) { + return { error: error instanceof Error ? error.name : typeof error } + } +} +async function lines(content: Iterable | AsyncIterable) { + const result: string[] = [] + for await (const line of content) { + result.push(line) + } + return result +} + +describe('independent JSON boundary review', () => { + for (const content of ['', ' \t\r\n']) { + it(`preserves empty-document parse outcome ${JSON.stringify(content)}`, async () => { + expect( + await outcome(() => parseHermesSessionDocument(file, bytes(content), 'linux', options)) + ).toEqual(await outcome(() => parseHermesSessionContent(file, content, 'linux', options))) + }) + } + for (const invalid of [[255], [195], [237, 160, 128], [240, 128, 128, 128], [226, 40, 161]]) { + it(`preserves legacy replacement decoding for UTF8 ${invalid.join('-')}`, async () => { + const data = Buffer.concat([ + Buffer.from('{"session_id":"id","messages":[{"role":"user","content":"before '), + Buffer.from(invalid), + Buffer.from(' after"}]}') + ]) + expect( + await outcome(() => parseHermesSessionDocument(file, bytes(data, 1), 'linux', options)) + ).toEqual( + await outcome(() => + parseHermesSessionContent(file, data.toString('utf8'), 'linux', options) + ) + ) + }) + } + it('ignores errors in an overwritten Cline messages array', async () => { + const metadata = '{"session_id":"id","prompt":"fallback"}' + const messages = '{"messages":[{"role":"user","content":"discarded","ts":1e300}],"messages":[]}' + expect( + await outcome(() => + parseClineSessionDocuments(file, bytes(metadata), () => bytes(messages), 'linux', options) + ) + ).toEqual( + await outcome(() => parseClineSessionContent(file, metadata, messages, 'linux', options)) + ) + }) + it('does not turn a bare carriage return into a JSONL record boundary', async () => { + const content = '{"role":"user","content":"first"}\r{"role":"assistant","content":"second"}' + expect(await lines(streamedSessionContentLines(bytes(content)))).toEqual( + await lines(remoteSessionContentLines(content)) + ) + }) + it('preserves escaped surrogate, duplicate nested key, and prototype-looking key values', async () => { + const content = String.raw`{"session_id":"id","__proto__":{"polluted":true},"messages":[{"role":"assistant","role":"user","content":"\ud800X\udc00 \ud83d\udc0b","__proto__":{"role":"assistant"}}]}` + expect(await parseHermesSessionDocument(file, bytes(content, 1), 'linux', options)).toEqual( + await parseHermesSessionContent(file, content, 'linux', options) + ) + expect(Reflect.get({}, 'polluted')).toBeUndefined() + }) + for (const content of [ + '{"messages":[],}', + '{"messages":[1,]}', + '{"messages":[01]}', + '{"messages":[NaN]}', + '{} {}' + ]) { + it(`rejects malformed JSON ${content}`, async () => { + expect( + await outcome(() => parseHermesSessionDocument(file, bytes(content), 'linux', options)) + ).toEqual(await outcome(() => parseHermesSessionContent(file, content, 'linux', options))) + }) + } +}) diff --git a/src/main/ai-vault/session-document-stream-parity.test.ts b/src/main/ai-vault/session-document-stream-parity.test.ts new file mode 100644 index 00000000000..441d25d2752 --- /dev/null +++ b/src/main/ai-vault/session-document-stream-parity.test.ts @@ -0,0 +1,95 @@ +import { describe, it, expect } from 'vitest' +import { + parseHermesSessionContent, + parseHermesSessionDocument +} from './session-scanner-hermes-parser' +import { parseDevinSessionContent, parseDevinSessionDocument } from './session-scanner-devin-parser' +import { + parseGeminiSessionContent, + parseGeminiSessionDocument +} from './session-scanner-gemini-parsers' +import { + parseClineSessionContent, + parseClineSessionDocuments +} from './session-scanner-cline-parser' + +const file = { + path: '/sessions/identity/identity.json', + mtimeMs: 1000, + modifiedAt: new Date(1000).toISOString() +} +const options = { executionHostId: 'ssh:parity' as const, executionHostPlatform: 'darwin' as const } +async function* bytes(content: string) { + const data = Buffer.from(content) + for (let i = 0; i < data.length; i += 3) { + yield data.subarray(i, i + 3) + } +} +const fixtures = [ + { + agent: 'hermes', + parse: parseHermesSessionContent, + stream: parseHermesSessionDocument, + content: + '{"messages":[{"role":"user","content":"Ü🐋 first"},{"role":"assistant","content":"answer"}],"session_id":"id","cwd":"/repo","model":"root","session_start":"2026-01-01T00:00:00Z","last_updated":"2026-01-02T00:00:00Z","message_count":99}' + }, + { + agent: 'devin', + parse: parseDevinSessionContent, + stream: parseDevinSessionDocument, + content: + '{"steps":[{"role":"assistant","text":"answer","metadata":{"generation_model":"step","created_at":"2026-01-02T00:00:00Z","metrics":{"input_tokens":10,"output_tokens":20}}},{"metadata":{"is_user_input":true},"text":"Ü🐋 prompt"}],"agent":{"model_name":"root"},"session_id":"id","working_directory":"/repo"}' + }, + { + agent: 'gemini', + parse: parseGeminiSessionContent, + stream: parseGeminiSessionDocument, + content: + '{"messages":[{"type":"user","content":"Ü🐋 first","timestamp":"2026-01-02T00:00:00Z"},{"type":"gemini","content":"answer","tokens":{"input":10,"output":20}}],"sessionId":"id","startTime":"2026-01-01T00:00:00Z","lastUpdated":"2026-01-03T00:00:00Z"}' + } +] +describe('streamed whole-document parser equivalence', () => { + for (const fixture of fixtures) { + it(`${fixture.agent}: field order and UTF8 chunk boundaries preserve every output field`, async () => { + expect(await fixture.stream(file, bytes(fixture.content), 'darwin', options)).toEqual( + await fixture.parse(file, fixture.content, 'darwin', options) + ) + }) + for (const last of [ + '[]', + 'null', + '[{"role":"user","type":"user","content":"last","text":"last","metadata":{"is_user_input":true}}]' + ]) { + it(`${fixture.agent}: duplicate arrays use their final value ${last}`, async () => { + const key = fixture.agent === 'devin' ? 'steps' : 'messages' + const content = `${fixture.content.slice(0, -1)},"${key}":${last}}` + expect(await fixture.stream(file, bytes(content), 'darwin', options)).toEqual( + await fixture.parse(file, content, 'darwin', options) + ) + }) + } + it(`${fixture.agent}: rejects a malformed tail after valid messages`, async () => { + const content = fixture.content.slice(0, -1) + await expect(fixture.stream(file, bytes(content), 'darwin', options)).rejects.toThrow() + }) + } + it('Cline preserves sidecar semantics, metadata field order and duplicate arrays', async () => { + const metadata = + '{"session_id":"id","cwd":"/repo","started_at":"2026-01-01T00:00:00Z","prompt":"fallback"}' + for (const messages of [ + '{"messages":[{"role":"user","content":"Ü🐋 first","ts":"2026-01-02T00:00:00Z"},{"role":"assistant","content":"answer","modelInfo":{"id":"sidecar"}}],"updated_at":"2026-01-03T00:00:00Z"}', + '{"messages":[{"role":"user","content":"old"}],"messages":[]}', + '{"messages":[{"role":"user","content":"partial"}]' + ]) { + expect( + await parseClineSessionDocuments( + file, + bytes(metadata), + () => bytes(messages), + 'darwin', + options + ) + ).toEqual(parseClineSessionContent(file, metadata, messages, 'darwin', options)) + } + }) +}) diff --git a/src/main/ai-vault/session-document-stream-projection.test.ts b/src/main/ai-vault/session-document-stream-projection.test.ts new file mode 100644 index 00000000000..2234153da37 --- /dev/null +++ b/src/main/ai-vault/session-document-stream-projection.test.ts @@ -0,0 +1,48 @@ +import { describe, it, expect } from 'vitest' +import { parseDevinSessionContent, parseDevinSessionDocument } from './session-scanner-devin-parser' +import { readStreamedSessionDocument } from './session-document-stream' +const file = { path: '/devin/test.json', modifiedAt: new Date(0).toISOString(), mtimeMs: 0 } +const options = { + executionHostId: 'ssh:projection' as const, + executionHostPlatform: 'darwin' as const +} +async function* bytes(content: string) { + const b = Buffer.from(content) + for (let i = 0; i < b.length; i += 7) { + yield b.subarray(i, i + 7) + } +} +describe('Devin consumed metadata projection', () => { + for (const suffix of [ + '{}', + 'null', + '[]', + '{"model":"last"}', + '{"model_name":"last-name","model":"fallback"}', + '{"model_name":[],"model":123}', + '{"model":"old","model":"last"}' + ]) { + it(`preserves duplicate root agent ${suffix}`, async () => { + const content = `{"agent":{"model_name":"old"},"steps":[{"role":"assistant","text":"message","metadata":{"generation_model":"step"}}],"generation_model":"root-fallback","agent":${suffix}}` + expect(await parseDevinSessionDocument(file, bytes(content), 'darwin', options)).toEqual( + parseDevinSessionContent(file, content, 'darwin', options) + ) + }) + } + it('retains only model fields from the agent object', async () => { + const result = await readStreamedSessionDocument({ + bytes: bytes( + '{"agent":{"ignored":{"many":[1,2,3]},"model_name":"root","model":"fallback"},"steps":[]}' + ), + arrayKey: 'steps', + fields: [], + objectFields: { agent: ['model_name', 'model'] }, + create: () => 0, + consume: () => {} + }) + expect(result).toEqual({ + record: { agent: { model_name: 'root', model: 'fallback' } }, + state: 0 + }) + }) +}) diff --git a/src/main/ai-vault/session-document-stream.ts b/src/main/ai-vault/session-document-stream.ts new file mode 100644 index 00000000000..4d12ab0fcc2 --- /dev/null +++ b/src/main/ai-vault/session-document-stream.ts @@ -0,0 +1,143 @@ +import { StringDecoder } from 'node:string_decoder' +import { JSONParser, TokenizerError, TokenParserError, TokenType } from '@streamparser/json' +import { setImmediate as yieldToEventLoop } from 'node:timers/promises' +import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' + +/** Fold one root array while retaining only the root fields the agent parser uses. */ +export async function readStreamedSessionDocument(args: { + bytes: AsyncIterable + arrayKey: string + fields: readonly string[] + objectFields?: Readonly> + create: () => T + consume: (state: T, value: unknown) => void + signal?: AbortSignal +}): Promise<{ record: Record; state: T } | null> { + const parser = new JSONParser({ + paths: [ + ...args.fields.map((field) => `$.${field}`), + ...Object.entries(args.objectFields ?? {}).flatMap(([root, fields]) => + fields.map((field) => `$.${root}.${field}`) + ), + ...(args.arrayKey ? [`$.${args.arrayKey}`, `$.${args.arrayKey}.*`] : []) + ], + keepStack: false, + stringBufferSize: 64 * 1024 + }) + const record: Record = Object.create(null) + const fields = new Set(args.fields) + let depth = 0 + let expectingRootKey = false + parser.onToken = ({ token, value }) => { + if (depth === 1 && expectingRootKey && token === TokenType.STRING) { + if (typeof value === 'string' && Object.hasOwn(args.objectFields ?? {}, value)) { + record[value] = Object.create(null) + } + expectingRootKey = false + } + if (token === TokenType.LEFT_BRACE || token === TokenType.LEFT_BRACKET) { + if (depth === 0 && token === TokenType.LEFT_BRACE) { + expectingRootKey = true + } + depth++ + } else if (token === TokenType.RIGHT_BRACE || token === TokenType.RIGHT_BRACKET) { + depth-- + } else if (token === TokenType.COMMA && depth === 1) { + expectingRootKey = true + } + } + let state = args.create() + let currentArray: unknown = null + let consumeFailure: { error: unknown } | undefined + const decoder = new StringDecoder('utf8') + let objectRoot: boolean | undefined + parser.onValue = ({ key, value, parent, stack }) => { + if (stack.length === 2 && stack[1].key === args.arrayKey && Array.isArray(parent)) { + if (parent !== currentArray) { + state = args.create() + consumeFailure = undefined + currentArray = parent + } + if (!consumeFailure) { + try { + args.consume(state, value) + } catch (error) { + consumeFailure = { error } + } + } + // The parser's array cursor is independent of retained array slots. + parent.pop() + } else if ( + stack.length === 2 && + typeof stack[1].key === 'string' && + typeof key === 'string' && + parent && + !Array.isArray(parent) + ) { + const root = stack[1].key + const projected = record[root] + if ( + Object.hasOwn(args.objectFields ?? {}, root) && + args.objectFields?.[root]?.includes(key) && + projected && + typeof projected === 'object' + ) { + Reflect.set(projected, key, value) + } + } else if (stack.length === 1 && typeof key === 'string') { + if (key === args.arrayKey) { + if (value !== currentArray || !Array.isArray(value)) { + state = args.create() + consumeFailure = undefined + } + currentArray = null + } else if (fields.has(key)) { + record[key] = value + } + if (parent && typeof parent === 'object') { + Reflect.deleteProperty(parent, key) + } + } + } + for await (const chunk of args.bytes) { + throwIfAiVaultScanCancelled(args.signal) + if (objectRoot === undefined) { + const first = chunk.find((byte) => byte !== 32 && byte !== 9 && byte !== 10 && byte !== 13) + if (first !== undefined) { + objectRoot = first === 123 + } + } + parseJson(() => parser.write(decoder.write(chunk))) + await yieldToEventLoop() + } + const tail = decoder.end() + if (tail) { + parseJson(() => parser.write(tail)) + } + if (objectRoot === undefined) { + throw new SyntaxError('Unexpected end of JSON input') + } + if (!parser.isEnded) { + parseJson(() => parser.end(), true) + } + throwIfAiVaultScanCancelled(args.signal) + if (consumeFailure) { + throw consumeFailure.error + } + return objectRoot ? { record, state } : null +} + +function parseJson(run: () => void, ending = false): void { + try { + run() + } catch (error) { + if ( + error instanceof TokenizerError || + error instanceof TokenParserError || + (ending && error instanceof Error) + ) { + throw new SyntaxError(error.message) + } + throw error + } +} diff --git a/src/main/ai-vault/session-scanner-antigravity-parser.ts b/src/main/ai-vault/session-scanner-antigravity-parser.ts index 126b56ce19a..775cc228370 100644 --- a/src/main/ai-vault/session-scanner-antigravity-parser.ts +++ b/src/main/ai-vault/session-scanner-antigravity-parser.ts @@ -1,4 +1,7 @@ -import { remoteSessionContentLines } from './remote-session-content-lines' +import { + remoteSessionContentLines, + type RemoteSessionContent +} from './remote-session-content-lines' import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' import type { AiVaultSession } from '../../shared/ai-vault-types' @@ -42,7 +45,7 @@ export async function parseAntigravitySessionFile( export async function parseAntigravitySessionContent( file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform = process.platform, options: ParserSessionOptions = {}, signal?: AbortSignal diff --git a/src/main/ai-vault/session-scanner-cline-parser.ts b/src/main/ai-vault/session-scanner-cline-parser.ts index 462108cfed9..5ef97f09cb0 100644 --- a/src/main/ai-vault/session-scanner-cline-parser.ts +++ b/src/main/ai-vault/session-scanner-cline-parser.ts @@ -1,3 +1,6 @@ +import { isMissingRemoteSessionPathError } from './remote-session-file-stat' +import { BinarySessionTranscriptError } from './remote-session-content-lines' +import { readStreamedSessionDocument } from './session-document-stream' import { wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' import type { AiVaultSession } from '../../shared/ai-vault-types' @@ -8,7 +11,7 @@ import { finalizeSession, updateTimeline } from './session-scanner-accumulator' -import type { FileWithMtime } from './session-scanner-types' +import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' import type { TranscriptMessageSink } from './session-transcript-consumers' import { arrayValue, @@ -93,21 +96,7 @@ export function parseClineSessionContent( if (messages) { updateTimeline(accumulator, messages.updated_at) for (const value of arrayValue(messages.messages)) { - const message = asRecord(value) - const role = message?.role - if (!message || (role !== 'user' && role !== 'assistant')) { - continue - } - accumulator.messageCount++ - updateTimeline(accumulator, message.ts) - const content = message.content - if (role === 'user' && !accumulator.fallbackTitle) { - accumulator.fallbackTitle = normalizeTitleText(extractContentText(content) ?? '') - } - if (role === 'assistant' && !accumulator.model) { - accumulator.model = extractString(asRecord(message.modelInfo)?.id) - } - addPreviewContent(accumulator, role, content, message.ts) + consumeClineSessionMessage(accumulator, value) } } accumulator.fallbackTitle ??= normalizeTitleText(extractString(metadata.prompt) ?? '') @@ -122,3 +111,88 @@ function parseJsonRecord(content: string): Record | null { return null } } + +function consumeClineSessionMessage(accumulator: SessionAccumulator, value: unknown): void { + const message = asRecord(value) + const role = message?.role + if (!message || (role !== 'user' && role !== 'assistant')) { + return + } + accumulator.messageCount++ + updateTimeline(accumulator, message.ts) + const content = message.content + if (role === 'user' && !accumulator.fallbackTitle) { + accumulator.fallbackTitle = normalizeTitleText(extractContentText(content) ?? '') + } + if (role === 'assistant' && !accumulator.model) { + accumulator.model = extractString(asRecord(message.modelInfo)?.id) + } + addPreviewContent(accumulator, role, content, message.ts) +} + +export async function parseClineSessionDocuments( + file: FileWithMtime, + metadataBytes: AsyncIterable, + readMessages: () => AsyncIterable, + platform: NodeJS.Platform, + options: ParserSessionOptions, + signal?: AbortSignal +): Promise { + let metadata: Record + try { + const parsed = await readStreamedSessionDocument({ + bytes: metadataBytes, + arrayKey: '', + fields: ['session_id', 'cwd', 'workspace_root', 'model', 'started_at', 'prompt'], + create: () => null, + consume: () => {}, + signal + }) + if (!parsed) { + return null + } + metadata = parsed.record + } catch (error) { + if (error instanceof SyntaxError) { + return null + } + throw error + } + const create = (): SessionAccumulator => { + const pathSegments = file.path.replace(/\\/g, '/').split('/').filter(Boolean) + const accumulator = createAccumulator({ + agent: 'cline', + file, + sessionId: extractString(metadata.session_id) ?? pathSegments.at(-2) ?? '' + }) + accumulator.cwd = extractString(metadata.cwd) ?? extractString(metadata.workspace_root) + accumulator.model = extractString(metadata.model) + updateTimeline(accumulator, metadata.started_at) + return accumulator + } + let accumulator = create() + try { + const parsed = await readStreamedSessionDocument({ + bytes: readMessages(), + arrayKey: 'messages', + fields: ['updated_at'], + create, + consume: consumeClineSessionMessage, + signal + }) + if (parsed) { + accumulator = parsed.state + updateTimeline(accumulator, parsed.record.updated_at) + } + } catch (error) { + if ( + !(error instanceof SyntaxError) && + !(error instanceof BinarySessionTranscriptError) && + !isMissingRemoteSessionPathError(error) + ) { + throw error + } + } + accumulator.fallbackTitle ??= normalizeTitleText(extractString(metadata.prompt) ?? '') + return finalizeSession(accumulator, platform, options) +} diff --git a/src/main/ai-vault/session-scanner-codex-parser.ts b/src/main/ai-vault/session-scanner-codex-parser.ts index b3571d4a337..beff5eb06b0 100644 --- a/src/main/ai-vault/session-scanner-codex-parser.ts +++ b/src/main/ai-vault/session-scanner-codex-parser.ts @@ -66,7 +66,7 @@ export async function parseCodexSessionFile( export async function parseCodexSessionContent(args: { file: FileWithMtime - content: string + content: string | AsyncIterable platform?: NodeJS.Platform codexHome?: string | null executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-copilot-parser.ts b/src/main/ai-vault/session-scanner-copilot-parser.ts index 239c5983457..a4d34fa5b13 100644 --- a/src/main/ai-vault/session-scanner-copilot-parser.ts +++ b/src/main/ai-vault/session-scanner-copilot-parser.ts @@ -1,4 +1,7 @@ -import { remoteSessionContentLines } from './remote-session-content-lines' +import { + remoteSessionContentLines, + type RemoteSessionContent +} from './remote-session-content-lines' import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' import type { AiVaultSession } from '../../shared/ai-vault-types' @@ -45,7 +48,7 @@ export async function parseCopilotSessionFile( export async function parseCopilotSessionContent( file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform = process.platform, options: ParserSessionOptions = {}, signal?: AbortSignal diff --git a/src/main/ai-vault/session-scanner-cursor-parser.ts b/src/main/ai-vault/session-scanner-cursor-parser.ts index bfa15caa530..a05817e2dc0 100644 --- a/src/main/ai-vault/session-scanner-cursor-parser.ts +++ b/src/main/ai-vault/session-scanner-cursor-parser.ts @@ -1,4 +1,7 @@ -import { remoteSessionContentLines } from './remote-session-content-lines' +import { + remoteSessionContentLines, + type RemoteSessionContent +} from './remote-session-content-lines' import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' import type { AiVaultSession } from '../../shared/ai-vault-types' @@ -43,7 +46,7 @@ export async function parseCursorSessionFile( export async function parseCursorSessionContent( file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform = process.platform, options: ParserSessionOptions = {}, signal?: AbortSignal diff --git a/src/main/ai-vault/session-scanner-devin-parser.ts b/src/main/ai-vault/session-scanner-devin-parser.ts index 12e40ef3fc2..d3a62b08a59 100644 --- a/src/main/ai-vault/session-scanner-devin-parser.ts +++ b/src/main/ai-vault/session-scanner-devin-parser.ts @@ -1,7 +1,8 @@ +import { readStreamedSessionDocument } from './session-document-stream' import { wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' import type { AiVaultSession } from '../../shared/ai-vault-types' import type { ExecutionHostId } from '../../shared/execution-host' -import type { FileWithMtime } from './session-scanner-types' +import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' import type { TranscriptMessageSink } from './session-transcript-consumers' import { addPreviewContent, @@ -70,38 +71,8 @@ function parseDevinSessionRecord( extractString(agentRecord?.model) ?? extractString(record.generation_model) accumulator.cwd = extractString(record.working_directory) - const steps = arrayValue(record.steps) - for (const step of steps) { - const stepRecord = asRecord(step) - if (!stepRecord) { - continue - } - const metadata = asRecord(stepRecord.metadata) - updateTimeline(accumulator, extractString(metadata?.created_at)) - const metrics = asRecord(metadata?.metrics) - accumulator.model ??= - extractString(metadata?.generation_model) ?? extractString(metrics?.generation_model) - accumulator.totalTokens += devinStepTokenTotal(metadata, metrics) - const isUser = metadata?.is_user_input === true - if (isUser) { - accumulator.messageCount++ - const text = - extractDevinStepText(stepRecord) ?? - extractContentText(stepRecord.content) ?? - extractString(stepRecord.text) - const titleCandidate = normalizeTitleText(text ?? '') - if (titleCandidate) { - accumulator.title ??= titleCandidate - } - addPreviewContent(accumulator, 'user', text ?? stepRecord.content) - } else if (extractString(stepRecord.role) === 'assistant' || stepRecord.tool_calls) { - accumulator.messageCount++ - addPreviewContent( - accumulator, - 'assistant', - extractDevinStepText(stepRecord) ?? stepRecord.content - ) - } + for (const step of arrayValue(record.steps)) { + consumeDevinSessionStep(accumulator, step) } return finalizeSession(accumulator, platform, options) } @@ -147,3 +118,71 @@ function numberFromDevinMetadata( } return 0 } + +export function consumeDevinSessionStep(accumulator: SessionAccumulator, step: unknown): void { + const stepRecord = asRecord(step) + if (!stepRecord) { + return + } + const metadata = asRecord(stepRecord.metadata) + updateTimeline(accumulator, extractString(metadata?.created_at)) + const metrics = asRecord(metadata?.metrics) + accumulator.model ??= + extractString(metadata?.generation_model) ?? extractString(metrics?.generation_model) + accumulator.totalTokens += devinStepTokenTotal(metadata, metrics) + const isUser = metadata?.is_user_input === true + if (isUser) { + accumulator.messageCount++ + const text = + extractDevinStepText(stepRecord) ?? + extractContentText(stepRecord.content) ?? + extractString(stepRecord.text) + const titleCandidate = normalizeTitleText(text ?? '') + if (titleCandidate) { + accumulator.title ??= titleCandidate + } + addPreviewContent(accumulator, 'user', text ?? stepRecord.content) + } else if (extractString(stepRecord.role) === 'assistant' || stepRecord.tool_calls) { + accumulator.messageCount++ + addPreviewContent( + accumulator, + 'assistant', + extractDevinStepText(stepRecord) ?? stepRecord.content + ) + } +} + +export async function parseDevinSessionDocument( + file: FileWithMtime, + bytes: AsyncIterable, + platform: NodeJS.Platform, + options: ParserSessionOptions, + signal?: AbortSignal +): Promise { + const parsed = await readStreamedSessionDocument({ + bytes, + arrayKey: 'steps', + fields: ['session_id', 'sessionId', 'generation_model', 'working_directory'], + objectFields: { agent: ['model_name', 'model'] }, + create: () => + createAccumulator({ agent: 'devin', file, sessionId: sessionIdFromFileName(file.path) }), + consume: consumeDevinSessionStep, + signal + }) + if (!parsed) { + return null + } + const { record, state: accumulator } = parsed + accumulator.sessionId = + extractString(record.session_id) ?? + extractString(record.sessionId) ?? + sessionIdFromFileName(file.path) + const agentRecord = asRecord(record.agent) + accumulator.model = + extractString(agentRecord?.model_name) ?? + extractString(agentRecord?.model) ?? + extractString(record.generation_model) ?? + accumulator.model + accumulator.cwd = extractString(record.working_directory) + return finalizeSession(accumulator, platform, options) +} diff --git a/src/main/ai-vault/session-scanner-droid-parser.ts b/src/main/ai-vault/session-scanner-droid-parser.ts index 748a8a6bcc9..7865ecc1827 100644 --- a/src/main/ai-vault/session-scanner-droid-parser.ts +++ b/src/main/ai-vault/session-scanner-droid-parser.ts @@ -1,4 +1,7 @@ -import { remoteSessionContentLines } from './remote-session-content-lines' +import { + remoteSessionContentLines, + type RemoteSessionContent +} from './remote-session-content-lines' import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' import type { AiVaultSession } from '../../shared/ai-vault-types' @@ -50,7 +53,7 @@ export async function parseDroidSessionFile( export async function parseDroidSessionContent( file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform = process.platform, options: ParserSessionOptions = {}, signal?: AbortSignal diff --git a/src/main/ai-vault/session-scanner-gemini-parsers.ts b/src/main/ai-vault/session-scanner-gemini-parsers.ts index efc9eef9e10..a1d7e259f79 100644 --- a/src/main/ai-vault/session-scanner-gemini-parsers.ts +++ b/src/main/ai-vault/session-scanner-gemini-parsers.ts @@ -1,3 +1,4 @@ +import { readStreamedSessionDocument } from './session-document-stream' import { remoteSessionContentLines } from './remote-session-content-lines' import { openTranscriptReadStream, wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' @@ -135,7 +136,7 @@ export function createGeminiJsonlSessionResumeState( ) } -async function parseGeminiJsonlSessionLines(args: { +export async function parseGeminiJsonlSessionLines(args: { file: FileWithMtime lines: AsyncIterable | Iterable platform: NodeJS.Platform @@ -173,3 +174,29 @@ export function consumeGeminiMessage( accumulator.totalTokens += tokenTotal(record.tokens) } } + +export async function parseGeminiSessionDocument( + file: FileWithMtime, + bytes: AsyncIterable, + platform: NodeJS.Platform, + options: ResumableParseFinalizeOptions, + signal?: AbortSignal +): Promise { + const parsed = await readStreamedSessionDocument({ + bytes, + arrayKey: 'messages', + fields: ['sessionId', 'startTime', 'lastUpdated'], + create: () => + createAccumulator({ agent: 'gemini', file, sessionId: sessionIdFromFileName(file.path) }), + consume: (state, value) => consumeGeminiMessage(state, asRecord(value)), + signal + }) + if (!parsed) { + return null + } + const { record, state: accumulator } = parsed + accumulator.sessionId = extractString(record.sessionId) ?? sessionIdFromFileName(file.path) + updateTimeline(accumulator, extractString(record.startTime)) + updateTimeline(accumulator, extractString(record.lastUpdated)) + return finalizeSession(accumulator, platform, options) +} diff --git a/src/main/ai-vault/session-scanner-graph-parsers.ts b/src/main/ai-vault/session-scanner-graph-parsers.ts index 581e885fd96..3ca4e754106 100644 --- a/src/main/ai-vault/session-scanner-graph-parsers.ts +++ b/src/main/ai-vault/session-scanner-graph-parsers.ts @@ -1,4 +1,7 @@ -import { remoteSessionContentLines } from './remote-session-content-lines' +import { + remoteSessionContentLines, + type RemoteSessionContent +} from './remote-session-content-lines' import { openTranscriptReadStream, wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' import { basename, dirname, join } from 'node:path' import { createInterface } from 'node:readline' @@ -195,7 +198,7 @@ export async function parseMessageGraphSessionFile( export async function parseMessageGraphSessionContent( agent: MessageGraphAgent, file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform = process.platform, options: ParserSessionOptions = {}, signal?: AbortSignal diff --git a/src/main/ai-vault/session-scanner-hermes-parser.ts b/src/main/ai-vault/session-scanner-hermes-parser.ts index f532fa8241d..784c53f0408 100644 --- a/src/main/ai-vault/session-scanner-hermes-parser.ts +++ b/src/main/ai-vault/session-scanner-hermes-parser.ts @@ -1,7 +1,8 @@ +import { readStreamedSessionDocument } from './session-document-stream' import { wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' import type { AiVaultSession } from '../../shared/ai-vault-types' import type { ExecutionHostId } from '../../shared/execution-host' -import type { FileWithMtime } from './session-scanner-types' +import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' import type { TranscriptMessageSink } from './session-transcript-consumers' import { addPreviewContent, @@ -69,18 +70,56 @@ async function parseHermesSessionRecord( updateTimeline(accumulator, extractString(record.session_start)) updateTimeline(accumulator, extractString(record.last_updated)) for (const message of arrayValue(record.messages)) { - const messageRecord = asRecord(message) - const role = extractString(messageRecord?.role) - if (role === 'user' || role === 'assistant') { - accumulator.messageCount++ - if (role === 'user') { - accumulator.title ??= extractContentText(messageRecord?.content) - } - addPreviewContent(accumulator, role, messageRecord?.content) - } + consumeHermesSessionMessage(accumulator, message) } if (accumulator.messageCount === 0) { accumulator.messageCount = numberValue(record.message_count) } return finalizeSession(accumulator, platform, options) } + +export function consumeHermesSessionMessage( + accumulator: SessionAccumulator, + message: unknown +): void { + const messageRecord = asRecord(message) + const role = extractString(messageRecord?.role) + if (role === 'user' || role === 'assistant') { + accumulator.messageCount++ + if (role === 'user') { + accumulator.title ??= extractContentText(messageRecord?.content) + } + addPreviewContent(accumulator, role, messageRecord?.content) + } +} + +export async function parseHermesSessionDocument( + file: FileWithMtime, + bytes: AsyncIterable, + platform: NodeJS.Platform, + options: ParserSessionOptions, + signal?: AbortSignal +): Promise { + const parsed = await readStreamedSessionDocument({ + bytes, + arrayKey: 'messages', + fields: ['session_id', 'model', 'cwd', 'session_start', 'last_updated', 'message_count'], + create: () => + createAccumulator({ agent: 'hermes', file, sessionId: sessionIdFromFileName(file.path) }), + consume: consumeHermesSessionMessage, + signal + }) + if (!parsed) { + return null + } + const { record, state: accumulator } = parsed + accumulator.sessionId = extractString(record.session_id) ?? sessionIdFromFileName(file.path) + accumulator.model = extractString(record.model) + accumulator.cwd = extractString(record.cwd) + updateTimeline(accumulator, extractString(record.session_start)) + updateTimeline(accumulator, extractString(record.last_updated)) + if (accumulator.messageCount === 0) { + accumulator.messageCount = numberValue(record.message_count) + } + return finalizeSession(accumulator, platform, options) +} diff --git a/src/main/ai-vault/session-scanner-primary-parsers.ts b/src/main/ai-vault/session-scanner-primary-parsers.ts index 62149920b5a..acd556b5504 100644 --- a/src/main/ai-vault/session-scanner-primary-parsers.ts +++ b/src/main/ai-vault/session-scanner-primary-parsers.ts @@ -1,4 +1,7 @@ -import { remoteSessionContentLines } from './remote-session-content-lines' +import { + remoteSessionContentLines, + type RemoteSessionContent +} from './remote-session-content-lines' import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' import type { AiVaultSession } from '../../shared/ai-vault-types' @@ -229,7 +232,7 @@ export async function parseClaudeSessionFile( export async function parseClaudeSessionContent( file: FileWithMtime, - content: string, + content: RemoteSessionContent, platform: NodeJS.Platform = process.platform, options: ParserSessionOptions = {}, signal?: AbortSignal diff --git a/src/main/browser/agent-browser-bridge-interaction-commands.ts b/src/main/browser/agent-browser-bridge-interaction-commands.ts index 51854878c0b..97fa3892ab9 100644 --- a/src/main/browser/agent-browser-bridge-interaction-commands.ts +++ b/src/main/browser/agent-browser-bridge-interaction-commands.ts @@ -12,6 +12,8 @@ import type { } from '../../shared/runtime-types' import { BrowserError } from './cdp-bridge' import { WAIT_PROCESS_TIMEOUT_GRACE_MS } from './agent-browser-bridge-types' +import { acquireElectronDebugger } from './electron-debugger-lease' +import { parseCdpKeyEvent, imeFallbackKeyEvent } from './cdp-keyboard-us-layout' import { AgentBrowserBridgeCaptureCommands } from './agent-browser-bridge-capture-commands' export abstract class AgentBrowserBridgeInteractionCommands extends AgentBrowserBridgeCaptureCommands { @@ -170,9 +172,70 @@ export abstract class AgentBrowserBridgeInteractionCommands extends AgentBrowser worktreeId?: string, browserPageId?: string ): Promise { - return this.enqueueTargetedCommand(worktreeId, browserPageId, async (sessionName) => { - return (await this.execAgentBrowser(sessionName, ['press', key])) as BrowserKeypressResult - }) + return this.enqueueTargetedCommand( + worktreeId, + browserPageId, + async (sessionName, target) => { + const parsed = parseCdpKeyEvent(key) ?? imeFallbackKeyEvent(key) + if (!parsed) { + // Why: a key name the table cannot express must not dispatch keyCode 0 and + // report success — route it to the helper, creating its session only now so + // the direct path never pays for it. + await this.ensureSession(sessionName, target.browserPageId, target.webContentsId) + return (await this.execAgentBrowser(sessionName, ['press', key])) as BrowserKeypressResult + } + const wc = this.getWebContents(target.webContentsId) + if (!wc || wc.isDestroyed()) { + throw new BrowserError( + 'browser_tab_not_found', + `Browser page ${target.browserPageId} is no longer available` + ) + } + const event = { + windowsVirtualKeyCode: parsed.keyCode, + nativeVirtualKeyCode: parsed.keyCode, + key: parsed.key, + code: parsed.code, + modifiers: parsed.modifiers, + location: parsed.location + } + let releaseDebugger = (): void => {} + try { + releaseDebugger = acquireElectronDebugger(wc).release + await wc.debugger.sendCommand('Input.dispatchKeyEvent', { + // Why: rawKeyDown is the no-character form; sending keyDown without text + // makes Blink synthesize an empty input for editing keys. + type: parsed.text === null ? 'rawKeyDown' : 'keyDown', + ...event, + ...(parsed.text === null ? {} : { text: parsed.text, unmodifiedText: parsed.text }) + }) + await wc.debugger.sendCommand('Input.dispatchKeyEvent', { + type: 'keyUp', + ...event, + // Why: the self bit is keydown-only -- Blink reports shiftKey false on the Shift keyup. + modifiers: parsed.modifiers & ~parsed.selfModifier + }) + return { pressed: key } + } catch (error) { + // Why: attach/dispatch reject with plain Errors, which the RPC layer would report as + // runtime_error — the helper path this replaced always produced a browser_* code, and + // the pane only reclaims a dead page when it sees one. + if (error instanceof BrowserError) { + throw error + } + if (!this.getWebContents(target.webContentsId)) { + throw this.createPageUnavailableError(sessionName) + } + throw new BrowserError( + 'browser_error', + `Failed to press ${key} in browser page ${target.browserPageId}: ${error instanceof Error ? error.message : String(error)}` + ) + } finally { + releaseDebugger() + } + }, + { ensureSession: false } + ) } async pdf(worktreeId?: string, browserPageId?: string): Promise { diff --git a/src/main/browser/agent-browser-bridge-keypress-input.test.ts b/src/main/browser/agent-browser-bridge-keypress-input.test.ts new file mode 100644 index 00000000000..3be23f31c76 --- /dev/null +++ b/src/main/browser/agent-browser-bridge-keypress-input.test.ts @@ -0,0 +1,292 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' + +const { execFileMock, webContentsFromIdMock, existsSyncMock, readFileSyncMock, stdinWrites } = + vi.hoisted(() => { + const stdinWrites: string[] = [] + return { + execFileMock: vi.fn(), + webContentsFromIdMock: vi.fn(), + existsSyncMock: vi.fn(() => false), + readFileSyncMock: vi.fn(() => Buffer.from('')), + stdinWrites + } + }) + +vi.mock('child_process', () => ({ execFile: execFileMock })) +vi.mock('fs', () => ({ + existsSync: existsSyncMock, + readFileSync: readFileSyncMock, + accessSync: vi.fn(), + chmodSync: vi.fn(), + constants: { X_OK: 1 } +})) +vi.mock('os', () => ({ platform: () => 'darwin', arch: () => 'arm64' })) +vi.mock('electron', () => { + return { + app: { getPath: vi.fn(() => '/app'), getAppPath: vi.fn(() => '/project'), isPackaged: false }, + webContents: { fromId: webContentsFromIdMock } + } +}) +const { CdpWsProxyMock } = vi.hoisted(() => { + const instances: unknown[] = [] + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const MockClass = vi.fn().mockImplementation(function (this: any, _wc: unknown) { + this._wc = _wc + this.start = vi.fn(async () => 'ws://127.0.0.1:9222') + this.stop = vi.fn(async () => {}) + this.getPort = vi.fn(() => 9222) + instances.push(this) + }) + return { CdpWsProxyMock: Object.assign(MockClass, { instances }) } +}) + +vi.mock('./cdp-ws-proxy', () => ({ + CdpWsProxy: CdpWsProxyMock +})) + +import { AgentBrowserBridge } from './agent-browser-bridge' +import { + createSucceedWith, + mockBrowserManager, + mockWebContents, + overrideBridgeWebContentsLookup, + resetAgentBrowserBridgeMocks, + type MockWebContents +} from './agent-browser-bridge-test-harness' + +overrideBridgeWebContentsLookup(AgentBrowserBridge.prototype, webContentsFromIdMock) + +const succeedWith = createSucceedWith(execFileMock, stdinWrites) + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null +} + +function isStringArray(value: unknown): value is string[] { + return Array.isArray(value) && value.every((entry) => typeof entry === 'string') +} + +function keyEventCalls(wc: MockWebContents): Record[] { + return wc.debugger.sendCommand.mock.calls + .filter(([method]) => method === 'Input.dispatchKeyEvent') + .map(([, params]) => params) + .filter(isRecord) +} + +describe('AgentBrowserBridge keypress input', () => { + let bridge: AgentBrowserBridge + let wc: MockWebContents + + beforeEach(() => { + resetAgentBrowserBridgeMocks({ + webContentsFromIdMock, + existsSyncMock, + readFileSyncMock, + stdinWrites, + cdpWsProxyInstances: CdpWsProxyMock.instances + }) + bridge = new AgentBrowserBridge(mockBrowserManager()) + bridge.setActiveTab(100) + wc = mockWebContents(100) + wc.debugger.sendCommand.mockResolvedValue({}) + webContentsFromIdMock.mockImplementation((id: number) => (id === 100 ? wc : null)) + }) + + it('dispatches a printable key over CDP without spawning agent-browser', async () => { + await expect(bridge.keypress('a', undefined, 'tab-1')).resolves.toEqual({ pressed: 'a' }) + + expect(execFileMock).not.toHaveBeenCalled() + expect(CdpWsProxyMock.instances).toHaveLength(0) + // Why: exactly two CDP calls, so the dispatch pair is the whole interaction. + expect(wc.debugger.sendCommand.mock.calls).toHaveLength(2) + expect(keyEventCalls(wc)).toEqual([ + { + type: 'keyDown', + windowsVirtualKeyCode: 65, + nativeVirtualKeyCode: 65, + key: 'a', + code: 'KeyA', + modifiers: 0, + location: 0, + text: 'a', + unmodifiedText: 'a' + }, + { + type: 'keyUp', + windowsVirtualKeyCode: 65, + nativeVirtualKeyCode: 65, + key: 'a', + code: 'KeyA', + modifiers: 0, + location: 0 + } + ]) + }) + + it('types & as shifted 7 instead of colliding with the ArrowUp virtual key code', async () => { + await bridge.keypress('&', undefined, 'tab-1') + + expect(keyEventCalls(wc)[0]).toMatchObject({ + type: 'keyDown', + windowsVirtualKeyCode: 55, + modifiers: 8, + text: '&' + }) + }) + + it('dispatches editing and navigation keys as rawKeyDown with no text', async () => { + await bridge.keypress('ArrowDown', undefined, 'tab-1') + + expect(keyEventCalls(wc)[0]).toMatchObject({ + type: 'rawKeyDown', + windowsVirtualKeyCode: 40, + key: 'ArrowDown' + }) + expect(keyEventCalls(wc)[0]).not.toHaveProperty('text') + }) + + it('carries modifier masks for shortcuts', async () => { + await expect(bridge.keypress('Ctrl+Shift+K', undefined, 'tab-1')).resolves.toEqual({ + pressed: 'Ctrl+Shift+K' + }) + + expect(keyEventCalls(wc)[0]).toMatchObject({ + type: 'rawKeyDown', + windowsVirtualKeyCode: 75, + modifiers: 10 + }) + }) + + it('reports the modifier bit on a bare Shift keydown but not on its keyup', async () => { + await bridge.keypress('Shift', undefined, 'tab-1') + + expect(keyEventCalls(wc)[0]).toMatchObject({ + type: 'rawKeyDown', + windowsVirtualKeyCode: 16, + code: 'ShiftLeft', + modifiers: 8, + location: 1 + }) + expect(keyEventCalls(wc)[1]).toMatchObject({ type: 'keyUp', modifiers: 0, location: 1 }) + }) + + it('keeps held modifiers on the keyup of a non-modifier shortcut key', async () => { + await bridge.keypress('Ctrl+Shift+K', undefined, 'tab-1') + + expect(keyEventCalls(wc)[1]).toMatchObject({ type: 'keyUp', modifiers: 10 }) + }) + + it('presses Enter with its carriage-return text so fields submit', async () => { + await bridge.keypress('Enter', undefined, 'tab-1') + + expect(keyEventCalls(wc)[0]).toMatchObject({ + type: 'keyDown', + windowsVirtualKeyCode: 13, + text: '\r' + }) + }) + + it('dispatches a non-US printable character as an IME-style event in process', async () => { + await expect(bridge.keypress('é', undefined, 'tab-1')).resolves.toEqual({ pressed: 'é' }) + + expect(execFileMock).not.toHaveBeenCalled() + expect(keyEventCalls(wc)[0]).toMatchObject({ + type: 'keyDown', + windowsVirtualKeyCode: 229, + key: 'é', + code: '', + text: 'é', + unmodifiedText: 'é' + }) + expect(keyEventCalls(wc)[1]).toMatchObject({ type: 'keyUp', windowsVirtualKeyCode: 229 }) + }) + + it('keeps the helper for a surrogate-pair character', async () => { + succeedWith({ pressed: '👍' }) + + await expect(bridge.keypress('👍', undefined, 'tab-1')).resolves.toEqual({ pressed: '👍' }) + + expect(keyEventCalls(wc)).toHaveLength(0) + }) + + it('falls back to agent-browser for a key name the table cannot express', async () => { + succeedWith({ pressed: 'MediaPlayPause' }) + + await expect(bridge.keypress('MediaPlayPause', undefined, 'tab-1')).resolves.toEqual({ + pressed: 'MediaPlayPause' + }) + + expect(keyEventCalls(wc)).toHaveLength(0) + const pressCall = execFileMock.mock.calls + .map(([, commandArgs]) => commandArgs) + .filter(isStringArray) + .find((commandArgs) => commandArgs.includes('press')) + expect(pressCall).toBeDefined() + const args = pressCall ?? [] + expect(args[args.indexOf('press') + 1]).toBe('MediaPlayPause') + }) + + it('rejects with tab not found when the page is gone', async () => { + webContentsFromIdMock.mockReturnValue(null) + + await expect(bridge.keypress('a', undefined, 'tab-1')).rejects.toMatchObject({ + code: 'browser_tab_not_found' + }) + }) + + // Why: one keypress looks the page up three times — the queued target, the + // automation-visibility refresh, then the dispatch guard. Serving the first N keeps the + // later ones on the guard; the trailing assertions fail loudly if that count ever moves. + function killPageAfterLookups(lookups: number): () => number { + let remaining = lookups + webContentsFromIdMock.mockImplementation((id: number) => { + if (id !== 100 || remaining === 0) { + return null + } + remaining -= 1 + return wc + }) + return () => remaining + } + + it('rejects with tab not found when the page dies after its target is resolved', async () => { + const remaining = killPageAfterLookups(2) + + await expect(bridge.keypress('a', undefined, 'tab-1')).rejects.toMatchObject({ + code: 'browser_tab_not_found' + }) + expect(remaining()).toBe(0) + expect(keyEventCalls(wc)).toHaveLength(0) + }) + + it('rejects with tab not found when the page dies mid-dispatch', async () => { + const remaining = killPageAfterLookups(3) + wc.debugger.sendCommand.mockRejectedValue(new Error('Inspected target navigated or closed')) + + await expect(bridge.keypress('a', undefined, 'tab-1')).rejects.toMatchObject({ + code: 'browser_tab_not_found' + }) + expect(remaining()).toBe(0) + }) + + it('reports a dispatch failure on a live page as a browser error', async () => { + wc.debugger.sendCommand.mockRejectedValue(new Error('Debugger is not attached to the target')) + + await expect(bridge.keypress('a', undefined, 'tab-1')).rejects.toMatchObject({ + code: 'browser_error', + message: expect.stringContaining('Debugger is not attached to the target') + }) + }) + + it('reports a debugger attach failure as a browser error', async () => { + wc.debugger.isAttached.mockReturnValue(false) + wc.debugger.attach.mockImplementation(() => { + throw new Error('Another debugger is already attached to the debug target') + }) + + await expect(bridge.keypress('a', undefined, 'tab-1')).rejects.toMatchObject({ + code: 'browser_error' + }) + expect(keyEventCalls(wc)).toHaveLength(0) + }) +}) diff --git a/src/main/browser/cdp-keyboard-us-layout.test.ts b/src/main/browser/cdp-keyboard-us-layout.test.ts new file mode 100644 index 00000000000..b9bcffa50ec --- /dev/null +++ b/src/main/browser/cdp-keyboard-us-layout.test.ts @@ -0,0 +1,133 @@ +import { describe, it, expect } from 'vitest' +import { imeFallbackKeyEvent, parseCdpKeyEvent } from './cdp-keyboard-us-layout' + +describe('parseCdpKeyEvent', () => { + it('maps every printable ASCII character to a key event that types that character', () => { + const broken: string[] = [] + for (let charCode = 32; charCode <= 126; charCode++) { + const ch = String.fromCharCode(charCode) + const parsed = parseCdpKeyEvent(ch) + if (!parsed || parsed.text !== ch || parsed.keyCode === 0) { + broken.push(ch) + } + } + expect(broken).toEqual([]) + }) + + it.each([ + ['#', 51], + ['$', 52], + ['%', 53], + ['&', 55], + ["'", 222], + ['(', 57], + ['.', 190] + ])( + 'gives %s the US-layout key code %i instead of its own char code', + (ch: string, keyCode: number) => { + // Why: charCodeAt-derived codes put '&' on VK_UP (38) and '.' on VK_DELETE (46), + // which Blink executes as caret commands that swallow the character. + expect(parseCdpKeyEvent(ch)).toMatchObject({ keyCode, text: ch }) + } + ) + + it.each([ + ['Ctrl+A', { keyCode: 65, key: 'a', modifiers: 2, text: null }], + ['Control+a', { keyCode: 65, key: 'a', modifiers: 2, text: null }], + ['Shift+Home', { keyCode: 36, key: 'Home', modifiers: 8, text: null }], + ['Alt+ArrowDown', { keyCode: 40, key: 'ArrowDown', modifiers: 1, text: null }], + ['Ctrl+Shift+K', { keyCode: 75, key: 'K', modifiers: 10, text: null }], + ['Meta+r', { keyCode: 82, key: 'r', modifiers: 4, text: null }], + ['Control+Shift+r', { keyCode: 82, key: 'R', modifiers: 10, text: null }] + ])('parses the shortcut %s', (raw: string, expected: object) => { + expect(parseCdpKeyEvent(raw)).toMatchObject(expected) + }) + + it('treats a capital letter in a shortcut as the key name, not a shift request', () => { + expect(parseCdpKeyEvent('Ctrl+A')).toMatchObject({ key: 'a', modifiers: 2 }) + expect(parseCdpKeyEvent('Ctrl+Shift+A')).toMatchObject({ key: 'A', modifiers: 10 }) + }) + + it('shifts a bare capital letter and reports the shifted character as text', () => { + expect(parseCdpKeyEvent('R')).toMatchObject({ keyCode: 82, key: 'R', modifiers: 8, text: 'R' }) + expect(parseCdpKeyEvent('Shift+a')).toMatchObject({ key: 'A', modifiers: 8, text: 'A' }) + }) + + it('maps shifted punctuation onto its base key with shift held', () => { + expect(parseCdpKeyEvent('Shift+1')).toMatchObject({ keyCode: 49, key: '!', text: '!' }) + expect(parseCdpKeyEvent('+')).toMatchObject({ keyCode: 187, modifiers: 8, text: '+' }) + }) + + it.each([ + ['Enter', { keyCode: 13, text: '\r' }], + ['Space', { keyCode: 32, key: ' ', text: ' ' }], + ['Esc', { keyCode: 27, key: 'Escape', text: null }], + ['PgDn', { keyCode: 34, key: 'PageDown', text: null }], + ['ContextMenu', { keyCode: 93, text: null }], + ['F5', { keyCode: 116, key: 'F5', code: 'F5', text: null }], + ['F12', { keyCode: 123, text: null }] + ])('parses the named key %s', (raw: string, expected: object) => { + expect(parseCdpKeyEvent(raw)).toMatchObject(expected) + }) + + it.each([ + ['Shift', { keyCode: 16, key: 'Shift', code: 'ShiftLeft', modifiers: 8, selfModifier: 8 }], + ['Ctrl', { keyCode: 17, key: 'Control', code: 'ControlLeft', modifiers: 2, selfModifier: 2 }], + ['Alt', { keyCode: 18, key: 'Alt', code: 'AltLeft', modifiers: 1, selfModifier: 1 }], + ['Meta', { keyCode: 91, key: 'Meta', code: 'MetaLeft', modifiers: 4, selfModifier: 4 }] + ])( + 'reports the own modifier bit and left-side location for a bare %s press', + (raw: string, expected: object) => { + expect(parseCdpKeyEvent(raw)).toMatchObject({ ...expected, location: 1, text: null }) + } + ) + + it('adds the self bit on top of held modifiers for a modifier-only chord', () => { + expect(parseCdpKeyEvent('Ctrl+Shift')).toMatchObject({ + keyCode: 16, + modifiers: 10, + selfModifier: 8 + }) + }) + + it('reports no self bit or location for non-modifier keys', () => { + expect(parseCdpKeyEvent('Enter')).toMatchObject({ location: 0, selfModifier: 0 }) + expect(parseCdpKeyEvent('a')).toMatchObject({ location: 0, selfModifier: 0 }) + expect(parseCdpKeyEvent('Ctrl+A')).toMatchObject({ location: 0, selfModifier: 0 }) + }) + + it.each([['MediaPlayPause'], ['F25'], [''], ['NoSuchKey']])( + 'returns null for %s so the caller can fall back', + (raw: string) => { + expect(parseCdpKeyEvent(raw)).toBeNull() + } + ) +}) + +describe('imeFallbackKeyEvent', () => { + it.each([['é'], ['ß'], ['ñ'], ['ü'], ['漢'], ['한']])( + 'gives %s the IME key event form with keyCode 229 and its text', + (ch: string) => { + expect(imeFallbackKeyEvent(ch)).toEqual({ + keyCode: 229, + key: ch, + code: '', + modifiers: 0, + location: 0, + selfModifier: 0, + text: ch + }) + } + ) + + it.each([ + ['a table-covered ASCII character', 'a'], + ['a surrogate-pair emoji', '👍'], + ['a combining sequence', 'e\u0301'], + ['a multi-character name', 'MediaPlayPause'], + ['a chord with a non-US character', 'Ctrl+é'], + ['an empty string', ''] + ])('returns null for %s so the helper keeps its behavior', (_name: string, raw: string) => { + expect(imeFallbackKeyEvent(raw)).toBeNull() + }) +}) diff --git a/src/main/browser/cdp-keyboard-us-layout.ts b/src/main/browser/cdp-keyboard-us-layout.ts new file mode 100644 index 00000000000..23de58a7241 --- /dev/null +++ b/src/main/browser/cdp-keyboard-us-layout.ts @@ -0,0 +1,251 @@ +// Why: deriving a virtual key code from a character's own char code collides with editing +// keys — '&' (38) arrives as VK_UP and '.' (46) as VK_DELETE, so Blink runs the caret +// command and silently drops the character. This table maps Orca key names ("a", "&", +// "Ctrl+Shift+K", "Alt+ArrowDown", "F5") to the CDP key event a US-layout keyboard +// would produce; anything it cannot express returns null so the caller can fall back. + +const CDP_MODIFIER_BITS: Record = { + alt: 1, + option: 1, + ctrl: 2, + control: 2, + cmd: 4, + command: 4, + meta: 4, + super: 4, + win: 4, + shift: 8 +} + +// name -> [windowsVirtualKeyCode, key, code, text] +const CDP_NAMED_KEYS: Record = { + enter: [13, 'Enter', 'Enter', '\r'], + return: [13, 'Enter', 'Enter', '\r'], + tab: [9, 'Tab', 'Tab', null], + backspace: [8, 'Backspace', 'Backspace', null], + delete: [46, 'Delete', 'Delete', null], + del: [46, 'Delete', 'Delete', null], + escape: [27, 'Escape', 'Escape', null], + esc: [27, 'Escape', 'Escape', null], + space: [32, ' ', 'Space', ' '], + spacebar: [32, ' ', 'Space', ' '], + arrowup: [38, 'ArrowUp', 'ArrowUp', null], + up: [38, 'ArrowUp', 'ArrowUp', null], + arrowdown: [40, 'ArrowDown', 'ArrowDown', null], + down: [40, 'ArrowDown', 'ArrowDown', null], + arrowleft: [37, 'ArrowLeft', 'ArrowLeft', null], + left: [37, 'ArrowLeft', 'ArrowLeft', null], + arrowright: [39, 'ArrowRight', 'ArrowRight', null], + right: [39, 'ArrowRight', 'ArrowRight', null], + home: [36, 'Home', 'Home', null], + end: [35, 'End', 'End', null], + pageup: [33, 'PageUp', 'PageUp', null], + pgup: [33, 'PageUp', 'PageUp', null], + pagedown: [34, 'PageDown', 'PageDown', null], + pgdn: [34, 'PageDown', 'PageDown', null], + pgdown: [34, 'PageDown', 'PageDown', null], + insert: [45, 'Insert', 'Insert', null], + ins: [45, 'Insert', 'Insert', null], + contextmenu: [93, 'ContextMenu', 'ContextMenu', null], + apps: [93, 'ContextMenu', 'ContextMenu', null], + capslock: [20, 'CapsLock', 'CapsLock', null], + numlock: [144, 'NumLock', 'NumLock', null], + scrolllock: [145, 'ScrollLock', 'ScrollLock', null], + pause: [19, 'Pause', 'Pause', null], + printscreen: [44, 'PrintScreen', 'PrintScreen', null], + shift: [16, 'Shift', 'ShiftLeft', null], + control: [17, 'Control', 'ControlLeft', null], + ctrl: [17, 'Control', 'ControlLeft', null], + alt: [18, 'Alt', 'AltLeft', null], + option: [18, 'Alt', 'AltLeft', null], + meta: [91, 'Meta', 'MetaLeft', null], + cmd: [91, 'Meta', 'MetaLeft', null], + command: [91, 'Meta', 'MetaLeft', null] +} + +// Characters a US keyboard produces with shift held, and the base key they share. +const US_SHIFTED_CHARS: Record = { + '~': '`', + '!': '1', + '@': '2', + '#': '3', + $: '4', + '%': '5', + '^': '6', + '&': '7', + '*': '8', + '(': '9', + ')': '0', + _: '-', + '+': '=', + '{': '[', + '}': ']', + '|': '\\', + ':': ';', + '"': "'", + '<': ',', + '>': '.', + '?': '/' +} + +const US_SHIFT_OF: Record = {} +for (const shifted of Object.keys(US_SHIFTED_CHARS)) { + US_SHIFT_OF[US_SHIFTED_CHARS[shifted]] = shifted +} + +// char -> [windowsVirtualKeyCode, code], for the keys that are not letters or digits. +const US_PUNCTUATION_KEYS: Record = { + ' ': [32, 'Space'], + ';': [186, 'Semicolon'], + '=': [187, 'Equal'], + ',': [188, 'Comma'], + '-': [189, 'Minus'], + '.': [190, 'Period'], + '/': [191, 'Slash'], + '`': [192, 'Backquote'], + '[': [219, 'BracketLeft'], + '\\': [220, 'Backslash'], + ']': [221, 'BracketRight'], + "'": [222, 'Quote'] +} + +type UsKeyboardKey = { + keyCode: number + code: string + shift: boolean +} + +function usKeyboardKeyForChar(ch: string): UsKeyboardKey | null { + if (ch >= 'a' && ch <= 'z') { + return { keyCode: ch.charCodeAt(0) - 32, code: `Key${ch.toUpperCase()}`, shift: false } + } + if (ch >= 'A' && ch <= 'Z') { + return { keyCode: ch.charCodeAt(0), code: `Key${ch}`, shift: true } + } + if (ch >= '0' && ch <= '9') { + return { keyCode: ch.charCodeAt(0), code: `Digit${ch}`, shift: false } + } + if (Object.hasOwn(US_SHIFTED_CHARS, ch)) { + const base = usKeyboardKeyForChar(US_SHIFTED_CHARS[ch]) + return base === null ? null : { keyCode: base.keyCode, code: base.code, shift: true } + } + if (Object.hasOwn(US_PUNCTUATION_KEYS, ch)) { + return { keyCode: US_PUNCTUATION_KEYS[ch][0], code: US_PUNCTUATION_KEYS[ch][1], shift: false } + } + return null +} + +export type CdpKeyEvent = { + keyCode: number + key: string + code: string + modifiers: number + // Why: 1 = left-side key -- the table pins bare modifiers to ShiftLeft/ControlLeft/etc. + location: number + // Why: a modifier key's own bit is set during its keydown but already cleared on its keyup. + selfModifier: number + // Why: null means the key produces no character (a rawKeyDown, not a keyDown with text). + text: string | null +} + +// Why: printable characters outside the table (accented letters, non-latin scripts) +// still have an in-process form -- the IME convention, keyCode 229 with the text, +// which is how composed input already reaches pages. One BMP code point only: +// surrogate pairs and combining sequences keep the helper's behavior. +export function imeFallbackKeyEvent(raw: string): CdpKeyEvent | null { + if (raw.length !== 1) { + return null + } + const codePoint = raw.charCodeAt(0) + if (codePoint < 0xa0 || (codePoint >= 0xd800 && codePoint <= 0xdfff)) { + return null + } + return { keyCode: 229, key: raw, code: '', modifiers: 0, location: 0, selfModifier: 0, text: raw } +} + +export function parseCdpKeyEvent(raw: string): CdpKeyEvent | null { + if (raw.length === 0) { + return null + } + let rest = raw + let modifiers = 0 + while (rest.length > 1) { + const plus = rest.indexOf('+') + if (plus <= 0) { + break + } + const name = rest.slice(0, plus).toLowerCase() + if (!Object.hasOwn(CDP_MODIFIER_BITS, name)) { + break + } + modifiers |= CDP_MODIFIER_BITS[name] + rest = rest.slice(plus + 1) + } + if (rest.length === 0) { + return null + } + + let keyCode: number + let key: string + let code: string + let text: string | null + let location = 0 + let selfModifier = 0 + if (rest.length === 1) { + const mapped = usKeyboardKeyForChar(rest) + if (mapped === null) { + return null + } + keyCode = mapped.keyCode + key = rest + code = mapped.code + text = rest + // Why: a capital letter in a shortcut is how people write the key, not a request for + // shift — Ctrl+A means select-all (key 'a'), never Ctrl+Shift+A. Shifted punctuation + // is different: on a US keyboard shift is the only way to produce the character. + const capitalShortcut = rest >= 'A' && rest <= 'Z' && (modifiers & ~8) !== 0 + if (capitalShortcut) { + key = rest.toLowerCase() + text = key + } else if (mapped.shift) { + modifiers |= 8 + } + } else if (Object.hasOwn(CDP_NAMED_KEYS, rest.toLowerCase())) { + const name = rest.toLowerCase() + const named = CDP_NAMED_KEYS[name] + keyCode = named[0] + key = named[1] + code = named[2] + text = named[3] + // Why: Blink reports a modifier's own bit during its keydown (shiftKey is true while + // Shift goes down), and the table's modifier entries are the left-side keys. + selfModifier = CDP_MODIFIER_BITS[name] ?? 0 + if (selfModifier !== 0) { + modifiers |= selfModifier + location = 1 + } + } else { + const functionKey = /^f([1-9]|1[0-9]|2[0-4])$/i.exec(rest) + if (functionKey === null) { + return null + } + keyCode = 111 + Number(functionKey[1]) + key = `F${functionKey[1]}` + code = key + text = null + } + + if (text !== null && (modifiers & 8) !== 0) { + text = Object.hasOwn(US_SHIFT_OF, text) ? US_SHIFT_OF[text] : text.toUpperCase() + // Why: Shift+a is the "A" key as far as the page is concerned. + if (rest.length === 1) { + key = text + } + } + // Why: with ctrl, alt or meta held the press is a shortcut and produces no character. + if ((modifiers & ~8) !== 0) { + text = null + } + + return { keyCode, key, code, modifiers, location, selfModifier, text } +} diff --git a/src/main/claude/claude-prompt-journaling.ts b/src/main/claude/claude-prompt-journaling.ts new file mode 100644 index 00000000000..99b163fe197 --- /dev/null +++ b/src/main/claude/claude-prompt-journaling.ts @@ -0,0 +1,46 @@ +// Journaling an approval or question prompt, and remembering the rows it wrote +// so a cancellation can tombstone exactly those. + +import type { AgentJournalItemIdentity } from '../../shared/agent-session-journal-types' +import { agentJournalItemKey } from '../../shared/agent-session-journal-item-key' +import type { StructuredAgentSessionEventSink } from '../native-chat/agent-session-wire/structured-agent-session-event-sink' +import type { ClaudeStructuredSessionEvent } from './claude-structured-session-state' +import { + claudeApprovalItem, + claudePromptIdentity, + claudeQuestionItems +} from './claude-structured-prompt-items' + +export type ClaudePromptJournalDeps = { + sink: StructuredAgentSessionEventSink + bindPromptItemId?: (journalItemId: string, promptKey: string, questionId?: string) => void + /** Prompt key → the rows it wrote, owned by the translator so a cancel can sweep them. */ + promptItems: Map +} + +export function journalClaudePrompt( + deps: ClaudePromptJournalDeps, + event: Extract +): void { + const identities: AgentJournalItemIdentity[] = [] + if (event.prompt.kind === 'question') { + for (const question of claudeQuestionItems({ + sessionId: event.sessionId, + prompt: event.prompt + })) { + identities.push(question.identity) + deps.sink.appendItem(question.identity, question.body) + deps.bindPromptItemId?.(agentJournalItemKey(question.identity), event.prompt.promptKey) + } + } else { + const identity = claudePromptIdentity({ + sessionId: event.sessionId, + promptKey: event.prompt.promptKey + }) + identities.push(identity) + deps.sink.appendItem(identity, claudeApprovalItem(event.prompt)) + deps.bindPromptItemId?.(agentJournalItemKey(identity), event.prompt.promptKey) + } + deps.promptItems.set(event.prompt.promptKey, identities) + deps.sink.publish() +} diff --git a/src/main/claude/claude-session-end-hook-capability.test.ts b/src/main/claude/claude-session-end-hook-capability.test.ts new file mode 100644 index 00000000000..755cdcbe498 --- /dev/null +++ b/src/main/claude/claude-session-end-hook-capability.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, it } from 'vitest' +import { + CLAUDE_SESSION_END_CAPABILITY_FLOOR, + claudeVersionSupportsSessionEnd, + parseClaudeCliVersion +} from './claude-session-end-hook-capability' + +describe('Claude SessionEnd hook version capability', () => { + it('records 2.1.261 as the measured floor', () => { + expect(CLAUDE_SESSION_END_CAPABILITY_FLOOR).toBe('2.1.261') + }) + + it('extracts Claude Code version output', () => { + expect(parseClaudeCliVersion('2.1.261 (Claude Code)')).toBe('2.1.261') + }) + + it.each([ + ['2.1.260', false], + ['2.1.261', true], + ['2.2.0', true], + ['unknown', false], + [undefined, false] + ])('classifies %s as SessionEnd-capable: %s', (version, expected) => { + expect(claudeVersionSupportsSessionEnd(version)).toBe(expected) + }) +}) diff --git a/src/main/claude/claude-session-end-hook-capability.ts b/src/main/claude/claude-session-end-hook-capability.ts new file mode 100644 index 00000000000..1587c154e7b --- /dev/null +++ b/src/main/claude/claude-session-end-hook-capability.ts @@ -0,0 +1,41 @@ +import { hasReachedAppVersion, isValidAppVersion } from '../../shared/app-version' +import { runProcess } from '../../shared/child-process/run-process' +import path from 'node:path' + +// 2.1.261 is the only version measured, not an established minimum. +export const CLAUDE_SESSION_END_CAPABILITY_FLOOR = '2.1.261' + +export function parseClaudeCliVersion(output: string | null | undefined): string | null { + const version = output?.match(/\b\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?\b/)?.[0] + return version && isValidAppVersion(version) ? version : null +} + +export function claudeVersionSupportsSessionEnd(version: string | null | undefined): boolean { + const parsed = parseClaudeCliVersion(version) + return parsed !== null && hasReachedAppVersion(parsed, CLAUDE_SESSION_END_CAPABILITY_FLOOR) +} + +export async function probeClaudeCliVersion(executablePath: string): Promise { + try { + const pathKey = process.platform === 'win32' && process.env.Path !== undefined ? 'Path' : 'PATH' + const executableDir = path.dirname(executablePath) + const inheritedPath = process.env[pathKey] + const result = await runProcess({ + program: executablePath, + args: ['--version'], + // Why: version-manager launchers often use `#!/usr/bin/env node`; the resolved CLI's sibling + // runtime must remain reachable even when Electron started with a thinner PATH. + env: { + ...process.env, + [pathKey]: inheritedPath + ? `${executableDir}${path.delimiter}${inheritedPath}` + : executableDir + }, + timeoutMs: 5_000, + maxOutputBytes: 4_096 + }) + return result.code === 0 ? parseClaudeCliVersion(`${result.stdout}\n${result.stderr}`) : null + } catch { + return null + } +} diff --git a/src/main/claude/claude-session-end-install.test.ts b/src/main/claude/claude-session-end-install.test.ts new file mode 100644 index 00000000000..46f374ca7ae --- /dev/null +++ b/src/main/claude/claude-session-end-install.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it } from 'vitest' +import { applyManagedHooks } from './hook-settings' + +const SCRIPT_FILE_NAME = 'claude-hook.sh' +const MANAGED_COMMAND = '/home/dev/.orca/agent-hooks/claude-hook.sh' +const managedHook = { type: 'command' as const, command: MANAGED_COMMAND } + +describe('Claude SessionEnd managed hook capability', () => { + it('installs SessionEnd beside SessionStart for the measured capable version', () => { + const written = applyManagedHooks({ hooks: {} }, managedHook, SCRIPT_FILE_NAME, { + claudeVersion: '2.1.261 (Claude Code)' + }) + + expect(written.hooks?.SessionEnd?.[0]?.hooks?.[0]?.command).toBe(MANAGED_COMMAND) + expect(written.hooks?.SessionStart?.[0]?.hooks?.[0]?.command).toBe(MANAGED_COMMAND) + }) + + it.each(['2.1.260', 'unknown', undefined])( + 'retains the legacy event set for an incapable or unverified host (%s)', + (claudeVersion) => { + const written = applyManagedHooks({ hooks: {} }, managedHook, SCRIPT_FILE_NAME, { + claudeVersion + }) + + expect(written.hooks?.SessionEnd).toBeUndefined() + expect(written.hooks?.SessionStart).toBeDefined() + } + ) + + it('removes only Orca SessionEnd during a capability downgrade', () => { + const capable = applyManagedHooks( + { + hooks: { + SessionEnd: [{ hooks: [{ type: 'command', command: 'echo user-session-end' }] }] + } + }, + managedHook, + SCRIPT_FILE_NAME, + { claudeVersion: '2.1.261' } + ) + const downgraded = applyManagedHooks(capable, managedHook, SCRIPT_FILE_NAME, { + claudeVersion: '2.1.260' + }) + + expect(downgraded.hooks?.SessionEnd).toEqual([ + { hooks: [{ type: 'command', command: 'echo user-session-end' }] } + ]) + }) +}) diff --git a/src/main/claude/claude-structured-journal-translation.test.ts b/src/main/claude/claude-structured-journal-translation.test.ts index 7a8ecf54344..65be68bb05f 100644 --- a/src/main/claude/claude-structured-journal-translation.test.ts +++ b/src/main/claude/claude-structured-journal-translation.test.ts @@ -220,10 +220,15 @@ describe('Claude structured journal translation', () => { for (const event of turn.start) { translator.handle(event) } + expect(lifecycleAppends(state.items)).toEqual([ + ['turn-lifecycle:msg_01-message-start', 'running'] + ]) + expect(assistantMessages(state.items)).toEqual([]) + for (const delta of turn.deltas) { translator.handle(delta) } - expect(state.items).toEqual([]) + expect(assistantMessages(state.items)).toEqual([]) const run = scheduled as (() => void) | null run?.() @@ -568,7 +573,11 @@ describe('Claude structured journal translation', () => { translator.handle(message('assistant', 'assistant-thinking', [{ type: 'thinking', thinking }])) - expect(state.items.at(-1)?.body).toEqual({ + // The frame also opens the turn it produced in, so pick the reasoning row itself. + const reasoning = state.items.find( + (item) => item.body.kind === 'message' && item.body.role === 'reasoning' + ) + expect(reasoning?.body).toEqual({ kind: 'message', role: 'reasoning', blocks: [ diff --git a/src/main/claude/claude-structured-journal-translation.ts b/src/main/claude/claude-structured-journal-translation.ts index 8b71149cba2..702ff5f6b26 100644 --- a/src/main/claude/claude-structured-journal-translation.ts +++ b/src/main/claude/claude-structured-journal-translation.ts @@ -10,7 +10,6 @@ import type { ClaudeStructuredSessionEvent } from './claude-structured-session-s import { claudeMessageBody, claudeMessageIdentity, - claudeHasReplayContent, claudeOutputEnvelope, claudeStreamingMessageBody, claudeThinkingIdentity, @@ -22,15 +21,11 @@ import { readClaudeMessageEnvelope, type ClaudeToolUse } from './claude-structured-item-translation' -import { - claudeApprovalItem, - claudePromptIdentity, - claudeQuestionItems -} from './claude-structured-prompt-items' +import { journalClaudePrompt } from './claude-prompt-journaling' import type { ClaudePromptRegistry } from './claude-structured-prompt-replies' import { claudeProviderFrameActivity } from '../native-chat/agent-session-wire/provider-frame-activity' import { - appendUnmodeledClaudeContent, + appendUnmodeledContent, claudeProviderFrameKind, claudeResultFailure, createClaudeProviderFrameFallback, @@ -39,6 +34,14 @@ import { import { ClaudeSubagentRoster } from './claude-subagent-roster' import { createClaudeStreamedBlockRegistry } from './claude-streamed-block-identity' import { createClaudeStreamedTextCheckpoints } from './claude-streamed-text-checkpoints' +import { + claudeStreamTurnStartSource, + claudeStreamTurnSource, + claudeTurnOpenedBySendEcho, + createClaudeTurnOpener, + isRootClaudeFrame, + type ClaudeTurnSource +} from './claude-turn-opening' import { claudeTurnEndForResult, claudeTurnLifecycleItem, @@ -84,6 +87,10 @@ export function createClaudeJournalTranslator( const promptItems = new Map() const streamedBlocks = createClaudeStreamedBlockRegistry() let currentTurn: ClaudeCurrentTurn | null = null + /** Provider output may not reopen a turn after the session ended or a turn + * failed: nothing would ever close the turn it opened, and the row would read + * working for the life of the session. Only an accepted send lifts it. */ + let reopenSuppressed = false const groupKeyOf = (turn: ClaudeCurrentTurn | null): string | null => turn ? `${turn.sessionId}:${turn.turnId}` : null const providerFallback = createClaudeProviderFrameFallback( @@ -110,6 +117,28 @@ export function createClaudeJournalTranslator( deps.sink.publish({ coalescingKey: item.publishCoalescingKey }) } + /** Open a turn, ending whichever one was still open. A new turn starting is the + * only end the previous one gets when its result never arrives; settling it + * later would sweep THIS turn. */ + const openTurn = (turn: ClaudeCurrentTurn, observedAt: number): void => { + if (currentTurn) { + subagents.settleTurn(groupKeyOf(currentTurn)) + publishLifecycle(currentTurn, { state: 'interrupted', completedAt: observedAt }) + } + currentTurn = turn + publishLifecycle(turn) + deps.sink.setActivity?.(null) + } + + /** The provider produced, so a turn is running. Idempotent: every frame of one + * reply stays inside the turn its first frame opened. A subagent's output is + * its parent turn's work and never a turn of its own. */ + const ensureTurnOpen = createClaudeTurnOpener({ + isTurnOpen: () => currentTurn !== null, + isSuppressed: () => reopenSuppressed, + open: openTurn + }) + const publishActivity = (kind: string, payload: unknown): void => { if (!currentTurn) { return @@ -120,8 +149,12 @@ export function createClaudeJournalTranslator( } } - const handleStream = (message: Record): boolean => { + const handleStream = (message: Record, observedAt: number): boolean => { const delta = streamedBlocks.observe(message) + // `message_start` is the provider's turn boundary. Keep the first text + // delta as a compatibility fallback for streams that omit it. + const source = delta ? claudeStreamTurnSource(message) : claudeStreamTurnStartSource(message) + ensureTurnOpen(message, source, observedAt) if (!delta) { return false } @@ -149,11 +182,23 @@ export function createClaudeJournalTranslator( (body && envelope.role === 'assistant' ? streamedBlocks.reconcile(envelope) : null) ?? claudeMessageIdentity(envelope) streamedText.forget(agentJournalItemKey(identity)) + const thinking = claudeThinkingText(outputEnvelope) + const source: ClaudeTurnSource = { + sessionId: envelope.sessionId, + uuid: envelope.uuid, + assistant: envelope.role === 'assistant' + } + const openOutputTurn = (): void => ensureTurnOpen(message, source, observedAt) if (body) { + // Opening before the append is what brackets a turn around its own first + // output; a reader that scans back to the turn record and stops would + // otherwise look straight past the row that opened it. + ensureTurnOpen(message, source, observedAt) deps.sink.appendItem(identity, body) changed = true } for (const tool of claudeToolUses(outputEnvelope)) { + ensureTurnOpen(message, source, observedAt) tools.set(tool.id, tool) deps.sink.appendItem( claudeToolIdentity(envelope.sessionId, tool.id), @@ -177,8 +222,8 @@ export function createClaudeJournalTranslator( tools.delete(result.toolUseId) changed = true } - const thinking = claudeThinkingText(outputEnvelope) if (thinking) { + ensureTurnOpen(message, source, observedAt) deps.sink.appendItem(claudeThinkingIdentity(envelope.sessionId, envelope.uuid), { kind: 'message', role: 'reasoning', @@ -188,28 +233,19 @@ export function createClaudeJournalTranslator( }) changed = true } - changed = appendUnmodeledClaudeContent(providerFallback, outputEnvelope, message) || changed - if ( - envelope.role === 'user' && - startsTurn && - claudeHasReplayContent(envelope) && - message.parent_tool_use_id === null - ) { - if (currentTurn) { - // A new turn starting is the only end the previous one gets when its - // result never arrives; settling it later would sweep THIS turn. - subagents.settleTurn(groupKeyOf(currentTurn)) - publishLifecycle(currentTurn, { state: 'interrupted', completedAt: observedAt }) - } - currentTurn = { - sessionId: envelope.sessionId, - turnId: envelope.uuid, - startedAt: observedAt, - // A user echo lands on its own message identity, so this is the user row's key. - userItemId: agentJournalItemKey(identity) - } - publishLifecycle(currentTurn) - deps.sink.setActivity?.(null) + changed = + appendUnmodeledContent(providerFallback, outputEnvelope, message, openOutputTurn) || changed + // The send's turn is anchored to the user row journaled just above it. + const sendEchoTurn = claudeTurnOpenedBySendEcho({ + envelope, + frame: message, + startsTurn, + observedAt, + userItemId: agentJournalItemKey(identity) + }) + if (sendEchoTurn) { + reopenSuppressed = false + openTurn(sendEchoTurn, observedAt) } if (changed) { deps.sink.publish() @@ -217,30 +253,6 @@ export function createClaudeJournalTranslator( return true } - const handlePrompt = (event: Extract): void => { - const identities: AgentJournalItemIdentity[] = [] - if (event.prompt.kind === 'question') { - for (const question of claudeQuestionItems({ - sessionId: event.sessionId, - prompt: event.prompt - })) { - identities.push(question.identity) - deps.sink.appendItem(question.identity, question.body) - deps.bindPromptItemId?.(agentJournalItemKey(question.identity), event.prompt.promptKey) - } - } else { - const identity = claudePromptIdentity({ - sessionId: event.sessionId, - promptKey: event.prompt.promptKey - }) - identities.push(identity) - deps.sink.appendItem(identity, claudeApprovalItem(event.prompt)) - deps.bindPromptItemId?.(agentJournalItemKey(identity), event.prompt.promptKey) - } - promptItems.set(event.prompt.promptKey, identities) - deps.sink.publish() - } - return { handle: (event) => { if (event.type === 'ended') { @@ -255,15 +267,18 @@ export function createClaudeJournalTranslator( }) currentTurn = null } + // A frame that arrives after the child is gone must not open a turn no + // event can close. + reopenSuppressed = true deps.sink.setActivity?.(null) return } - if (event.type === 'message' && handleStream(event.message)) { + if (event.type === 'message' && handleStream(event.message, event.observedAt ?? Date.now())) { return } streamedText.flush() if (event.type === 'prompt') { - handlePrompt(event) + journalClaudePrompt({ ...deps, promptItems }, event) } else if (event.type === 'prompt-cancelled') { for (const identity of promptItems.get(event.promptKey) ?? []) { deps.sink.appendTombstone(identity) @@ -271,22 +286,33 @@ export function createClaudeJournalTranslator( promptItems.delete(event.promptKey) deps.sink.publish() } else if (event.type === 'message' && event.message.type === 'result') { - // The turn is over however it ended, so a foreground child still - // reported as working will never be settled by an event. - subagents.settleTurn(groupKeyOf(currentTurn)) - if (currentTurn) { - publishLifecycle( - currentTurn, - claudeTurnEndForResult(event.message, event.observedAt ?? Date.now()) - ) - currentTurn = null + // Every turn this translator opens is root by construction, so a nested + // result settles the child that produced it and never the turn. The + // diagnostic below still runs: a child's failure is reportable even when + // it ends no turn. + const settlesTurn = isRootClaudeFrame(event.message) + if (settlesTurn) { + // The turn is over however it ended, so a foreground child still + // reported as working will never be settled by an event. + // A turn that failed, or that the user stopped, is not resumed by + // whatever the provider says next; the next send is what resumes it. + // The latch only ever sets here; an accepted send is what lifts it. + reopenSuppressed ||= event.message.is_error === true + subagents.settleTurn(groupKeyOf(currentTurn)) + if (currentTurn) { + publishLifecycle( + currentTurn, + claudeTurnEndForResult(event.message, event.observedAt ?? Date.now()) + ) + currentTurn = null + } + deps.sink.setActivity?.(null) + // The turn is over. A block still awaiting its final keeps the text the + // flush above journaled, but its live state goes: an interrupted turn + // would otherwise retain that text for the life of the session. + streamedBlocks.clear() + streamedText.settle() } - deps.sink.setActivity?.(null) - // The turn is over. A block still awaiting its final keeps the text the - // flush above journaled, but its live state goes: an interrupted turn - // would otherwise retain that text for the life of the session. - streamedBlocks.clear() - streamedText.settle() const kind = claudeProviderFrameKind(event.message) // Ordinary turn bookkeeping stays suppressed; a reported failure never does. const failure = claudeResultFailure(event.message) diff --git a/src/main/claude/claude-structured-model-catalog.ts b/src/main/claude/claude-structured-model-catalog.ts new file mode 100644 index 00000000000..8ea79eba3d5 --- /dev/null +++ b/src/main/claude/claude-structured-model-catalog.ts @@ -0,0 +1,109 @@ +import type { + AgentSessionModelOption, + AgentSessionOptionChoice +} from '../../shared/agent-session-wire' +import { CLAUDE_SESSION_OPTION_CATALOG } from '../../shared/agent-session-option-catalog-claude-codex' +import type { CatalogModel } from '../../shared/agent-session-option-catalog-types' + +export type ListedModel = AgentSessionModelOption & { resolvedModel: string | null } + +export function record(value: unknown): Record | null { + return typeof value === 'object' && value !== null && !Array.isArray(value) + ? (value as Record) + : null +} + +export function text(value: unknown): string | null { + return typeof value === 'string' && value.trim() ? value : null +} + +function effortLabel(value: string): string { + return value === 'xhigh' ? 'Extra high' : `${value.charAt(0).toUpperCase()}${value.slice(1)}` +} + +function listedEfforts(row: Record): AgentSessionOptionChoice[] { + return row.supportsEffort === true && Array.isArray(row.supportedEffortLevels) + ? row.supportedEffortLevels.flatMap((value) => { + const effort = text(value) + return effort ? [{ value: effort, label: effortLabel(effort) }] : [] + }) + : [] +} + +export function listedModels(value: unknown): ListedModel[] { + const response = record(value) + const rows = Array.isArray(response?.models) + ? response.models.map(record).filter((row): row is Record => row !== null) + : [] + const defaultRow = rows.find((row) => text(row.value) === 'default') + const defaultResolvedModel = text(defaultRow?.resolvedModel) + const seen = new Set() + return rows.flatMap((row) => { + const id = text(row.value) + if (!id || id === 'default' || seen.has(id)) { + return [] + } + seen.add(id) + const resolvedModel = text(row.resolvedModel) + const description = text(row.description) + const supportsFastMode = + typeof row.supportsFastMode === 'boolean' ? row.supportsFastMode : undefined + return [ + { + id, + label: text(row.displayName) ?? id, + ...(description ? { description } : {}), + isDefault: resolvedModel !== null && resolvedModel === defaultResolvedModel, + efforts: listedEfforts(row), + ...(supportsFastMode !== undefined ? { supportsFastMode } : {}), + resolvedModel + } + ] + }) +} + +/** Alias matcher for the Fast-mode guards: a pick stored as an alias, as the resolved + * id, or as the literal `default` finds the same row. The effort and admit guards + * match on alias and resolved id only — neither ever resolved `default`, and widening + * them here would tighten what they refuse. */ +export function matchListedModel( + models: readonly ListedModel[], + modelId: string +): ListedModel | undefined { + return models.find( + (model) => + model.id === modelId || + model.resolvedModel === modelId || + (modelId === 'default' && model.isDefault) + ) +} + +function seedEfforts(model: CatalogModel): AgentSessionOptionChoice[] { + const effort = model.options.find((option) => option.id === 'effort') + return effort?.kind.type === 'select' ? effort.kind.choices : [] +} + +export function seedModels(): ListedModel[] { + return CLAUDE_SESSION_OPTION_CATALOG.models.map((model) => ({ + id: model.id, + label: model.label, + ...(model.description ? { description: model.description } : {}), + isDefault: model.isDefault === true, + efforts: seedEfforts(model), + resolvedModel: null + })) +} + +export function currentModelId(models: ListedModel[], reportedModel: string | undefined): string { + const matched = reportedModel + ? models.find( + (model) => + model.id === reportedModel || + model.resolvedModel === reportedModel || + (reportedModel === 'default' && model.isDefault) + ) + : undefined + return ( + matched?.id ?? reportedModel ?? models.find((model) => model.isDefault)?.id ?? models[0]!.id + ) +} diff --git a/src/main/claude/claude-structured-options.test.ts b/src/main/claude/claude-structured-options.test.ts index 1bfae10b592..9b962fc33d7 100644 --- a/src/main/claude/claude-structured-options.test.ts +++ b/src/main/claude/claude-structured-options.test.ts @@ -1,8 +1,15 @@ import { describe, expect, it, vi } from 'vitest' -import { setClaudeStructuredOption } from './claude-structured-options' +import { + restoreClaudeStructuredSessionOptions, + setClaudeStructuredOption +} from './claude-structured-options' import type { ClaudeSession } from './claude-structured-session-state' import { ClaudeBackgroundTaskTracker } from './claude-background-task-tracker' import { ClaudeSlashCommandCatalog } from './claude-slash-command-catalog' +import { + observeClaudeFastModeFacts, + readClaudeStructuredSessionOptions +} from './claude-structured-session-options' function sessionFor(setModel: ClaudeSession['connection']['setModel']): ClaudeSession { return { @@ -58,3 +65,375 @@ describe('Claude structured option mutation fencing', () => { expect(session.options).toEqual(new Map([['model', 'new']])) }) }) + +function fastModeSession(supportsFastMode: boolean | undefined) { + let reportedFastMode = false + const applyFlagSettings = vi.fn(async (settings: { fastMode?: boolean }) => { + if (typeof settings.fastMode === 'boolean') { + reportedFastMode = settings.fastMode + } + }) + const session = sessionFor(vi.fn(async () => undefined)) + session.options.set('model', 'opus') + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the literal supplies every connection member this fixture's code paths call, and the spread carries the rest from sessionFor. + session.connection = { + ...session.connection, + supportedModels: async () => [ + { + value: 'opus', + resolvedModel: 'claude-opus-current', + displayName: 'Opus', + ...(supportsFastMode === undefined ? {} : { supportsFastMode }) + } + ], + applyFlagSettings, + getSettings: async () => ({ effective: { fastMode: reportedFastMode } }) + } as ClaudeSession['connection'] + return { session, applyFlagSettings } +} + +describe('Claude structured Fast mode', () => { + it('applies absolute on and off values and confirms provider readback', async () => { + const { session, applyFlagSettings } = fastModeSession(true) + + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).resolves.toMatchObject({ fastMode: 'true' }) + expect(session.confirmedOptions.has('fastMode')).toBe(true) + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'false' }, undefined) + ).resolves.toMatchObject({ fastMode: 'false' }) + expect(applyFlagSettings).toHaveBeenNthCalledWith( + 1, + { fastMode: true }, + { timeoutMs: undefined } + ) + expect(applyFlagSettings).toHaveBeenNthCalledWith( + 2, + { fastMode: false }, + { timeoutMs: undefined } + ) + }) + + it('rejects definitively unsupported Fast before applying', async () => { + const { session, applyFlagSettings } = fastModeSession(false) + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).rejects.toThrow('does not support Fast mode') + expect(applyFlagSettings).not.toHaveBeenCalled() + }) + + it('does not authorize a new Fast enable when model support is unknown', async () => { + const { session, applyFlagSettings } = fastModeSession(undefined) + + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).rejects.toThrow('does not support Fast mode') + expect(applyFlagSettings).not.toHaveBeenCalled() + }) + + it.each([undefined, false])( + 'allows explicit Fast off when model support is %s', + async (supportsFastMode) => { + const { session, applyFlagSettings } = fastModeSession(supportsFastMode) + + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'false' }, undefined) + ).resolves.toMatchObject({ fastMode: 'false' }) + expect(applyFlagSettings).toHaveBeenCalledWith({ fastMode: false }, { timeoutMs: undefined }) + } + ) + + // Turning Fast off needs no support evidence, so it must not pay a catalog round + // trip — restore replays a stored `false` on every acquire. + it('reads no catalog to turn Fast off, but does to turn it on', async () => { + const { session } = fastModeSession(true) + const listed = session.connection.supportedModels + let reads = 0 + session.connection.supportedModels = async (...args: Parameters) => { + reads += 1 + return listed(...args) + } + + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'false' }, undefined) + ).resolves.toMatchObject({ fastMode: 'false' }) + expect(reads).toBe(0) + + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).resolves.toMatchObject({ fastMode: 'true' }) + expect(reads).toBe(1) + }) + + it('restores explicit Fast off when model support is unknown', async () => { + const { session, applyFlagSettings } = fastModeSession(undefined) + session.options.set('fastMode', 'false') + + await restoreClaudeStructuredSessionOptions(session, undefined) + + expect(session.options.get('fastMode')).toBe('false') + expect(session.restoreSkippedOptions.has('fastMode')).toBe(false) + expect(applyFlagSettings).toHaveBeenCalledWith({ fastMode: false }, { timeoutMs: undefined }) + }) + + it('resolves the running CLI default model before applying Fast', async () => { + const { session, applyFlagSettings } = fastModeSession(true) + session.options.delete('model') + session.connection.supportedModels = async () => [ + { value: 'default', resolvedModel: 'claude-opus-current', displayName: 'Default' }, + { + value: 'opus[1m]', + resolvedModel: 'claude-opus-current', + displayName: 'Opus (1M context)', + supportsFastMode: true + } + ] + + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).resolves.toMatchObject({ fastMode: 'true' }) + expect(applyFlagSettings).toHaveBeenCalledWith({ fastMode: true }, { timeoutMs: undefined }) + }) + + it('rejects Fast on when the running session reports a blocking reason', async () => { + const { session, applyFlagSettings } = fastModeSession(true) + session.fastModeDisabledReason = 'extra_usage_disabled' + + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).rejects.toThrow('extra_usage_disabled') + expect(applyFlagSettings).not.toHaveBeenCalled() + }) + + // The child omits the reason when nothing blocks Fast, so a later unblocked frame is + // the only all-clear. Without it the first reason latches and the control never returns. + it('clears a blocking reason once a later frame reports state without one', async () => { + const { session } = fastModeSession(true) + + observeClaudeFastModeFacts(session, { + fast_mode_state: 'off', + fast_mode_disabled_reason: 'model_not_allowed' + }) + expect(session.fastModeDisabledReason).toBe('model_not_allowed') + await expect(readClaudeStructuredSessionOptions(session, undefined)).resolves.toMatchObject({ + fastModeSupport: { supported: false, reason: 'model_not_allowed' } + }) + + // Switched back to a model that allows Fast: state reported, reason omitted. + observeClaudeFastModeFacts(session, { fast_mode_state: 'on' }) + expect(session.fastModeDisabledReason).toBeUndefined() + await expect(readClaudeStructuredSessionOptions(session, undefined)).resolves.toMatchObject({ + fastModeSupport: { supported: true } + }) + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).resolves.toMatchObject({ fastMode: 'true' }) + }) + + it('reconciles an earlier Fast request to a later provider readback', async () => { + const { session } = fastModeSession(true) + session.options.set('fastMode', 'true') + session.connection.getSettings = async () => ({ effective: { fastMode: false } }) + + await expect(readClaudeStructuredSessionOptions(session, undefined)).resolves.toMatchObject({ + current: { fastMode: false, confirmed: ['fastMode'] } + }) + expect(session.options.get('fastMode')).toBe('false') + expect(session.confirmedOptions.has('fastMode')).toBe(true) + }) + + it('keeps the Fast preference on during cooldown when settings report it on', async () => { + const { session } = fastModeSession(true) + session.options.set('fastMode', 'false') + session.connection.getSettings = async () => ({ effective: { fastMode: true } }) + observeClaudeFastModeFacts(session, { fast_mode_state: 'cooldown' }) + + await expect(readClaudeStructuredSessionOptions(session, undefined)).resolves.toMatchObject({ + current: { fastMode: true, fastModeState: 'cooldown', confirmed: ['fastMode'] } + }) + expect(session.options.get('fastMode')).toBe('true') + expect(session.confirmedOptions.has('fastMode')).toBe(true) + }) + + it('publishes support and explicit false from running CLI reports', async () => { + const { session } = fastModeSession(true) + observeClaudeFastModeFacts(session, { + fast_mode_state: 'cooldown', + fast_mode_disabled_reason: null + }) + await expect(readClaudeStructuredSessionOptions(session, undefined)).resolves.toMatchObject({ + models: [expect.objectContaining({ id: 'opus', supportsFastMode: true })], + fastModeSupport: { supported: true }, + current: { + model: 'opus', + fastMode: false, + fastModeState: 'cooldown', + confirmed: ['fastMode'] + } + }) + }) + + it('hides Fast when the running CLI reports a blocking session reason', async () => { + const { session } = fastModeSession(true) + observeClaudeFastModeFacts(session, { + fast_mode_state: 'off', + fast_mode_disabled_reason: 'not_first_party' + }) + + await expect(readClaudeStructuredSessionOptions(session, undefined)).resolves.toMatchObject({ + fastModeSupport: { supported: false, reason: 'not_first_party' }, + current: { fastMode: false, fastModeState: 'off' } + }) + }) + + it('reconciles Fast off when switching to a model without support', async () => { + const { session, applyFlagSettings } = fastModeSession(true) + session.options.set('fastMode', 'true') + session.connection.supportedModels = async () => [ + { value: 'opus', displayName: 'Opus', supportsFastMode: true }, + { value: 'haiku', displayName: 'Haiku', supportsFastMode: false } + ] + + await expect( + setClaudeStructuredOption(session, { key: 'model', value: 'haiku' }, undefined) + ).resolves.toMatchObject({ model: 'haiku', fastMode: 'false' }) + expect(applyFlagSettings).toHaveBeenCalledWith({ fastMode: false }, { timeoutMs: undefined }) + }) + + it('keeps Fast on across a model switch while support discovery is transient', async () => { + const { session, applyFlagSettings } = fastModeSession(true) + session.options.set('fastMode', 'true') + session.connection.supportedModels = async () => { + throw new Error('catalog temporarily unavailable') + } + + await expect( + setClaudeStructuredOption(session, { key: 'model', value: 'haiku' }, undefined) + ).resolves.toMatchObject({ model: 'haiku', fastMode: 'true' }) + expect(applyFlagSettings).not.toHaveBeenCalled() + }) + + it('reconciles a transient model switch once support is definitively unavailable', async () => { + const { session } = fastModeSession(true) + session.options.set('fastMode', 'true') + session.connection.supportedModels = async () => { + throw new Error('catalog temporarily unavailable') + } + await setClaudeStructuredOption(session, { key: 'model', value: 'haiku' }, undefined) + session.connection.supportedModels = async () => [ + { value: 'opus', displayName: 'Opus', supportsFastMode: true }, + { value: 'haiku', displayName: 'Haiku', supportsFastMode: false } + ] + + await expect(readClaudeStructuredSessionOptions(session, undefined)).resolves.toMatchObject({ + current: { model: 'haiku', fastMode: false } + }) + expect(session.options.get('fastMode')).toBe('false') + expect(session.confirmedOptions.has('fastMode')).toBe(true) + }) + + it('keeps the accepted model when the unsupported-model Fast-off write fails', async () => { + const { session, applyFlagSettings } = fastModeSession(true) + session.options.set('fastMode', 'true') + session.reportedOptions.fastMode = true + session.confirmedOptions.add('fastMode') + session.connection.supportedModels = async () => [ + { value: 'opus', displayName: 'Opus', supportsFastMode: true }, + { value: 'haiku', displayName: 'Haiku', supportsFastMode: false } + ] + applyFlagSettings.mockRejectedValueOnce(new Error('flag write failed')) + + await expect( + setClaudeStructuredOption(session, { key: 'model', value: 'haiku' }, undefined) + ).resolves.toMatchObject({ model: 'haiku', fastMode: 'false' }) + expect(session.reportedOptions.fastMode).toBe(true) + expect(session.confirmedOptions.has('fastMode')).toBe(false) + }) + + it('treats an unrecognized provider disabled reason as unavailable', async () => { + const { session, applyFlagSettings } = fastModeSession(true) + observeClaudeFastModeFacts(session, { + fast_mode_state: 'off', + fast_mode_disabled_reason: 'future_entitlement_rule' + }) + + await expect(readClaudeStructuredSessionOptions(session, undefined)).resolves.toMatchObject({ + fastModeSupport: { supported: false, reason: 'future_entitlement_rule' } + }) + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).rejects.toThrow('future_entitlement_rule') + expect(applyFlagSettings).not.toHaveBeenCalled() + }) +}) + +describe('Claude Fast mode against a catalog that identifies nothing', () => { + /** + * A CLI whose catalog answers with nothing identifies no model, so it is not + * evidence against one — the same rule the model admit-check already applies. + * Refusing here would have Fast unavailable on every model of a CLI that cannot + * answer, while a catalog that did list the model and stayed silent about Fast + * still refuses. + */ + it('allows Fast on when the catalog identifies no model at all', async () => { + const { session, applyFlagSettings } = fastModeSession(true) + session.connection.supportedModels = async () => [] + + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).resolves.toMatchObject({ fastMode: 'true' }) + expect(applyFlagSettings).toHaveBeenCalledWith({ fastMode: true }, { timeoutMs: undefined }) + }) + + it('still refuses Fast on when the catalog lists the model and omits Fast support', async () => { + const { session, applyFlagSettings } = fastModeSession(undefined) + + await expect( + setClaudeStructuredOption(session, { key: 'fastMode', value: 'true' }, undefined) + ).rejects.toThrow('does not support Fast mode') + expect(applyFlagSettings).not.toHaveBeenCalled() + }) +}) + +describe('Claude Fast mode reported by the session frame alone', () => { + /** + * Measured against a running Claude session: the first `agentSession.options` + * read carries `fastModeState: 'off'` while `effective.fastMode` is still absent, + * so the two are not redundant — the frame answers at a moment the boolean has no + * answer. Without this the picker asks the user to disambiguate a value the + * provider already reported. + */ + function frameOnlySession(state: 'off' | 'on' | 'cooldown') { + const { session } = fastModeSession(true) + // Settings are silent on Fast, exactly as observed on a fresh session. + session.connection.getSettings = async () => ({ effective: { effortLevel: 'high' } }) + observeClaudeFastModeFacts(session, { fast_mode_state: state }) + return session + } + + it('reports Fast off from the session frame when settings never carry it', async () => { + const result = await readClaudeStructuredSessionOptions(frameOnlySession('off'), undefined) + + expect(result.current.fastMode).toBe(false) + expect(result.current.confirmed).toContain('fastMode') + }) + + it('reads a throttled session as on, since cooldown throttles routing not the pick', async () => { + await expect( + readClaudeStructuredSessionOptions(frameOnlySession('on'), undefined) + ).resolves.toMatchObject({ current: { fastMode: true } }) + await expect( + readClaudeStructuredSessionOptions(frameOnlySession('cooldown'), undefined) + ).resolves.toMatchObject({ current: { fastMode: true, fastModeState: 'cooldown' } }) + }) + + it('stays unknown when neither settings nor a session frame report Fast', async () => { + const { session } = fastModeSession(true) + session.connection.getSettings = async () => ({ effective: { effortLevel: 'high' } }) + + const result = await readClaudeStructuredSessionOptions(session, undefined) + + expect(result.current.fastMode).toBeUndefined() + }) +}) diff --git a/src/main/claude/claude-structured-options.ts b/src/main/claude/claude-structured-options.ts index 7f607755563..c85e233cde1 100644 --- a/src/main/claude/claude-structured-options.ts +++ b/src/main/claude/claude-structured-options.ts @@ -6,13 +6,17 @@ import { } from '../native-chat/agent-session-wire/structured-agent-session-option-error' import { claudeCatalogAdmitsModel, + claudeModelEffortLevels, + claudeModelFastModeSupport, readClaudeCurrentModel, - readClaudeModelEffortLevels, - readClaudeSettingsEffort + readClaudeListedModels, + readClaudeSettingsEffort, + readClaudeSettingsFastMode } from './claude-structured-session-options' import type { ClaudeSession } from './claude-structured-session-state' +import { decodeStructuredAgentSessionOptionValue } from '../../shared/structured-agent-session-option-codec' -const OPTION_ORDER = ['model', 'effort', 'permissionMode'] as const +const OPTION_ORDER = ['model', 'effort', 'fastMode', 'permissionMode'] as const /** * Efforts the settings readback cannot report. `max` applies for the rest of the @@ -38,6 +42,10 @@ export async function setClaudeStructuredOption( input: { key: string; value: string }, timeoutMs: number | undefined ): Promise>> { + const fastMode = + input.key === 'fastMode' + ? decodeStructuredAgentSessionOptionValue('fastMode', input.value) + : null const apply = input.key === 'model' ? () => session.connection.setModel(input.value, { timeoutMs }) @@ -49,31 +57,71 @@ export async function setClaudeStructuredOption( { effortLevel: input.value as EffortLevel }, { timeoutMs } ) - : null + : input.key === 'fastMode' && typeof fastMode === 'boolean' + ? () => session.connection.applyFlagSettings({ fastMode }, { timeoutMs }) + : null if (!apply) { throw new AgentSessionOptionRejectedError( `claude stream-json has no session option named ${input.key}` ) } + // One read answers every catalog question this write asks, so the guards below + // cannot each pay a round trip for the same list nor disagree about the model. + // Two writes ask nothing of it and so read nothing: an effort write with no current + // model has nothing to look up, and turning Fast off needs no support evidence — + // which is every restore replaying a stored `false`. + const needsCatalog = + input.key === 'model' || + (input.key === 'fastMode' && fastMode === true) || + (input.key === 'effort' && readClaudeCurrentModel(session).id !== undefined) + const listed = needsCatalog ? await readClaudeListedModels(session, timeoutMs) : [] // The child stores an effort its model has no control for and keeps it across // every later model switch and restore, so refuse before the write rather than // read the acceptance back as adoption. Refused here, restore drops the stale // value instead of replaying it onto a model that cannot use it. if (input.key === 'effort') { - const { modelId, levels } = await readClaudeModelEffortLevels(session, timeoutMs) + const { modelId, levels } = claudeModelEffortLevels(session, listed) if (levels && !levels.has(input.value)) { throw new AgentSessionOptionRejectedError( `claude model ${modelId} does not accept effort ${input.value}` ) } } + if (input.key === 'fastMode') { + if (typeof fastMode !== 'boolean') { + throw new AgentSessionOptionRejectedError('claude fast mode must be encoded as true or false') + } + const support = claudeModelFastModeSupport(session, listed) + // A catalog that identified nothing is not evidence against this model, the same + // rule the admit-check below applies — otherwise a CLI that cannot answer has Fast + // refused on every model. A catalog that did list the model and stayed silent + // about Fast is still not positive evidence, so that case keeps refusing. + if (fastMode && listed.length > 0 && support.supported !== true) { + throw new AgentSessionOptionRejectedError( + `claude model ${support.modelId ?? 'current'} does not support Fast mode` + ) + } + if ( + fastMode && + session.fastModeDisabledReason && + !['preference', 'sdk_opt_in_required'].includes(session.fastModeDisabledReason) + ) { + throw new AgentSessionOptionRejectedError( + `claude Fast mode is unavailable (${session.fastModeDisabledReason})` + ) + } + } // set_model resolves for a model the provider never lists and the session then // fails every turn with zero tokens, so the acceptance proves nothing and only // the catalog does. Restore replays a pick the provider may since have retired, // which reaches here with no user error at all. - if (input.key === 'model' && !(await claudeCatalogAdmitsModel(session, input.value, timeoutMs))) { + if (input.key === 'model' && !claudeCatalogAdmitsModel(listed, input.value)) { throw new AgentSessionOptionRejectedError(`claude does not list a model named ${input.value}`) } + const modelFastModeSupport = + input.key === 'model' && session.options.get('fastMode') === 'true' + ? claudeModelFastModeSupport(session, listed, input.value) + : null const modelWasConfirmed = readClaudeCurrentModel(session).confirmed const mutationSequence = ++session.optionMutationSequence // Only a model write can stale the model report — an effort or permission-mode @@ -85,6 +133,22 @@ export async function setClaudeStructuredOption( } try { await apply() + if ( + input.key === 'model' && + session.options.get('fastMode') === 'true' && + modelFastModeSupport?.supported === false + ) { + if (mutationSequence !== session.optionMutationSequence) { + return Object.fromEntries(session.options) + } + session.options.set('model', input.value) + session.options.set('fastMode', 'false') + session.confirmedOptions.delete('effort') + session.confirmedOptions.delete('fastMode') + // The requested model is already accepted; a cleanup failure cannot reject that write. + await session.connection.applyFlagSettings({ fastMode: false }, { timeoutMs }).catch(() => {}) + return Object.fromEntries(session.options) + } } catch (error) { if (error instanceof ClaudeControlRequestError) { throw new AgentSessionOptionRejectedError(error) @@ -94,26 +158,40 @@ export async function setClaudeStructuredOption( // apply_flag_settings answers `success` for an effort it then ignores, so the // absence of a throw proves nothing. Ask what the child actually holds. const adopted = - input.key === 'effort' && !UNREPORTED_EFFORTS.has(input.value) + (input.key === 'effort' && !UNREPORTED_EFFORTS.has(input.value)) || input.key === 'fastMode' ? await session.connection .getSettings({ timeoutMs }) - .then(readClaudeSettingsEffort) + .then((settings) => + input.key === 'fastMode' + ? readClaudeSettingsFastMode(settings) + : readClaudeSettingsEffort(settings) + ) .catch(() => null) : null if (mutationSequence !== session.optionMutationSequence) { return Object.fromEntries(session.options) } - // A disagreement stops main vouching for the value, it does not veto the write: - // the pre-flight guard already refuses levels the model advertises no control - // for, and no other client refuses on a readback. Keep the child's own answer so - // the disagreement survives as the level a later read falls back to. - if (adopted !== null && adopted !== input.value) { - session.reportedOptions.effort = adopted + if (input.key === 'fastMode' && typeof adopted === 'boolean') { + session.reportedOptions.fastMode = adopted } - session.options.set(input.key, input.value) + // A disagreement stops main vouching for the value, it does not veto the write: + // the pre-flight guard already refused levels the model advertises no control for, + // so what is left is the child reporting a value it chose for itself. Keep the + // child's own answer so the disagreement survives as the level a later read falls + // back to. + const decodedInput = input.key === 'fastMode' ? fastMode : input.value + if (adopted !== null && adopted !== decodedInput) { + if (typeof adopted === 'string') { + session.reportedOptions.effort = adopted + } + } + session.options.set( + input.key, + input.key === 'fastMode' && typeof adopted === 'boolean' ? String(adopted) : input.value + ) // Only a readback that agreed is adoption evidence; one that disagreed or could // not be taken records the value but must not also claim the provider vouched for it. - if (adopted !== null && adopted === input.value) { + if (adopted !== null && adopted === decodedInput) { session.confirmedOptions.add(input.key) } else { session.confirmedOptions.delete(input.key) @@ -123,6 +201,7 @@ export async function setClaudeStructuredOption( // it, and vouching for it would show a confirmed effort no readback covers. if (input.key === 'model') { session.confirmedOptions.delete('effort') + session.confirmedOptions.delete('fastMode') } return Object.fromEntries(session.options) } diff --git a/src/main/claude/claude-structured-provider-fallback.ts b/src/main/claude/claude-structured-provider-fallback.ts index 68aec07976b..167ab37ce98 100644 --- a/src/main/claude/claude-structured-provider-fallback.ts +++ b/src/main/claude/claude-structured-provider-fallback.ts @@ -106,16 +106,22 @@ export function createClaudeProviderFrameFallback( acquisitionId: string ): { /** `displayText` leads the row when Claude knows the sentence the frame itself does not name. */ - append: (kind: string, payload: unknown, displayText?: string | null) => void + append: ( + kind: string, + payload: unknown, + displayText?: string | null, + beforeAppend?: () => void + ) => boolean } { let sequence = 0 return { - append: (kind, payload, displayText) => { + append: (kind, payload, displayText, beforeAppend) => { sequence += 1 const translated = unhandledProviderFrameJournalItem('claude', kind, payload) if (!translated) { - return + return false } + beforeAppend?.() const bounded = displayText ? boundInlineText(displayText, DEFAULT_JOURNAL_PAYLOAD_LIMITS).text : null @@ -127,6 +133,7 @@ export function createClaudeProviderFrameFallback( bounded ? { ...translated.body, text: bounded } : translated.body ) sink.publish() + return true } } } @@ -136,24 +143,27 @@ export type ClaudeProviderFrameFallback = ReturnType + message: Record, + beforeAppend: () => void ): boolean { let changed = false for (const part of envelope.content.filter((part) => !isModeledClaudeContent(part))) { const partType = claudeText(claudeRecord(part)?.type) ?? 'unknown' - fallback.append( - `message:${envelope.role}:content:${partType}`, - part, - readableProviderFrameText(part) ?? CLAUDE_UNRENDERABLE_CONTENT_TEXT - ) - changed = true + changed = + fallback.append( + `message:${envelope.role}:content:${partType}`, + part, + readableProviderFrameText(part) ?? CLAUDE_UNRENDERABLE_CONTENT_TEXT, + beforeAppend + ) || changed } if (envelope.content.length === 0 && envelope.role === 'assistant') { - fallback.append(`message:${envelope.role}:empty`, message) - changed = true + // Empty provider placeholders do not prove work began, and may have no + // later result capable of closing a turn. + changed = fallback.append(`message:${envelope.role}:empty`, message) || changed } return changed } diff --git a/src/main/claude/claude-structured-session-acquisition-options.ts b/src/main/claude/claude-structured-session-acquisition-options.ts new file mode 100644 index 00000000000..be50d04b2e2 --- /dev/null +++ b/src/main/claude/claude-structured-session-acquisition-options.ts @@ -0,0 +1,45 @@ +import { + readClaudeFastModeFacts, + readClaudeSettingsFastMode, + readClaudeSettingsFastModePerSessionOptIn +} from './claude-structured-session-options' +import { restoredClaudeStructuredSessionOptions } from './claude-structured-options' +import type { ClaudeStreamJsonConnection } from './claude-stream-json-connection' + +export async function readClaudeStructuredSessionSettings( + connection: Pick, + timeoutMs: number | undefined +): Promise { + return connection.getSettings({ timeoutMs }).catch(() => null) +} + +export function prepareClaudeStructuredSessionAcquisitionOptions(args: { + settings: unknown + initialization: unknown + inputOptions: Readonly> | undefined + resumed: boolean +}) { + const fastMode = readClaudeSettingsFastMode(args.settings) + const fastModePerSessionOptIn = readClaudeSettingsFastModePerSessionOptIn(args.settings) + const fastModeFacts = readClaudeFastModeFacts(args.initialization) + const options = restoredClaudeStructuredSessionOptions(args.inputOptions) + if (!args.resumed && fastModePerSessionOptIn === true && options.get('fastMode') === 'true') { + options.delete('fastMode') + } + return { fastMode, fastModePerSessionOptIn, fastModeFacts, options } +} + +export function claudeStructuredSessionPublicationOptions(input: { + fastMode: boolean | null + fastModePerSessionOptIn: boolean | null + fastModeFacts: ReturnType +}) { + return { + fastMode: input.fastMode, + fastModePerSessionOptIn: input.fastModePerSessionOptIn, + ...(input.fastModeFacts.state ? { fastModeState: input.fastModeFacts.state } : {}), + ...(input.fastModeFacts.disabledReason + ? { fastModeDisabledReason: input.fastModeFacts.disabledReason } + : {}) + } +} diff --git a/src/main/claude/claude-structured-session-acquisition.ts b/src/main/claude/claude-structured-session-acquisition.ts index 2e8e19da75b..b1b1370398a 100644 --- a/src/main/claude/claude-structured-session-acquisition.ts +++ b/src/main/claude/claude-structured-session-acquisition.ts @@ -1,8 +1,8 @@ import { ClaudeRewindAttempt, proveClaudeRewindRecovery } from './claude-structured-rewind' -import { AgentSessionPreSpawnError } from '../native-chat/agent-session-wire/structured-agent-session-adapter' -import type { - AgentSessionAcquisition, - StructuredAgentSessionAcquireInput +import { + AgentSessionPreSpawnError, + type AgentSessionAcquisition, + type StructuredAgentSessionAcquireInput } from '../native-chat/agent-session-wire/structured-agent-session-adapter' import { CLAUDE_AUTH_SWITCH_IN_PROGRESS_MESSAGE } from '../claude-accounts/environment' import { isClaudeAuthSwitchInProgress } from '../claude-accounts/live-pty-gate' @@ -22,13 +22,18 @@ import { } from './claude-structured-init-deadline' import { claudeConfigDirEnvPatch } from './claude-config-dir-pin' import { CLAUDE_SPAWN_TOKEN_ENV, claudeProcessIdentity } from './claude-structured-owner-identity' -import { - restoreClaudeStructuredSessionOptions, - restoredClaudeStructuredSessionOptions -} from './claude-structured-options' +import { restoreClaudeStructuredSessionOptions } from './claude-structured-options' import { ClaudePromptRegistry } from './claude-structured-prompt-replies' import { createClaudeSessionJournalTranslator } from './claude-structured-journal-translation' -import { readClaudeSettingsEffort } from './claude-structured-session-options' +import { + observeClaudeFastModeFacts, + readClaudeSettingsEffort +} from './claude-structured-session-options' +import { + claudeStructuredSessionPublicationOptions, + prepareClaudeStructuredSessionAcquisitionOptions, + readClaudeStructuredSessionSettings +} from './claude-structured-session-acquisition-options' import { createClaudeSessionPublication } from './claude-structured-session-publication' import { mintClaudeAcquisitionGeneration, @@ -38,7 +43,7 @@ import { type ClaudeStructuredSessionAdapterDeps, type ClaudeAcquireCallbacks } from './claude-structured-session-state' -import { claudeAcquisitionCleanupError } from './claude-structured-session-close' +import { resolveClaudeAcquisitionError } from './claude-structured-session-close' import { readClaudeTranscriptEntryUuid } from './claude-tui-exit' import { withAgentSessionCreatePhase } from '../observability/agent-session-instrumentation' import { resolveClaudeAcquisitionLaunch } from './claude-structured-acquisition-launch' @@ -110,6 +115,7 @@ export async function acquireClaudeSession({ observedLeafUuid = readClaudeTranscriptEntryUuid(message) ?? observedLeafUuid if (liveSession) { liveSession.leafUuid = observedLeafUuid + observeClaudeFastModeFacts(liveSession, message) } const startsTurn = liveSession ? resolveClaudeReplayWaiter(liveSession, message, (settlement) => @@ -210,9 +216,13 @@ export async function acquireClaudeSession({ `claude proved session ${init.providerSessionId}, expected ${launch.providerSessionId}` ) } - const settings = await connection - .getSettings({ timeoutMs: deps.requestTimeoutMs }) - .catch(() => null) + const settings = await readClaudeStructuredSessionSettings(connection, deps.requestTimeoutMs) + const acquisitionOptions = prepareClaudeStructuredSessionAcquisitionOptions({ + settings, + initialization, + inputOptions: input.options, + resumed: launch.resumed + }) callbacks.deliver(attempt, sessionId, () => callbacks.emit(liveSession, input.events, { type: 'auth-diagnostic', @@ -240,13 +250,14 @@ export async function acquireClaudeSession({ leafUuid: observedLeafUuid, fence: input.fence, effort: readClaudeSettingsEffort(settings), + ...claudeStructuredSessionPublicationOptions(acquisitionOptions), resumed: launch.resumed, prompts, translator, events: input.events, process, acquisitionGeneration: mintClaudeAcquisitionGeneration(deps), - options: restoredClaudeStructuredSessionOptions(input.options), + options: acquisitionOptions.options, capabilities: readClaudeCapabilities(init, initialization), ...(deps.mintLinkId ? { linkId: deps.mintLinkId() } : {}), observedAt: deps.now?.() ?? Date.now() @@ -269,20 +280,14 @@ export async function acquireClaudeSession({ return acquired } catch (error) { initDeadline.clear() - let acquisitionError = error - if (sessions.get(sessionId)?.connection !== attempt.connection) { - translator?.dispose() - // Settle any callback that fired before the failure so no SDK promise dangles. - for (const prompt of prompts.clear()) { - prompt.settle(null) - } - const closed = (await attempt.connection?.close()) ?? true - if (attempt.connection?.exitVerdict.root === 'processless') { - acquisitionError = new AgentSessionPreSpawnError(error) - } else if (!closed) { - acquisitionError = claudeAcquisitionCleanupError(attempt.connection, error) - } - } + const acquisitionError = await resolveClaudeAcquisitionError({ + error, + sessionId, + sessions, + attempt, + translator, + prompts + }) acquisitions.deleteIfCurrent(sessionId, attempt) throw acquisitionError } finally { diff --git a/src/main/claude/claude-structured-session-adapter.test.ts b/src/main/claude/claude-structured-session-adapter.test.ts index 44a76f8402a..20be62f7997 100644 --- a/src/main/claude/claude-structured-session-adapter.test.ts +++ b/src/main/claude/claude-structured-session-adapter.test.ts @@ -96,6 +96,95 @@ describe('ClaudeStructuredSessionAdapter.acquire', () => { }) }) + it('restores an encoded Fast preference through the absolute flag setting', async () => { + const claude = fakeClaude({ + settings: { effective: { fastMode: false, fastModePerSessionOptIn: false } }, + routes: { + list_models: () => [{ value: 'opus', displayName: 'Opus', supportsFastMode: true }] + } + }) + const adapter = adapterFor(claude) + + await adapter.acquire({ + identity: identityFor(), + fence: 7, + spawnToken: 'spawn-9', + options: { model: 'opus', fastMode: 'true' } + }) + + expect(claude.connections[0].calls).toContainEqual({ + subtype: 'apply_flag_settings', + params: { settings: { fastMode: true } } + }) + }) + + it('does not carry a saved opt-in into a new per-session-opt-in child', async () => { + const claude = fakeClaude({ + settings: { effective: { fastMode: false, fastModePerSessionOptIn: true } }, + routes: { + list_models: () => [{ value: 'opus', displayName: 'Opus', supportsFastMode: true }] + } + }) + const adapter = adapterFor(claude) + + await adapter.acquire({ + identity: identityFor(), + fence: 7, + spawnToken: 'spawn-9', + options: { model: 'opus', fastMode: 'true' } + }) + + expect( + claude.connections[0].calls.filter((call) => call.subtype === 'apply_flag_settings') + ).toEqual([]) + }) + + it('restores Fast when reacquiring the same per-session-opt-in conversation', async () => { + const claude = fakeClaude({ + settings: { effective: { fastMode: false, fastModePerSessionOptIn: true } }, + routes: { + list_models: () => [{ value: 'opus', displayName: 'Opus', supportsFastMode: true }] + } + }) + const adapter = adapterFor(claude, { resumed: true }) + + await adapter.acquire({ + identity: identityFor(), + fence: 7, + spawnToken: 'spawn-9', + options: { model: 'opus', fastMode: 'true' } + }) + + expect(claude.connections[0].calls).toContainEqual({ + subtype: 'apply_flag_settings', + params: { settings: { fastMode: true } } + }) + }) + + it('self-heals a Fast preference the running model no longer supports', async () => { + const claude = fakeClaude({ + settings: { effective: { fastMode: false } }, + routes: { + list_models: () => [{ value: 'opus', displayName: 'Opus', supportsFastMode: false }] + } + }) + const adapter = adapterFor(claude) + + await expect( + adapter.acquire({ + identity: identityFor(), + fence: 7, + spawnToken: 'spawn-9', + options: { model: 'opus', fastMode: 'true' } + }) + ).resolves.toBeDefined() + + expect(adapter.readOptionRestoreFailures('session-1')).toContain('fastMode') + expect( + claude.connections[0].calls.filter((call) => call.subtype === 'apply_flag_settings') + ).toEqual([]) + }) + it.each([ ['model', 'set_model', { model: 'retired-model' }], ['effort', 'apply_flag_settings', { effort: 'retired-effort' }], diff --git a/src/main/claude/claude-structured-session-close.ts b/src/main/claude/claude-structured-session-close.ts index a78ac1b7eab..431d6e38ab8 100644 --- a/src/main/claude/claude-structured-session-close.ts +++ b/src/main/claude/claude-structured-session-close.ts @@ -1,4 +1,5 @@ import type { + ClaudeAcquisitionAttempt, ClaudeAcquisitionRegistry, ClaudeSession, ClaudeSessionExit, @@ -11,6 +12,8 @@ import { AgentSessionPreSpawnError } from '../native-chat/agent-session-wire/structured-agent-session-adapter' import type { ClaudeStreamJsonConnection } from './claude-stream-json-connection' +import type { ClaudeJournalTranslator } from './claude-structured-journal-translation' +import type { ClaudePromptRegistry } from './claude-structured-prompt-replies' import type { AgentSessionBackgroundTaskState } from '../../shared/agent-session-wire' import { closeProcessRegistry } from '../../shared/child-process/close-process-registry' import { retireClaudeDispatchWaiters } from './claude-structured-dispatch' @@ -29,6 +32,30 @@ export function claudeAcquisitionCleanupError( : new AgentSessionAcquisitionExitUnprovenError(cause) } +export async function resolveClaudeAcquisitionError(input: { + error: unknown + sessionId: string + sessions: Map + attempt: ClaudeAcquisitionAttempt + translator: ClaudeJournalTranslator | null + prompts: ClaudePromptRegistry +}): Promise { + let acquisitionError = input.error + if (input.sessions.get(input.sessionId)?.connection !== input.attempt.connection) { + input.translator?.dispose() + for (const prompt of input.prompts.clear()) { + prompt.settle(null) + } + const closed = (await input.attempt.connection?.close()) ?? true + if (input.attempt.connection?.exitVerdict.root === 'processless') { + acquisitionError = new AgentSessionPreSpawnError(input.error) + } else if (!closed) { + acquisitionError = claudeAcquisitionCleanupError(input.attempt.connection, input.error) + } + } + return acquisitionError +} + export function settleClaudeExitedSession(session: ClaudeSession): void { // The child is gone, so no replay can start these turns. Nothing else ends a // waiter's life now that no deadline does. diff --git a/src/main/claude/claude-structured-session-options.ts b/src/main/claude/claude-structured-session-options.ts index 2385f362c2a..4ad95223dec 100644 --- a/src/main/claude/claude-structured-session-options.ts +++ b/src/main/claude/claude-structured-session-options.ts @@ -1,23 +1,19 @@ import type { - AgentSessionModelOption, - AgentSessionOptionChoice, + AgentSessionFastModeState, + AgentSessionFastModeSupport, AgentSessionOptionsResult } from '../../shared/agent-session-wire' -import { CLAUDE_SESSION_OPTION_CATALOG } from '../../shared/agent-session-option-catalog-claude-codex' -import type { CatalogModel } from '../../shared/agent-session-option-catalog-types' +import { + currentModelId, + listedModels, + matchListedModel, + record, + seedModels, + text, + type ListedModel +} from './claude-structured-model-catalog' import type { ClaudeSession } from './claude-structured-session-state' - -type ListedModel = AgentSessionModelOption & { resolvedModel: string | null } - -function record(value: unknown): Record | null { - return typeof value === 'object' && value !== null && !Array.isArray(value) - ? (value as Record) - : null -} - -function text(value: unknown): string | null { - return typeof value === 'string' && value.trim() ? value : null -} +import { decodeStructuredAgentSessionOptionValue } from '../../shared/structured-agent-session-option-codec' /** * The session's current effort, which only `get_settings` reports: the @@ -29,71 +25,49 @@ export function readClaudeSettingsEffort(settings: unknown): string | null { return text(record(record(settings)?.effective)?.effortLevel) } -function effortLabel(value: string): string { - return value === 'xhigh' ? 'Extra high' : `${value.charAt(0).toUpperCase()}${value.slice(1)}` +export function readClaudeSettingsFastMode(settings: unknown): boolean | null { + const value = record(record(settings)?.effective)?.fastMode + return typeof value === 'boolean' ? value : null } -function listedEfforts(row: Record): AgentSessionOptionChoice[] { - return row.supportsEffort === true && Array.isArray(row.supportedEffortLevels) - ? row.supportedEffortLevels.flatMap((value) => { - const effort = text(value) - return effort ? [{ value: effort, label: effortLabel(effort) }] : [] - }) - : [] +export function readClaudeSettingsFastModePerSessionOptIn(settings: unknown): boolean | null { + const value = record(record(settings)?.effective)?.fastModePerSessionOptIn + return typeof value === 'boolean' ? value : null } -function listedModels(value: unknown): ListedModel[] { - const response = record(value) - const rows = Array.isArray(response?.models) - ? response.models.map(record).filter((row): row is Record => row !== null) - : [] - const defaultRow = rows.find((row) => text(row.value) === 'default') - const defaultResolvedModel = text(defaultRow?.resolvedModel) - const seen = new Set() - return rows.flatMap((row) => { - const id = text(row.value) - if (!id || id === 'default' || seen.has(id)) { - return [] - } - seen.add(id) - const resolvedModel = text(row.resolvedModel) - const description = text(row.description) - return [ - { - id, - label: text(row.displayName) ?? id, - ...(description ? { description } : {}), - isDefault: resolvedModel !== null && resolvedModel === defaultResolvedModel, - efforts: listedEfforts(row), - resolvedModel - } - ] - }) +const FAST_MODE_STATES: readonly AgentSessionFastModeState[] = ['off', 'cooldown', 'on'] + +export function readClaudeFastModeFacts(value: unknown): { + state?: AgentSessionFastModeState + disabledReason?: string + disabledReasonReported: boolean +} { + const row = record(value) + const state = text(row?.fast_mode_state) + // Narrowed by lookup, so the wire string reaches the session only as a known state. + const matched = FAST_MODE_STATES.find((entry) => entry === state) + const reportedDisabledReason = text(row?.fast_mode_disabled_reason) + return { + ...(matched ? { state: matched } : {}), + ...(reportedDisabledReason ? { disabledReason: reportedDisabledReason } : {}), + disabledReasonReported: Object.hasOwn(row ?? {}, 'fast_mode_disabled_reason') + } } -function seedEfforts(model: CatalogModel): AgentSessionOptionChoice[] { - const effort = model.options.find((option) => option.id === 'effort') - return effort?.kind.type === 'select' ? effort.kind.choices : [] -} - -function seedModels(): ListedModel[] { - return CLAUDE_SESSION_OPTION_CATALOG.models.map((model) => ({ - id: model.id, - label: model.label, - ...(model.description ? { description: model.description } : {}), - isDefault: model.isDefault === true, - efforts: seedEfforts(model), - resolvedModel: null - })) -} - -function currentModelId(models: ListedModel[], reportedModel: string | undefined): string { - const matched = reportedModel - ? models.find((model) => model.id === reportedModel || model.resolvedModel === reportedModel) - : undefined - return ( - matched?.id ?? reportedModel ?? models.find((model) => model.isDefault)?.id ?? models[0]!.id - ) +export function observeClaudeFastModeFacts(session: ClaudeSession, value: unknown): void { + const facts = readClaudeFastModeFacts(value) + if (facts.state) { + session.fastModeState = facts.state + } + if (facts.disabledReason) { + session.fastModeDisabledReason = facts.disabledReason + } else if (facts.state || facts.disabledReasonReported) { + // The child omits the reason entirely when nothing blocks Fast — it never sends a + // null — so a frame that reports state without one is the only all-clear there is. + // Requiring the key back would latch the first reason for the session's life and + // retire the control for good: a model switch away and back never restores it. + delete session.fastModeDisabledReason + } } /** @@ -129,19 +103,26 @@ export function readClaudeCurrentModel(session: ClaudeSession): { * of a refusal — and an absent or unlisted one is not evidence, or a live CLI * that predates `list_models` would have every effort refused under it. */ -export async function readClaudeModelEffortLevels( +/** One catalog read serves a whole option write. The admit check, the effort guard + * and the Fast guard all ask about the same list; each taking its own read made a + * single model write pay for two `list_models` round trips and let two guards answer + * from two different catalogs. An unreadable catalog is an empty list, which + * identifies no model and so refuses nothing. */ +export async function readClaudeListedModels( session: ClaudeSession, timeoutMs: number | undefined -): Promise<{ modelId: string | undefined; levels: ReadonlySet | null }> { - const modelId = readClaudeCurrentModel(session).id - if (!modelId) { - return { modelId, levels: null } - } +): Promise { const catalog = await session.connection.supportedModels({ timeoutMs }).catch(() => null) - const matched = catalog - ? listedModels({ models: catalog }).find( - (model) => model.id === modelId || model.resolvedModel === modelId - ) + return catalog ? listedModels({ models: catalog }) : [] +} + +export function claudeModelEffortLevels( + session: ClaudeSession, + models: readonly ListedModel[] +): { modelId: string | undefined; levels: ReadonlySet | null } { + const modelId = readClaudeCurrentModel(session).id + const matched = modelId + ? models.find((model) => model.id === modelId || model.resolvedModel === modelId) : undefined return { modelId: matched?.id ?? modelId, @@ -149,19 +130,64 @@ export async function readClaudeModelEffortLevels( } } +export function claudeModelFastModeSupport( + session: ClaudeSession, + models: readonly ListedModel[], + requestedModel?: string +): { modelId: string | undefined; supported: boolean | null } { + const reportedModelId = requestedModel ?? readClaudeCurrentModel(session).id + const modelId = reportedModelId ?? models.find((model) => model.isDefault)?.id + const matched = modelId ? matchListedModel(models, modelId) : undefined + return { + modelId: matched?.id ?? modelId, + supported: matched?.supportsFastMode ?? null + } +} + +const TRANSIENT_FAST_MODE_REASONS = new Set(['network_error', 'unknown', 'pending']) +const NON_BLOCKING_FAST_MODE_REASONS = new Set(['preference', 'sdk_opt_in_required']) + +function claudeFastModeSupport( + models: readonly ListedModel[], + disabledReason: string | undefined +): AgentSessionFastModeSupport | undefined { + if (disabledReason && TRANSIENT_FAST_MODE_REASONS.has(disabledReason)) { + return undefined + } + if (disabledReason && !NON_BLOCKING_FAST_MODE_REASONS.has(disabledReason)) { + return { supported: false, reason: disabledReason } + } + if (!models.some((model) => model.supportsFastMode === true)) { + return models.length > 0 && models.every((model) => model.supportsFastMode === false) + ? { supported: false, reason: 'model-not-supported' } + : undefined + } + return { supported: true } +} + +function listedModelFastModeSupport( + models: readonly ListedModel[], + modelId: string +): boolean | undefined { + return matchListedModel(models, modelId)?.supportsFastMode +} + +function decodedFastMode(session: ClaudeSession): boolean | undefined { + const encoded = session.options.get('fastMode') + if (encoded === undefined) { + return undefined + } + const decoded = decodeStructuredAgentSessionOptionValue('fastMode', encoded) + return typeof decoded === 'boolean' ? decoded : undefined +} + /** * Whether the catalog admits the model, matched by alias or resolved id so a pick * stored as either one is found. The permissive case lives here rather than at the * call site: every caller must treat an unidentified catalog the same way, and one * that forgot would refuse every model on a CLI that cannot answer. */ -export async function claudeCatalogAdmitsModel( - session: ClaudeSession, - modelId: string, - timeoutMs: number | undefined -): Promise { - const catalog = await session.connection.supportedModels({ timeoutMs }).catch(() => null) - const models = listedModels(catalog ? { models: catalog } : null) +export function claudeCatalogAdmitsModel(models: readonly ListedModel[], modelId: string): boolean { // An empty list identifies no model, so it is not evidence against one — a live // CLI predating `list_models` would otherwise have every model refused under it. // Do not turn this into a refusal. @@ -175,7 +201,29 @@ export async function readClaudeStructuredSessionOptions( session: ClaudeSession, timeoutMs: number | undefined ): Promise { - const catalog = await session.connection.supportedModels({ timeoutMs }).catch(() => null) + const readMutationSequence = session.optionMutationSequence + const [catalog, settings] = await Promise.all([ + session.connection.supportedModels({ timeoutMs }).catch(() => null), + session.connection.getSettings({ timeoutMs }).catch(() => null) + ]) + if (settings !== null && readMutationSequence === session.optionMutationSequence) { + const effort = readClaudeSettingsEffort(settings) + const fastMode = readClaudeSettingsFastMode(settings) + const perSessionOptIn = readClaudeSettingsFastModePerSessionOptIn(settings) + if (effort) { + session.reportedOptions.effort = effort + } + if (fastMode !== null) { + session.reportedOptions.fastMode = fastMode + if (decodedFastMode(session) !== undefined) { + session.options.set('fastMode', String(fastMode)) + } + session.confirmedOptions.add('fastMode') + } + if (perSessionOptIn !== null) { + session.fastModePerSessionOptIn = perSessionOptIn + } + } const discovered = listedModels(catalog ? { models: catalog } : null) const models = discovered.length > 0 ? discovered : seedModels() const current = readClaudeCurrentModel(session) @@ -184,9 +232,34 @@ export async function readClaudeStructuredSessionOptions( models.push({ id: model, label: model, isDefault: false, efforts: [], resolvedModel: null }) } const effort = session.options.get('effort') ?? session.reportedOptions.effort + let desiredFastMode = decodedFastMode(session) + if ( + desiredFastMode === true && + listedModelFastModeSupport(discovered, model) === false && + readMutationSequence === session.optionMutationSequence + ) { + session.options.set('fastMode', 'false') + session.confirmedOptions.delete('fastMode') + desiredFastMode = false + } + // The child answers Fast two ways and need not answer both: the settings readback + // carries the boolean, and the session frames carry a routing state. A fresh + // session reports the state while the boolean is still absent, so without this + // fallback the picker asks the user to re-answer what the provider just reported. + // `cooldown` throttles routing, it does not clear the pick, so it reads as on — + // reading it as off would flip a control nobody touched. + const fastMode = + desiredFastMode ?? + session.reportedOptions.fastMode ?? + (session.fastModeState === undefined ? undefined : session.fastModeState !== 'off') + const support = claudeFastModeSupport(discovered, session.fastModeDisabledReason) const confirmed = [ ...(current.confirmed ? ['model'] : []), - ...(effort && session.confirmedOptions.has('effort') ? ['effort'] : []) + ...(effort && session.confirmedOptions.has('effort') ? ['effort'] : []), + ...(fastMode !== undefined && + (session.confirmedOptions.has('fastMode') || !session.options.has('fastMode')) + ? ['fastMode'] + : []) ] return { models: models.map((entry) => ({ @@ -194,11 +267,15 @@ export async function readClaudeStructuredSessionOptions( label: entry.label, ...(entry.description ? { description: entry.description } : {}), isDefault: entry.isDefault, - efforts: entry.efforts + efforts: entry.efforts, + ...(entry.supportsFastMode !== undefined ? { supportsFastMode: entry.supportsFastMode } : {}) })), + ...(support ? { fastModeSupport: support } : {}), current: { model, ...(effort ? { effort } : {}), + ...(fastMode !== undefined ? { fastMode } : {}), + ...(session.fastModeState ? { fastModeState: session.fastModeState } : {}), ...(confirmed.length > 0 ? { confirmed } : {}) } } diff --git a/src/main/claude/claude-structured-session-publication.ts b/src/main/claude/claude-structured-session-publication.ts index e55608ae679..395335332e7 100644 --- a/src/main/claude/claude-structured-session-publication.ts +++ b/src/main/claude/claude-structured-session-publication.ts @@ -26,9 +26,14 @@ export function createClaudeSessionPublication(input: { capabilities: readonly string[] /** Read from `get_settings`; `system/init` never reports an effort. */ effort: string | null + fastMode: boolean | null + fastModePerSessionOptIn: boolean | null + fastModeState?: ClaudeSession['fastModeState'] + fastModeDisabledReason?: string }): { acquisition: AgentSessionAcquisition; session: ClaudeSession } { const model = input.init.model const effort = input.effort + const fastMode = input.fastMode return { acquisition: { process: input.process, @@ -61,10 +66,21 @@ export function createClaudeSessionPublication(input: { capabilities: input.capabilities, reportedOptions: { ...(model ? { model } : {}), - ...(effort ? { effort } : {}) + ...(effort ? { effort } : {}), + ...(fastMode !== null ? { fastMode } : {}) }, + ...(input.fastModeState ? { fastModeState: input.fastModeState } : {}), + ...(input.fastModeDisabledReason + ? { fastModeDisabledReason: input.fastModeDisabledReason } + : {}), + ...(input.fastModePerSessionOptIn !== null + ? { fastModePerSessionOptIn: input.fastModePerSessionOptIn } + : {}), reportedModelMutation: 0, - confirmedOptions: new Set(effort ? ['effort'] : []), + confirmedOptions: new Set([ + ...(effort ? ['effort'] : []), + ...(fastMode !== null ? ['fastMode'] : []) + ]), restoreSkippedOptions: new Set(), translator: input.translator, events: input.events diff --git a/src/main/claude/claude-structured-session-state.ts b/src/main/claude/claude-structured-session-state.ts index 7c3dc5e050e..1fbdcca42c2 100644 --- a/src/main/claude/claude-structured-session-state.ts +++ b/src/main/claude/claude-structured-session-state.ts @@ -12,7 +12,10 @@ import type { ClaudeJournalTranslator } from './claude-structured-journal-transl import type { ClaudePendingPrompt, ClaudePromptRegistry } from './claude-structured-prompt-replies' import { cancelProcessAcquisition } from '../../shared/child-process/cancel-process-acquisition' import { randomUUID } from 'node:crypto' -import type { AgentSessionBackgroundTaskState } from '../../shared/agent-session-wire' +import type { + AgentSessionBackgroundTaskState, + AgentSessionFastModeState +} from '../../shared/agent-session-wire' import type { ClaudeBackgroundTaskTracker } from './claude-background-task-tracker' import type { ClaudeSlashCommandCatalog } from './claude-slash-command-catalog' @@ -129,7 +132,10 @@ export type ClaudeSession = { /** Once a retired waiter is evicted, legacy content-only replay matching is unsafe. */ replayContentFallbackBlocked: boolean options: Map - reportedOptions: { model?: string; effort?: string } + reportedOptions: { model?: string; effort?: string; fastMode?: boolean } + fastModeState?: AgentSessionFastModeState + fastModeDisabledReason?: string + fastModePerSessionOptIn?: boolean /** `optionMutationSequence` when `reportedOptions.model` was last observed, so a * write still awaiting its first turn outranks the report it will replace. */ reportedModelMutation: number diff --git a/src/main/claude/claude-turn-lifecycle-item.ts b/src/main/claude/claude-turn-lifecycle-item.ts index 00d7c4dd65e..664a06f0898 100644 --- a/src/main/claude/claude-turn-lifecycle-item.ts +++ b/src/main/claude/claude-turn-lifecycle-item.ts @@ -2,6 +2,7 @@ import type { AgentJournalItemIdentity, AgentJournalTurnItem } from '../../shared/agent-session-journal-types' +import { agentJournalItemKey } from '../../shared/agent-session-journal-item-key' import { agentJournalTurnBody } from '../../shared/agent-session-turn-record' import type { StructuredAgentSessionAppendOptions } from '../native-chat/agent-session-wire/structured-agent-session-event-sink' import { claudeText } from './claude-structured-item-translation' @@ -10,7 +11,8 @@ export type ClaudeCurrentTurn = { sessionId: string turnId: string startedAt: number - /** Provider key of the user echo that opened the turn. */ + /** Provider key of the user echo, or the lifecycle row itself when provider + * output opened a turn with no user row to receive its timing. */ userItemId: string } @@ -50,6 +52,12 @@ export function claudeTurnLifecycleIdentity( } } +/** Keep provider-resumed timing off the preceding prompt on clients that treat + * a missing user key as an older-host lifecycle row. */ +export function claudeProviderResumedTurnTimingAnchor(sessionId: string, turnId: string): string { + return agentJournalItemKey(claudeTurnLifecycleIdentity(sessionId, turnId)) +} + /** The lifecycle row is revised to its terminal state, never tombstoned, so the * turn's host-clock endpoints outlive the turn. */ export function claudeTurnLifecycleItem( diff --git a/src/main/claude/claude-turn-opening.ts b/src/main/claude/claude-turn-opening.ts new file mode 100644 index 00000000000..9b4be37eb8e --- /dev/null +++ b/src/main/claude/claude-turn-opening.ts @@ -0,0 +1,104 @@ +// Whether Orca's own send echo opens a turn. +// +// The provider's own output opens one too — see `ensureTurnOpen` in the +// translator, which the content sites call as they journal. Orca's turn used to +// open only here, while any `result` frame closed it, and that asymmetry is what +// leaves a working session reading idle: the provider resumes on its own when a +// background task reports in and wakes the agent, and nothing Orca sent ever +// arrives to reopen a turn. + +import { + claudeHasReplayContent, + claudeRecord, + claudeText, + type ClaudeMessageEnvelope +} from './claude-structured-item-translation' +import { + claudeProviderResumedTurnTimingAnchor, + type ClaudeCurrentTurn +} from './claude-turn-lifecycle-item' + +export type ClaudeSendEchoTurnInput = { + envelope: ClaudeMessageEnvelope + /** The raw frame: an absent `parent_tool_use_id` is not the same claim as an + * explicit `null`, and only a root frame carries a root turn. */ + frame: Record + /** Orca dispatched this send and the provider is replaying it back. */ + startsTurn: boolean + observedAt: number + /** Provider key of the user row this turn is anchored to. */ + userItemId: string +} + +/** The turn a replayed send echo opens, or null when this frame is not one. */ +export function claudeTurnOpenedBySendEcho( + input: ClaudeSendEchoTurnInput +): ClaudeCurrentTurn | null { + const { envelope } = input + return envelope.role === 'user' && + input.startsTurn && + claudeHasReplayContent(envelope) && + input.frame.parent_tool_use_id === null + ? { + sessionId: envelope.sessionId, + turnId: envelope.uuid, + startedAt: input.observedAt, + userItemId: input.userItemId + } + : null +} + +/** Whether a frame is the root turn's own, rather than a child's. An absent + * `parent_tool_use_id` is a root frame: only a string names a parent, and a + * build that omits the field on root frames must not silently stop opening + * turns. */ +export function isRootClaudeFrame(frame: Record): boolean { + return typeof frame.parent_tool_use_id !== 'string' +} + +export type ClaudeTurnSource = { sessionId: string; uuid: string; assistant: boolean } + +/** Reads a turn source off a raw frame, for the streamed path that has no envelope. */ +export function claudeStreamTurnSource(frame: Record): ClaudeTurnSource | null { + const sessionId = claudeText(frame.session_id) + const uuid = claudeText(frame.uuid) + // A streamed delta only ever carries model output. + return sessionId && uuid ? { sessionId, uuid, assistant: true } : null +} + +/** A streamed assistant message has begun, before its first content delta. */ +export function claudeStreamTurnStartSource( + frame: Record +): ClaudeTurnSource | null { + const event = claudeRecord(frame.event) + return frame.type === 'stream_event' && event?.type === 'message_start' + ? claudeStreamTurnSource(frame) + : null +} + +/** The provider produced, so a turn is running. Root-ness first, then the + * suppression latch, then idempotency — every frame of one reply stays inside + * the turn its first frame opened. */ +export function createClaudeTurnOpener(deps: { + isTurnOpen: () => boolean + isSuppressed: () => boolean + open: (turn: ClaudeCurrentTurn, observedAt: number) => void +}): (frame: Record, source: ClaudeTurnSource | null, observedAt: number) => void { + return (frame, source, observedAt) => { + if (!source?.assistant || !isRootClaudeFrame(frame)) { + return + } + if (deps.isSuppressed() || deps.isTurnOpen()) { + return + } + deps.open( + { + sessionId: source.sessionId, + turnId: source.uuid, + startedAt: observedAt, + userItemId: claudeProviderResumedTurnTimingAnchor(source.sessionId, source.uuid) + }, + observedAt + ) + } +} diff --git a/src/main/claude/claude-turn-resumption.test.ts b/src/main/claude/claude-turn-resumption.test.ts new file mode 100644 index 00000000000..96d364f91a5 --- /dev/null +++ b/src/main/claude/claude-turn-resumption.test.ts @@ -0,0 +1,428 @@ +// Regression for a structured Claude session that reported idle while it was +// working. Reproduced from the journal of the reported session +// (962e6f25…/epoch 3d214e6f…, 2026-09-13): a `result` settled the turn at +// 13:56:06, a background task reported in at 13:58:59, and the agent then ran +// tool calls until 14:05:18 — nine minutes in which the shared projector, and +// so the sidebar row and the chat indicator, read `idle`. + +import { describe, expect, it, vi } from 'vitest' +import type { + AgentJournalItemBody, + AgentJournalItemIdentity, + AgentJournalRenderItem +} from '../../shared/agent-session-journal-types' +import { agentJournalItemKey } from '../../shared/agent-session-journal-item-key' +import { + legacyAgentJournalTurnStatusBody, + readAgentJournalTurn +} from '../../shared/agent-session-turn-record' +import { selectStructuredAgentSettledTurns } from '../../shared/structured-agent-session-turn-timing' +import { + hasUnansweredStructuredAgentSessionDispatch, + projectStructuredAgentSessionStatus, + projectStructuredAgentSessionStatusSummary +} from '../../shared/structured-agent-session-projection' +import { activeStructuredAgentSessionToolCall } from '../../shared/structured-agent-session-live-turn' +import type { StructuredAgentSessionEventSink } from '../native-chat/agent-session-wire/structured-agent-session-event-sink' +import { createClaudeJournalTranslator } from './claude-structured-journal-translation' + +const SESSION = 'claude-session' + +function harness() { + const appended: { identity: AgentJournalItemIdentity; body: AgentJournalItemBody }[] = [] + const sink: StructuredAgentSessionEventSink = { + appendItem: (identity, body) => appended.push({ identity, body }), + appendTombstone: () => {}, + publish: vi.fn() + } + const translator = createClaudeJournalTranslator({ sink, fallbackIdPrefix: 'test' }) + // The reducer keys items by identity and orders them by first append, so the + // render list the projector reads is the deduplicated append order. + const items = (): AgentJournalRenderItem[] => { + const byKey = new Map() + appended.forEach(({ identity, body }, index) => { + const key = agentJournalItemKey(identity) + const existing = byKey.get(key) + byKey.set(key, { + itemId: key, + revision: (existing?.revision ?? 0) + 1, + body, + sequence: existing?.sequence ?? index, + observedAt: index + }) + }) + return [...byKey.values()].sort((a, b) => a.sequence - b.sequence) + } + return { translator, items, appended } +} + +function frame( + type: 'assistant' | 'user', + uuid: string, + content: unknown[], + parentToolUseId: string | null = null +) { + return { + type: 'message' as const, + sessionId: 'orca-session', + ...(type === 'user' && parentToolUseId === null ? { startsTurn: true as const } : {}), + message: { + type, + uuid, + session_id: SESSION, + parent_tool_use_id: parentToolUseId, + message: { role: type, content } + } + } +} + +/** The captured `task-notification` wake-up: a main-thread user frame Orca never + * dispatched, so it carries no replay waiter and cannot start a turn. */ +function taskNotification(uuid: string) { + return { + type: 'message' as const, + sessionId: 'orca-session', + message: { + type: 'user', + uuid, + session_id: SESSION, + parent_tool_use_id: null, + message: { + role: 'user', + content: [{ type: 'text', text: 'bfnmj08v6' }] + } + } + } +} + +/** A partial-message text delta. `--include-partial-messages` is a pinned launch + * contract, so this is the shape a resumed turn's first output usually takes. */ +function textDelta(uuid: string, messageId: string, text: string) { + return { + type: 'message' as const, + sessionId: 'orca-session', + message: { + type: 'stream_event', + uuid, + session_id: SESSION, + parent_tool_use_id: null, + event: { type: 'content_block_delta', index: 0, delta: { type: 'text_delta', text } }, + message: { id: messageId } + } + } +} + +function streamMessageStart(uuid: string, parentToolUseId: string | null = null) { + return { + type: 'message' as const, + sessionId: 'orca-session', + message: { + type: 'stream_event', + uuid, + session_id: SESSION, + parent_tool_use_id: parentToolUseId, + event: { type: 'message_start', message: { id: `msg-${uuid}`, role: 'assistant' } } + } + } +} + +function result(uuid: string, parentToolUseId: string | null = null, durationMs = 322_937) { + return { + type: 'message' as const, + sessionId: 'orca-session', + message: { + type: 'result', + subtype: 'success', + uuid, + session_id: SESSION, + parent_tool_use_id: parentToolUseId, + duration_ms: durationMs + } + } +} + +function projected(items: readonly AgentJournalRenderItem[]): string { + // No submission is outstanding: the send was acknowledged long ago, which is + // exactly the state in which the reported session fell back to idle. + expect(hasUnansweredStructuredAgentSessionDispatch([], null)).toBe(false) + return projectStructuredAgentSessionStatus(items, [], null) +} + +describe('a Claude turn the provider resumed on its own', () => { + it('reports working while the agent runs tool calls after a result settled the turn', () => { + const { translator, items } = harness() + + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + expect(projected(items())).toBe('working') + + translator.handle(result('r1')) + // The agent really did stop here, so idle is correct. + expect(projected(items())).toBe('idle') + + // A background task reports in and wakes the agent; it starts working again. + translator.handle(taskNotification('n1')) + translator.handle(frame('assistant', 'a1', [{ type: 'text', text: 'Back on it.' }])) + expect(projected(items())).toBe('working') + + translator.handle( + frame('assistant', 'a2', [ + { type: 'tool_use', id: 'toolu_1', name: 'Bash', input: { command: 'rg foo' } } + ]) + ) + expect(projected(items())).toBe('working') + + // The next result settles the turn the provider opened, so nothing over-claims. + translator.handle(result('r2')) + expect(projected(items())).toBe('idle') + }) + + it('gives the resumed turn its own record, anchored away from the preceding user row', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(result('r1')) + translator.handle(frame('assistant', 'a1', [{ type: 'text', text: 'Back on it.' }])) + + const turns = items().flatMap((item) => { + const turn = readAgentJournalTurn(item.body) + return turn ? [turn] : [] + }) + expect(turns.map((turn) => turn.state)).toEqual(['completed', 'running']) + expect(turns[1]?.turnId).toBe('a1') + expect(turns[1]?.userItemId).toBe('legacy:claude:claude-session:turn-lifecycle%3Aa1') + }) + + it('does not replace the preceding prompt timing with provider-resumed work', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(result('r1', null, 1_000)) + translator.handle(frame('assistant', 'a1', [{ type: 'text', text: 'Back on it.' }])) + translator.handle(result('r2', null, 9_000)) + + const translatedItems = items() + const originalTurn = translatedItems + .map((item) => readAgentJournalTurn(item.body)) + .find((turn) => turn?.turnId === 'u1') + expect(originalTurn?.userItemId).toBeDefined() + if (!originalTurn?.userItemId) { + throw new Error('expected the original turn to name its user row') + } + const userItem: AgentJournalRenderItem = { + itemId: originalTurn.userItemId, + revision: 1, + sequence: -1, + observedAt: 0, + body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'go' }] } + } + const currentItems = [userItem, ...translatedItems] + expect(selectStructuredAgentSettledTurns(currentItems).get(userItem.itemId)).toMatchObject({ + workedSeconds: 1 + }) + + const legacyItems = currentItems.map((item) => { + const turn = readAgentJournalTurn(item.body) + return item.body.kind === 'turn' && turn + ? { ...item, body: legacyAgentJournalTurnStatusBody(turn, item.itemId) } + : item + }) + expect(selectStructuredAgentSettledTurns(legacyItems).get(userItem.itemId)).toMatchObject({ + workedSeconds: 1 + }) + }) + + it('leaves a settled turn settled when only a subagent is still producing', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(result('r1')) + + // Children outlive the turn that spawned them; their streams are not a turn. + translator.handle(streamMessageStart('child-start', 'toolu_parent')) + expect(projected(items())).toBe('idle') + }) + + it('does not reopen a turn that is already running', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(frame('assistant', 'a1', [{ type: 'text', text: 'one' }])) + translator.handle(frame('assistant', 'a2', [{ type: 'text', text: 'two' }])) + + const running = items().filter((item) => readAgentJournalTurn(item.body)?.state === 'running') + expect(running).toHaveLength(1) + expect(readAgentJournalTurn(running[0]!.body)?.turnId).toBe('u1') + expect(projected(items())).toBe('working') + }) + + it('reports the first tool call of a resumed turn as the live tool', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + // A real first turn leaves prose behind, which is what makes the session listable. + translator.handle(frame('assistant', 'a0', [{ type: 'text', text: 'Launched it.' }])) + translator.handle(result('r1')) + + // The provider resumes straight into a tool call, with no prose first. The + // turn has to bracket its own first output or every reader that stops at the + // turn record looks straight past it. + translator.handle( + frame('assistant', 'a1', [ + { type: 'tool_use', id: 'toolu_1', name: 'Bash', input: { command: 'rg foo' } } + ]) + ) + + expect(projected(items())).toBe('working') + expect(activeStructuredAgentSessionToolCall(items())?.name).toBe('Bash') + expect(projectStructuredAgentSessionStatusSummary(items(), [], null).toolName).toBe('Bash') + }) + + it('leaves the turn running when a nested result settles a child', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(frame('assistant', 'a0', [{ type: 'text', text: 'working on it' }])) + + // A child's result ends the child, not the turn that spawned it. No real + // stream has been observed carrying one; this holds the symmetry with the + // open path, which already refuses to open a turn from nested output. + translator.handle(result('r-child', 'toolu_parent')) + expect(projected(items())).toBe('working') + + translator.handle(result('r-root')) + expect(projected(items())).toBe('idle') + }) + + it('never opens a turn from a frame that arrives after the session ended', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(frame('assistant', 'a0', [{ type: 'text', text: 'on it' }])) + translator.handle({ type: 'ended', sessionId: 'orca-session', reason: 'exit', observedAt: 1 }) + expect(projected(items())).toBe('idle') + + // Nothing can close a turn opened now, so nothing may open one. + translator.handle(streamMessageStart('late-start')) + expect(projected(items())).toBe('idle') + }) + + it('does not let provider chatter resume a turn the provider failed', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(frame('assistant', 'a0', [{ type: 'text', text: 'on it' }])) + translator.handle({ + type: 'message' as const, + sessionId: 'orca-session', + message: { + type: 'result', + subtype: 'error', + uuid: 'r-fail', + session_id: SESSION, + parent_tool_use_id: null, + is_error: true + } + }) + expect(projected(items())).toBe('idle') + + translator.handle(frame('assistant', 'a1', [{ type: 'text', text: 'still talking' }])) + expect(projected(items())).toBe('idle') + + // The next accepted send is what resumes it. + translator.handle(frame('user', 'u2', [{ type: 'text', text: 'again' }])) + expect(projected(items())).toBe('working') + }) + + it('reports working from the first streamed delta of a resumed turn', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(frame('assistant', 'a0', [{ type: 'text', text: 'on it' }])) + translator.handle(result('r1')) + expect(projected(items())).toBe('idle') + + // The resumed reply streams in before any whole assistant frame lands. + translator.handle(textDelta('d1', 'msg-1', 'Back ')) + translator.handle(textDelta('d2', 'msg-1', 'on it.')) + expect(projected(items())).toBe('working') + }) + + it('opens before a resumed stream produces its first content delta', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(result('r1')) + + translator.handle(streamMessageStart('message-start-1')) + + expect(projected(items())).toBe('working') + expect(readAgentJournalTurn(items().at(-1)?.body)?.turnId).toBe('message-start-1') + expect(items().some((item) => item.body.kind === 'status')).toBe(false) + }) + + it('opens before journaling substantive fallback output', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(result('r1')) + + translator.handle( + frame('assistant', 'a1', [{ type: 'future_content', message: 'new provider output' }]) + ) + + const resumed = items().slice(-2) + expect(readAgentJournalTurn(resumed[0]?.body)?.state).toBe('running') + expect(resumed[1]?.body).toMatchObject({ + kind: 'status', + providerFrame: { kind: 'message:assistant:content:future_content' } + }) + expect(projected(items())).toBe('working') + }) + + it('does not open a turn for an empty assistant placeholder', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(result('r1')) + + translator.handle(frame('assistant', 'empty-1', [])) + + expect(projected(items())).toBe('idle') + expect(items().at(-1)?.body).toMatchObject({ + kind: 'status', + providerFrame: { kind: 'message:assistant:empty' } + }) + }) + + it('still reports a nested result failure even though it settles no turn', () => { + const { translator, items, appended } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(frame('assistant', 'a0', [{ type: 'text', text: 'on it' }])) + const before = appended.length + translator.handle({ + type: 'message' as const, + sessionId: 'orca-session', + message: { + type: 'result', + subtype: 'error', + uuid: 'r-child-fail', + session_id: SESSION, + parent_tool_use_id: 'toolu_parent', + is_error: true, + result: 'child blew up' + } + }) + expect(projected(items())).toBe('working') + expect(appended.length).toBeGreaterThan(before) + }) + + it('keeps the failure latch set when a later root result succeeds', () => { + const { translator, items } = harness() + translator.handle(frame('user', 'u1', [{ type: 'text', text: 'go' }])) + translator.handle(frame('assistant', 'a0', [{ type: 'text', text: 'on it' }])) + translator.handle({ + type: 'message' as const, + sessionId: 'orca-session', + message: { + type: 'result', + subtype: 'error', + uuid: 'r-fail', + session_id: SESSION, + parent_tool_use_id: null, + is_error: true + } + }) + // A clean result arriving afterwards must not lift the latch. + translator.handle(result('r-late-ok')) + translator.handle(frame('assistant', 'a1', [{ type: 'text', text: 'still talking' }])) + expect(projected(items())).toBe('idle') + }) +}) diff --git a/src/main/claude/hook-script.ts b/src/main/claude/hook-script.ts new file mode 100644 index 00000000000..efbe71fc9e3 --- /dev/null +++ b/src/main/claude/hook-script.ts @@ -0,0 +1,93 @@ +/** The managed Claude-compatible hook script, built for local, POSIX-remote and Windows targets. + * Split from hook-service.ts so the service owns install/status and this owns script text, + * mirroring the same split under src/main/cursor/. */ +import { buildWindowsAgentHookCurlPostCommand } from '../agent-hooks/installer-utils' +import { buildPosixAgentHookPostCommand } from '../agent-hooks/hook-post-command' +import { + buildPosixGrokReplayGuardLines, + buildWindowsGrokReplayGuardLines +} from '../agent-hooks/grok-replay-guard' +import { + WINDOWS_HOOK_STDIN_DRAIN_LABEL, + buildPosixHookPayloadCapture, + buildPosixHookSpoolLines, + buildWindowsHookEnvironmentGuardLines, + buildWindowsHookStdinDrainEpilogue +} from '../agent-hooks/hook-stdin-contract' + +export function getManagedScript( + target: 'local' | 'posix' = 'local', + options: { + skipWhenDevinImportsClaude?: boolean + skipWhenGrokImportsClaude?: boolean + } = {} +): string { + if (target === 'local' && process.platform === 'win32') { + return [ + '@echo off', + 'setlocal', + // Why: Claude-compatible permission hooks fail closed on empty stdout (#14818). + 'echo {}', + // Why: refresh endpoint coordinates for PTYs surviving an Orca restart. + 'if defined ORCA_AGENT_HOOK_ENDPOINT if exist "%ORCA_AGENT_HOOK_ENDPOINT%" call "%ORCA_AGENT_HOOK_ENDPOINT%" 2>nul', + // Why (#11549): the env guards must outrank the Devin skip — the Devin skip parks in more.com, + // and outside an Orca pane the caller can abandon stdin, so more.com never returns. + ...buildWindowsHookEnvironmentGuardLines(), + // Why: a backgrounded session runs in a daemon worker that inherited the dispatching + // pane's env, so ORCA_PANE_KEY names a pane this session does not run in (#9236). + // Why exit, not the drain label: the drain parks in more.com and a worker is outside + // an Orca pane — the abandoned-stdin hang #11549 guards against. + 'if not "%CLAUDE_JOB_DIR%"=="" exit /b 0', + ...(options.skipWhenGrokImportsClaude ? buildWindowsGrokReplayGuardLines() : []), + ...(options.skipWhenDevinImportsClaude + ? [ + // Why: Devin imports .claude hooks by default; skip Orca's managed hook there so status posts stay attributed to Devin. + `if not "%DEVIN_PROJECT_DIR%"=="" goto :${WINDOWS_HOOK_STDIN_DRAIN_LABEL}` + ] + : []), + // Why: use curl.exe to avoid an extra PowerShell startup per hook. + buildWindowsAgentHookCurlPostCommand('claude'), + 'exit /b 0', + ...buildWindowsHookStdinDrainEpilogue(), + '' + ].join('\r\n') + } + + return [ + '#!/bin/sh', + // Why: Claude-compatible permission hooks fail closed on empty stdout (#14818). + 'printf "{}\\n"', + ...buildPosixHookPayloadCapture(), + ...(options.skipWhenGrokImportsClaude ? buildPosixGrokReplayGuardLines() : []), + ...buildPosixHookSpoolLines('claude'), + ...(options.skipWhenDevinImportsClaude + ? [ + // Why: Devin imports .claude hooks by default; skip Orca's managed hook there so status posts stay attributed to Devin. + 'if [ -n "$DEVIN_PROJECT_DIR" ]; then', + ' exit 0', + 'fi' + ] + : []), + // Why: a backgrounded session runs in a daemon worker that inherited the dispatching + // pane's env, so ORCA_PANE_KEY names a pane this session does not run in (#9236). + 'if [ -n "$CLAUDE_JOB_DIR" ]; then', + ' exit 0', + 'fi', + // Why: refresh endpoint coordinates for PTYs surviving an Orca restart. + // Why: suppress parse errors so they neither leak nor trip outer set -e. + 'if [ -n "$ORCA_AGENT_HOOK_ENDPOINT" ] && [ -r "$ORCA_AGENT_HOOK_ENDPOINT" ]; then', + ' unset ORCA_AGENT_HOOK_TRANSPORT', + ' . "$ORCA_AGENT_HOOK_ENDPOINT" 2>/dev/null || :', + 'fi', + 'if [ -z "$ORCA_AGENT_HOOK_PORT" ] || [ -z "$ORCA_AGENT_HOOK_TOKEN" ] || [ -z "$ORCA_PANE_KEY" ]; then', + ' spool_hook_event', + ' exit 0', + 'fi', + // Why: keep full hook JSON off the command line and avoid IDS-friendly URL-encoded paths. + ...buildPosixAgentHookPostCommand('claude').map((line, index, lines) => + index === lines.length - 1 ? `${line} >/dev/null 2>&1 || spool_hook_event` : line + ), + 'exit 0', + '' + ].join('\n') +} diff --git a/src/main/claude/hook-service.test.ts b/src/main/claude/hook-service.test.ts index a4e48c98120..2a07aff4c8a 100644 --- a/src/main/claude/hook-service.test.ts +++ b/src/main/claude/hook-service.test.ts @@ -262,6 +262,7 @@ describe('ClaudeHookService.install', () => { 'utf-8' ) expect(managedScript).toContain('DEVIN_PROJECT_DIR') + expect(managedScript).toContain('GROK_HOOK_EVENT') // Why: guard and Devin-skip paths must still return neutral JSON (#14818). expect(managedScript).toMatch( process.platform === 'win32' @@ -711,6 +712,7 @@ describe('ClaudeHookService.installRemote', () => { const script = fs.files.get('/home/dev/.orca/agent-hooks/claude-hook.sh') expect(script).toContain('#!/bin/sh') expect(script).toContain('DEVIN_PROJECT_DIR') + expect(script).toContain('GROK_HOOK_EVENT') // Why: remote guard paths must still return neutral JSON (#14818). expect(script!.indexOf('printf "{}\\n"')).toBe( script!.indexOf('#!/bin/sh') + '#!/bin/sh\n'.length @@ -813,6 +815,9 @@ describe('OpenClaudeHookService-compatible install', () => { expect( readFileSync(join(tmpHome, '.orca', 'agent-hooks', OPENCLAUDE_SCRIPT_FILE_NAME), 'utf-8') ).not.toContain('DEVIN_PROJECT_DIR') + expect( + readFileSync(join(tmpHome, '.orca', 'agent-hooks', OPENCLAUDE_SCRIPT_FILE_NAME), 'utf-8') + ).not.toContain('GROK_HOOK_EVENT') // Why: the statusline usage feed is Claude-only; OpenClaude installs must not set statusLine. expect(parsed.statusLine).toBeUndefined() expect(existsSync(join(tmpHome, '.claude', 'settings.json'))).toBe(false) diff --git a/src/main/claude/hook-service.ts b/src/main/claude/hook-service.ts index b3ae8d01136..73e7add40dc 100644 --- a/src/main/claude/hook-service.ts +++ b/src/main/claude/hook-service.ts @@ -3,26 +3,20 @@ import type { SFTPWrapper } from 'ssh2' import type { AgentHookInstallState, AgentHookInstallStatus } from '../../shared/agent-hook-types' import { buildManagedCommandHook, - buildWindowsAgentHookCurlPostCommand, readHooksJson, writeHooksJson, - writeManagedScript, - type HooksConfig + type HooksConfig, + writeManagedScript } from '../agent-hooks/installer-utils' -import { buildPosixAgentHookPostCommand } from '../agent-hooks/hook-post-command' import { readHooksJsonRemote, writeHooksJsonRemote, writeManagedScriptRemote } from '../agent-hooks/installer-utils-remote' import { refreshManagedScriptIfPresent } from '../agent-hooks/managed-hook-script-refresh' -import { - buildPosixHookPayloadCapture, - buildPosixHookSpoolLines, - buildWindowsHookEnvironmentGuardLines, - buildWindowsHookStdinDrainEpilogue, - WINDOWS_HOOK_STDIN_DRAIN_LABEL -} from '../agent-hooks/hook-stdin-contract' +import { getManagedScript } from './hook-script' + +export { getManagedScript } import { getManagedStatusLineScript } from './statusline-script' import { applyManagedHooks, @@ -53,84 +47,16 @@ type ClaudeHookServiceOptions = { settings: ClaudeCompatibleHookSettings } +type ClaudeHookInstallOptions = { + claudeVersion?: string +} + const DEFAULT_CLAUDE_HOOK_SERVICE_OPTIONS: ClaudeHookServiceOptions = { agent: 'claude', displayName: 'Claude', settings: CLAUDE_HOOK_SETTINGS } -function getManagedScript( - target: 'local' | 'posix' = 'local', - options: { skipWhenDevinImportsClaude?: boolean } = {} -): string { - if (target === 'local' && process.platform === 'win32') { - return [ - '@echo off', - 'setlocal', - // Why: Claude-compatible permission hooks fail closed on empty stdout (#14818). - 'echo {}', - // Why: refresh endpoint coordinates for PTYs surviving an Orca restart. - 'if defined ORCA_AGENT_HOOK_ENDPOINT if exist "%ORCA_AGENT_HOOK_ENDPOINT%" call "%ORCA_AGENT_HOOK_ENDPOINT%" 2>nul', - // Why (#11549): the env guards must outrank the Devin skip — the Devin skip parks in more.com, - // and outside an Orca pane the caller can abandon stdin, so more.com never returns. - ...buildWindowsHookEnvironmentGuardLines(), - // Why: a backgrounded session runs in a daemon worker that inherited the dispatching - // pane's env, so ORCA_PANE_KEY names a pane this session does not run in (#9236). - // Why exit, not the drain label: the drain parks in more.com and a worker is outside - // an Orca pane — the abandoned-stdin hang #11549 guards against. - 'if not "%CLAUDE_JOB_DIR%"=="" exit /b 0', - ...(options.skipWhenDevinImportsClaude - ? [ - // Why: Devin imports .claude hooks by default; skip Orca's managed hook there so status posts stay attributed to Devin. - `if not "%DEVIN_PROJECT_DIR%"=="" goto :${WINDOWS_HOOK_STDIN_DRAIN_LABEL}` - ] - : []), - // Why: use curl.exe to avoid an extra PowerShell startup per hook. - buildWindowsAgentHookCurlPostCommand('claude'), - 'exit /b 0', - ...buildWindowsHookStdinDrainEpilogue(), - '' - ].join('\r\n') - } - - return [ - '#!/bin/sh', - // Why: Claude-compatible permission hooks fail closed on empty stdout (#14818). - 'printf "{}\\n"', - ...buildPosixHookPayloadCapture(), - ...buildPosixHookSpoolLines('claude'), - ...(options.skipWhenDevinImportsClaude - ? [ - // Why: Devin imports .claude hooks by default; skip Orca's managed hook there so status posts stay attributed to Devin. - 'if [ -n "$DEVIN_PROJECT_DIR" ]; then', - ' exit 0', - 'fi' - ] - : []), - // Why: a backgrounded session runs in a daemon worker that inherited the dispatching - // pane's env, so ORCA_PANE_KEY names a pane this session does not run in (#9236). - 'if [ -n "$CLAUDE_JOB_DIR" ]; then', - ' exit 0', - 'fi', - // Why: refresh endpoint coordinates for PTYs surviving an Orca restart. - // Why: suppress parse errors so they neither leak nor trip outer set -e. - 'if [ -n "$ORCA_AGENT_HOOK_ENDPOINT" ] && [ -r "$ORCA_AGENT_HOOK_ENDPOINT" ]; then', - ' unset ORCA_AGENT_HOOK_TRANSPORT', - ' . "$ORCA_AGENT_HOOK_ENDPOINT" 2>/dev/null || :', - 'fi', - 'if [ -z "$ORCA_AGENT_HOOK_PORT" ] || [ -z "$ORCA_AGENT_HOOK_TOKEN" ] || [ -z "$ORCA_PANE_KEY" ]; then', - ' spool_hook_event', - ' exit 0', - 'fi', - // Why: keep full hook JSON off the command line and avoid IDS-friendly URL-encoded paths. - ...buildPosixAgentHookPostCommand('claude').map((line, index, lines) => - index === lines.length - 1 ? `${line} >/dev/null 2>&1 || spool_hook_event` : line - ), - 'exit 0', - '' - ].join('\n') -} - export class ClaudeHookService { private readonly options: ClaudeHookServiceOptions @@ -188,7 +114,10 @@ export class ClaudeHookService { async refreshManagedScripts(): Promise { await refreshManagedScriptIfPresent( getManagedScriptPath(this.options.settings), - getManagedScript('local', { skipWhenDevinImportsClaude: this.options.agent === 'claude' }) + getManagedScript('local', { + skipWhenDevinImportsClaude: this.options.agent === 'claude', + skipWhenGrokImportsClaude: this.options.agent === 'claude' + }) ) // Why: no agent gate — the statusline script only ever exists for claude, so presence is the gate. await refreshManagedScriptIfPresent( @@ -197,7 +126,7 @@ export class ClaudeHookService { ) } - install(): AgentHookInstallStatus { + install(options: ClaudeHookInstallOptions = {}): AgentHookInstallStatus { const configPath = getConfigPath(this.options.settings) const scriptPath = getManagedScriptPath(this.options.settings) const config = readHooksJson(configPath) @@ -215,11 +144,15 @@ export class ClaudeHookService { let nextConfig = applyManagedHooks( config, hook, - getManagedScriptFileName(this.options.settings) + getManagedScriptFileName(this.options.settings), + this.options.agent === 'claude' ? options : undefined ) writeManagedScript( scriptPath, - getManagedScript('local', { skipWhenDevinImportsClaude: this.options.agent === 'claude' }) + getManagedScript('local', { + skipWhenDevinImportsClaude: this.options.agent === 'claude', + skipWhenGrokImportsClaude: this.options.agent === 'claude' + }) ) // Why: the statusline usage feed is Claude-only — OpenClaude data would be misattributed to the Claude provider. if (this.options.agent === 'claude') { @@ -254,7 +187,11 @@ export class ClaudeHookService { } // Why: install the Claude hook on the remote box (via SFTP); POSIX-only by design (Windows-remote deferred). - async installRemote(sftp: SFTPWrapper, remoteHome: string): Promise { + async installRemote( + sftp: SFTPWrapper, + remoteHome: string, + options: ClaudeHookInstallOptions = {} + ): Promise { // Why: remote Windows is unsupported; local process.platform cannot identify the remote OS. const remoteConfigPath = getRemoteConfigPath(remoteHome, this.options.settings) const remoteScriptFileName = getPosixManagedScriptFileName(this.options.settings) @@ -274,14 +211,22 @@ export class ClaudeHookService { // Why: settings resolve HOME at runtime while SFTP still targets the discovered remote home. const hook = buildManagedCommandHook(getRemoteManagedCommand(remoteScriptPath)) - const nextConfig = applyManagedHooks(config, hook, remoteScriptFileName) + const nextConfig = applyManagedHooks( + config, + hook, + remoteScriptFileName, + this.options.agent === 'claude' ? options : undefined + ) // Why: write scripts before settings to avoid settings pointing to missing scripts. // Why: SSH scripts always use POSIX .sh paths, regardless of the local OS. await writeManagedScriptRemote( sftp, remoteScriptPath, - getManagedScript('posix', { skipWhenDevinImportsClaude: this.options.agent === 'claude' }) + getManagedScript('posix', { + skipWhenDevinImportsClaude: this.options.agent === 'claude', + skipWhenGrokImportsClaude: this.options.agent === 'claude' + }) ) // Why: no statusline install here — this path serves SSH remotes and WSL guests, whose relay hook // listener doesn't route /statusline/claude, and an SSH box's Claude login can be a different diff --git a/src/main/claude/hook-settings.ts b/src/main/claude/hook-settings.ts index 047fcbb26b6..92ffa9606a2 100644 --- a/src/main/claude/hook-settings.ts +++ b/src/main/claude/hook-settings.ts @@ -16,6 +16,7 @@ import { import { wrapRuntimeHomeHookCommand } from '../agent-hooks/runtime-home-hook-command' import { wrapWindowsDirectCmdHookCommand } from '../agent-hooks/windows-direct-cmd-hook-command' import { isGitBashAvailable } from '../git-bash' +import { claudeVersionSupportsSessionEnd } from './claude-session-end-hook-capability' export type ClaudeCompatibleHookSettings = { configDirName: '.claude' | '.openclaude' @@ -101,6 +102,15 @@ export const CLAUDE_EVENTS = [ } ] as const +const CLAUDE_SESSION_END_EVENT = { + eventName: 'SessionEnd', + definition: { hooks: [{ type: 'command', command: '' }] } +} as const + +export type ApplyManagedClaudeHooksOptions = { + claudeVersion?: string +} + export function getConfigPath(settings = CLAUDE_HOOK_SETTINGS): string { return join(homedir(), settings.configDirName, 'settings.json') } @@ -212,12 +222,15 @@ export function getRemoteManagedCommand(scriptPath: string): string { export function applyManagedHooks( config: HooksConfig, hook: HookCommandConfig, - scriptFileName = getManagedScriptFileName() + scriptFileName = getManagedScriptFileName(), + options: ApplyManagedClaudeHooksOptions = {} ): HooksConfig { const nextHooks = { ...config.hooks } const isManagedCommand = createManagedCommandMatcher(scriptFileName) + const sessionEndCapable = claudeVersionSupportsSessionEnd(options.claudeVersion) + const events = sessionEndCapable ? [...CLAUDE_EVENTS, CLAUDE_SESSION_END_EVENT] : CLAUDE_EVENTS - for (const event of CLAUDE_EVENTS) { + for (const event of events) { const current = Array.isArray(nextHooks[event.eventName]) ? nextHooks[event.eventName] : [] const cleaned = removeManagedCommands(current, isManagedCommand) const definition: HookDefinition = { @@ -227,6 +240,16 @@ export function applyManagedHooks( nextHooks[event.eventName] = [...cleaned, definition] } + if (!sessionEndCapable) { + const current = Array.isArray(nextHooks.SessionEnd) ? nextHooks.SessionEnd : [] + const cleaned = removeManagedCommands(current, isManagedCommand) + if (cleaned.length === 0) { + delete nextHooks.SessionEnd + } else { + nextHooks.SessionEnd = cleaned + } + } + return { ...config, hooks: nextHooks } } diff --git a/src/main/codex/codex-structured-fast-mode.test.ts b/src/main/codex/codex-structured-fast-mode.test.ts new file mode 100644 index 00000000000..917133c7543 --- /dev/null +++ b/src/main/codex/codex-structured-fast-mode.test.ts @@ -0,0 +1,145 @@ +import { describe, expect, it, vi } from 'vitest' +import { + USER_MESSAGE, + adapterFor, + fakeCodex, + identityFor, + type Route +} from './codex-structured-session-adapter-fixture' + +describe('Codex structured Fast mode dispatch', () => { + it('uses the provider-advertised Fast tier on the first turn after acquisition', async () => { + const codex = fakeCodex({ + 'model/list': () => ({ + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + serviceTiers: [{ id: 'priority-live-v2', name: 'Fast' }] + } + ], + nextCursor: null + }), + 'turn/start': () => ({ turn: { id: 'turn-fast' } }) + }) + const adapter = adapterFor(codex) + await adapter.acquire({ + identity: identityFor('session-1'), + fence: 7, + spawnToken: 'spawn-9', + options: { fastMode: 'true' } + }) + + await adapter.dispatch({ + sessionId: 'session-1', + clientMessageId: 'client-fast', + body: USER_MESSAGE, + fence: 7 + }) + + expect( + codex.connections[0].calls.find((call) => call.method === 'turn/start')?.params + ).toMatchObject({ serviceTier: 'priority-live-v2' }) + }) + + it('uses Standard on the first turn after acquisition with Fast explicitly off', async () => { + const codex = fakeCodex({ 'turn/start': () => ({ turn: { id: 'turn-standard' } }) }) + const adapter = adapterFor(codex) + await adapter.acquire({ + identity: identityFor('session-1'), + fence: 7, + spawnToken: 'spawn-9', + options: { fastMode: 'false' } + }) + + await adapter.dispatch({ + sessionId: 'session-1', + clientMessageId: 'client-standard', + body: USER_MESSAGE, + fence: 7 + }) + + expect( + codex.connections[0].calls.find((call) => call.method === 'turn/start')?.params + ).toMatchObject({ serviceTier: 'default' }) + expect(codex.connections[0].calls.some((call) => call.method === 'model/list')).toBe(false) + }) + + it.each(['absent', 'transient'] as const)( + 'uses Standard while restored Fast discovery is %s, then recovers the exact tier', + async (discovery) => { + const unavailableCatalog = () => { + if (discovery === 'transient') { + throw new Error('catalog temporarily unavailable') + } + return { + data: [{ model: 'gpt-live', supportedReasoningEfforts: [] }], + nextCursor: null + } + } + const listModels = vi.fn().mockImplementationOnce(unavailableCatalog) + if (discovery === 'absent') { + listModels.mockImplementationOnce(unavailableCatalog) + } + listModels.mockImplementation(() => ({ + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + serviceTiers: [{ id: 'priority-recovered', name: 'Fast' }] + } + ], + nextCursor: null + })) + const codex = fakeCodex({ + 'model/list': listModels, + 'turn/start': () => ({ turn: { id: 'turn-recovered' } }) + }) + const adapter = adapterFor(codex) + await expect( + adapter.acquire({ + identity: identityFor('session-1'), + fence: 7, + spawnToken: 'spawn-9', + options: { fastMode: 'true' } + }) + ).resolves.toBeDefined() + + await expect( + adapter.dispatch({ + sessionId: 'session-1', + clientMessageId: 'client-unverified', + body: USER_MESSAGE, + fence: 7 + }) + ).resolves.toMatchObject({ state: 'accepted' }) + expect( + codex.connections[0].calls.find((call) => call.method === 'turn/start')?.params + ).toMatchObject({ serviceTier: 'default' }) + + let options = await adapter.readOptions({ sessionId: 'session-1', fence: 7 }) + expect(options).toMatchObject({ + current: { fastMode: true } + }) + if (discovery === 'absent') { + expect(options.fastModeSupport).toBeUndefined() + expect(options.models[0]?.supportsFastMode).toBeUndefined() + options = await adapter.readOptions({ sessionId: 'session-1', fence: 7 }) + } + expect(options).toMatchObject({ + models: [expect.objectContaining({ supportsFastMode: true })], + fastModeSupport: { supported: true }, + current: { fastMode: true } + }) + await adapter.dispatch({ + sessionId: 'session-1', + clientMessageId: 'client-recovered', + body: USER_MESSAGE, + fence: 7 + }) + expect( + codex.connections[0].calls.filter((call) => call.method === 'turn/start')[1]?.params + ).toMatchObject({ serviceTier: 'priority-recovered' }) + } + ) +}) diff --git a/src/main/codex/codex-structured-fast-mode.ts b/src/main/codex/codex-structured-fast-mode.ts new file mode 100644 index 00000000000..145d3ff2a8f --- /dev/null +++ b/src/main/codex/codex-structured-fast-mode.ts @@ -0,0 +1,106 @@ +import type { + AgentSessionFastModeSupport, + AgentSessionModelOption +} from '../../shared/agent-session-wire' +import { decodeStructuredAgentSessionOptionValue } from '../../shared/structured-agent-session-option-codec' +import type { CodexOpenedThread } from './codex-structured-thread-open' +import type { CodexSession } from './codex-structured-session-state' + +function record(value: unknown): Record | null { + return typeof value === 'object' && value !== null ? (value as Record) : null +} + +function text(value: unknown): string | null { + return typeof value === 'string' && value.trim() ? value : null +} + +export function readCodexFastModeTier(row: Record): { + id?: string + supportKnown: boolean +} { + const modern = Array.isArray(row.serviceTiers) ? row.serviceTiers : null + const advertised = modern?.flatMap((value) => { + const tier = record(value) + const id = text(tier?.id) + const name = text(tier?.name) + return id && name ? [{ id, name }] : [] + }) + const exactModern = advertised?.find( + (tier) => tier.name.toLowerCase() === 'fast' || tier.id.toLowerCase() === 'fast' + ) + if (exactModern) { + return { id: exactModern.id, supportKnown: true } + } + const legacy = Array.isArray(row.additionalSpeedTiers) ? row.additionalSpeedTiers : null + const exactLegacy = legacy?.map(text).find((tier) => tier?.toLowerCase() === 'fast') + return { + ...(exactLegacy ? { id: exactLegacy } : {}), + supportKnown: modern !== null || legacy !== null + } +} + +export function codexFastModeSupport( + models: readonly AgentSessionModelOption[] +): AgentSessionFastModeSupport | undefined { + if (models.some((model) => model.supportsFastMode === true)) { + return { supported: true } + } + return models.length > 0 && models.every((model) => model.supportsFastMode === false) + ? { supported: false, reason: 'model-not-supported' } + : undefined +} + +export function decodeCodexFastMode(options: ReadonlyMap): boolean | undefined { + const encoded = options.get('fastMode') + if (encoded === undefined) { + return undefined + } + const decoded = decodeStructuredAgentSessionOptionValue('fastMode', encoded) + return typeof decoded === 'boolean' ? decoded : undefined +} + +export function reportedCodexThreadOptions( + opened: CodexOpenedThread +): CodexSession['reportedOptions'] { + return { + ...(opened.model ? { model: opened.model } : {}), + ...(opened.effort ? { effort: opened.effort } : {}), + ...('serviceTier' in opened + ? { serviceTier: opened.serviceTier ?? null, serviceTierKnown: true as const } + : {}) + } +} + +export function reconcileCodexFastModeOption( + session: CodexSession, + input: { + fastModeTierByModel: Map + currentFastMode: boolean | undefined + model: string + modelFastModeSupport: boolean | undefined + } +): void { + session.fastModeTierByModel = input.fastModeTierByModel + const encoded = session.options.get('fastMode') + if (encoded !== undefined && decodeCodexFastMode(session.options) === undefined) { + session.options.delete('fastMode') + } + const legacyTier = session.options.get('serviceTier') + session.options.delete('serviceTier') + if (session.options.has('fastMode')) { + if (session.options.get('fastMode') === 'true' && input.modelFastModeSupport === false) { + session.options.set('fastMode', 'false') + } + return + } + if (legacyTier === 'default') { + session.options.set('fastMode', 'false') + } else if ( + legacyTier !== undefined && + legacyTier === input.fastModeTierByModel.get(input.model) + ) { + session.options.set('fastMode', 'true') + } else if (legacyTier === undefined && input.currentFastMode !== undefined) { + session.options.set('fastMode', String(input.currentFastMode)) + } +} diff --git a/src/main/codex/codex-structured-journal-settlement.ts b/src/main/codex/codex-structured-journal-settlement.ts index 5785b273e92..5aa158fafc7 100644 --- a/src/main/codex/codex-structured-journal-settlement.ts +++ b/src/main/codex/codex-structured-journal-settlement.ts @@ -9,10 +9,7 @@ import type { StructuredAgentSessionEventSink, StructuredAgentSessionSinkAdmission } from '../native-chat/agent-session-wire/structured-agent-session-event-sink' -import { - boundJournalStatusText, - cancelledJournalPromptBody -} from '../native-chat/agent-session-journal/journal-prompt-body-bounds' +import { cancelledJournalPromptBody } from '../native-chat/agent-session-journal/journal-prompt-body-bounds' import { codexJournalItem, codexStreamingJournalItem, @@ -75,16 +72,6 @@ export function settleCodexJournalSession(input: { }) } } - if (!('cause' in input.event) || input.event.cause === 'unexpected-exit') { - mutations.push({ - kind: 'item', - identity: { provider: 'orca', clientMessageId: exitSettlementId(input.event) }, - body: { - kind: 'status', - text: boundJournalStatusText(`Provider exited: ${input.event.reason}`) - } - }) - } for (const [threadId, turnIds] of input.currentTurnIds) { if (input.primaryThreadId !== threadId) { continue diff --git a/src/main/codex/codex-structured-journal-translation-settlement.test.ts b/src/main/codex/codex-structured-journal-translation-settlement.test.ts index b5e60699ce1..ab0e602e955 100644 --- a/src/main/codex/codex-structured-journal-translation-settlement.test.ts +++ b/src/main/codex/codex-structured-journal-translation-settlement.test.ts @@ -270,7 +270,6 @@ describe('codex journal translation', () => { kind: 'approval', resolution: expect.objectContaining({ state: 'cancelled' }) }), - { kind: 'status', text: 'Provider exited: lost child' }, expect.objectContaining({ kind: 'turn', turnId: TURN_ID, state: 'interrupted' }) ]) expect(publishes).toHaveLength(2) @@ -342,9 +341,6 @@ describe('codex journal translation', () => { resolution: expect.objectContaining({ state: 'cancelled' }) }) }), - expect.objectContaining({ - body: { kind: 'status', text: 'Provider exited: lost child' } - }), expect.objectContaining({ kind: 'item', body: expect.objectContaining({ kind: 'turn', turnId: TURN_ID, state: 'interrupted' }) @@ -416,11 +412,7 @@ describe('codex journal translation', () => { `provider-exit:${SESSION_ID}:7:generation-1:${index + 1}/${batches.length}` ) ) - expect(flattened).toHaveLength(122) - expect(flattened.at(-2)).toMatchObject({ - kind: 'item', - body: { kind: 'status', text: 'Provider exited: lost child' } - }) + expect(flattened).toHaveLength(121) expect(flattened.at(-1)).toMatchObject({ kind: 'item', body: { kind: 'turn', state: 'interrupted' } diff --git a/src/main/codex/codex-structured-journal-translation.test.ts b/src/main/codex/codex-structured-journal-translation.test.ts index 7e2b2f45bea..443d61a8e27 100644 --- a/src/main/codex/codex-structured-journal-translation.test.ts +++ b/src/main/codex/codex-structured-journal-translation.test.ts @@ -268,7 +268,6 @@ describe('codex journal translation', () => { expect(tap.rows.map((row) => row.body)).toEqual([ expect.objectContaining({ kind: 'turn', turnId: 'turn-stale', state: 'running' }), expect.objectContaining({ kind: 'turn', turnId: 'turn-later', state: 'running' }), - expect.objectContaining({ text: 'Provider exited: app-server exited' }), expect.objectContaining({ kind: 'turn', turnId: 'turn-stale', state: 'interrupted' }), expect.objectContaining({ kind: 'turn', turnId: 'turn-later', state: 'interrupted' }) ]) @@ -440,14 +439,13 @@ describe('codex journal translation', () => { expect(tap.rows.map((row) => row.body)).toEqual( expect.arrayContaining([ - expect.objectContaining({ blocks: [{ type: 'text', text: 'half' }] }), - { kind: 'status', text: 'Provider exited: app-server exited' } + expect.objectContaining({ blocks: [{ type: 'text', text: 'half' }] }) ]) ) expect(window.idle()).toBe(true) }) - it('settles tools, prompts, exit status, and turn lifecycle in one ordered batch', () => { + it('settles tools, prompts, and turn lifecycle in one ordered batch', () => { const tap = recorder() const batches: { settlementId: string; mutations: unknown[] }[] = [] tap.sink.appendLifecycleBatch = (settlementId, mutations) => { @@ -500,10 +498,6 @@ describe('codex journal translation', () => { resolution: expect.objectContaining({ state: 'cancelled' }) }) }), - expect.objectContaining({ - kind: 'item', - body: { kind: 'status', text: 'Provider exited: lost child' } - }), expect.objectContaining({ kind: 'item', body: expect.objectContaining({ kind: 'turn', turnId: TURN_ID, state: 'interrupted' }) diff --git a/src/main/codex/codex-structured-model-catalog.ts b/src/main/codex/codex-structured-model-catalog.ts new file mode 100644 index 00000000000..37a89e5ba4a --- /dev/null +++ b/src/main/codex/codex-structured-model-catalog.ts @@ -0,0 +1,160 @@ +import type { + AgentSessionModelOption, + AgentSessionOptionChoice, + AgentSessionOptionsResult +} from '../../shared/agent-session-wire' +import type { CodexAppServerConnection } from './codex-app-server-connection' +import { codexFastModeSupport, readCodexFastModeTier } from './codex-structured-fast-mode' + +const MODEL_PAGE_LIMIT = 100 +const MAX_MODEL_PAGES = 20 + +function record(value: unknown): Record | null { + return typeof value === 'object' && value !== null ? (value as Record) : null +} + +function text(value: unknown): string | null { + return typeof value === 'string' && value.trim() ? value : null +} + +function effortLabel(value: string): string { + return value === 'xhigh' + ? 'Extra high' + : value === 'minimal' + ? 'Minimal' + : `${value.charAt(0).toUpperCase()}${value.slice(1)}` +} + +function effortChoice(value: unknown): AgentSessionOptionChoice | null { + const row = record(value) + const effort = text(row?.reasoningEffort) + if (!effort) { + return null + } + const description = text(row?.description) + return { + value: effort, + label: effortLabel(effort), + ...(description ? { description } : {}) + } +} + +type ParsedCodexModelOption = { + option: AgentSessionModelOption + fastModeTierId?: string +} + +function modelOption(value: unknown): ParsedCodexModelOption | null { + const row = record(value) + if (!row) { + return null + } + const id = text(row.model) ?? text(row.id) + const label = text(row.displayName) ?? id + if (!id || !label || row.hidden === true) { + return null + } + const description = text(row.description) + const defaultEffort = text(row.defaultReasoningEffort) + const efforts = Array.isArray(row.supportedReasoningEfforts) + ? row.supportedReasoningEfforts + .map(effortChoice) + .filter((choice): choice is AgentSessionOptionChoice => choice !== null) + : [] + const fastMode = readCodexFastModeTier(row) + return { + option: { + id, + label, + ...(description ? { description } : {}), + isDefault: row.isDefault === true, + ...(defaultEffort ? { defaultEffort } : {}), + efforts, + ...(fastMode.supportKnown ? { supportsFastMode: Boolean(fastMode.id) } : {}) + }, + ...(fastMode.id ? { fastModeTierId: fastMode.id } : {}) + } +} + +export type CodexSessionOptionCatalog = { + result: AgentSessionOptionsResult + fastModeTierByModel: Map +} + +export async function readCodexStructuredSessionOptionCatalog(input: { + connection: Pick + current: { model?: string; effort?: string; fastMode?: boolean } + reportedServiceTier?: string | null + reportedServiceTierKnown?: boolean + timeoutMs?: number +}): Promise { + const parsedModels: ParsedCodexModelOption[] = [] + let cursor: string | null = null + for (let page = 0; page < MAX_MODEL_PAGES; page += 1) { + const response = record( + await input.connection.request( + 'model/list', + { limit: MODEL_PAGE_LIMIT, includeHidden: false, ...(cursor ? { cursor } : {}) }, + { timeoutMs: input.timeoutMs } + ) + ) + const rows = Array.isArray(response?.data) ? response.data : [] + for (const row of rows) { + const parsed = modelOption(row) + if (parsed && !parsedModels.some((model) => model.option.id === parsed.option.id)) { + parsedModels.push(parsed) + } + } + cursor = text(response?.nextCursor) + if (!cursor) { + break + } + } + if ( + input.current.model && + !parsedModels.some((model) => model.option.id === input.current.model) + ) { + parsedModels.push({ + option: { + id: input.current.model, + label: input.current.model, + isDefault: false, + efforts: [] + } + }) + } + const models = parsedModels.map((entry) => entry.option) + const model = input.current.model ?? models.find((entry) => entry.isDefault)?.id ?? models[0]?.id + if (!model) { + throw new Error('codex app-server returned no available models') + } + const fastModeTierByModel = new Map( + parsedModels.flatMap((entry) => + entry.fastModeTierId ? [[entry.option.id, entry.fastModeTierId] as const] : [] + ) + ) + const reportedFastMode = input.reportedServiceTierKnown + ? input.reportedServiceTier === null || input.reportedServiceTier === 'default' + ? false + : input.reportedServiceTier === fastModeTierByModel.get(model) + ? true + : undefined + : undefined + const fastMode = input.current.fastMode ?? reportedFastMode + const support = codexFastModeSupport(models) + return { + result: { + models, + ...(support ? { fastModeSupport: support } : {}), + current: { + model, + ...(input.current.effort ? { effort: input.current.effort } : {}), + ...(fastMode !== undefined ? { fastMode } : {}), + ...(reportedFastMode !== undefined && input.current.fastMode === undefined + ? { confirmed: ['fastMode'] } + : {}) + } + }, + fastModeTierByModel + } +} diff --git a/src/main/codex/codex-structured-session-acquire.ts b/src/main/codex/codex-structured-session-acquire.ts index c9a306128b6..b5cdd2caf4e 100644 --- a/src/main/codex/codex-structured-session-acquire.ts +++ b/src/main/codex/codex-structured-session-acquire.ts @@ -20,9 +20,13 @@ import { handleCodexSessionExit } from './codex-structured-session-close' import { - reportedCodexThreadOptions, + readCodexStructuredSessionOptionCatalog, restoredCodexSessionOptions } from './codex-structured-session-options' +import { + reconcileCodexFastModeOption, + reportedCodexThreadOptions +} from './codex-structured-fast-mode' import { codexSessionLifecycle, mintCodexAcquisitionGeneration, @@ -196,6 +200,23 @@ export async function acquireCodexStructuredSession(input: { throw new Error(`codex app-server for session ${sessionId} exited while being acquired`) } acquisitions.assertCurrent(sessionId, attempt) + const options = restoredCodexSessionOptions(acquireInput.options) + const fastModeCatalog = + options.get('fastMode') === 'true' || options.has('serviceTier') + ? await readCodexStructuredSessionOptionCatalog({ + connection, + current: { + ...(opened.model ? { model: opened.model } : {}), + ...(opened.effort ? { effort: opened.effort } : {}), + fastMode: true + }, + timeoutMs: deps.requestTimeoutMs + }).catch(() => null) + : null + acquisitions.assertCurrent(sessionId, attempt) + if (connection.closed) { + throw new Error(`codex app-server for session ${sessionId} exited while being acquired`) + } acquisitions.deleteIfCurrent(sessionId, attempt) const session: CodexSession = { connection, @@ -205,8 +226,9 @@ export async function acquireCodexStructuredSession(input: { historyMode: opened.historyMode, activeTurnIds: new Set(), prompts: acquisition.prompts, - options: restoredCodexSessionOptions(acquireInput.options), + options, reportedOptions: reportedCodexThreadOptions(opened), + fastModeTierByModel: fastModeCatalog?.fastModeTierByModel ?? new Map(), turnIdWaiters: [], translator, backgroundTasks: new CodexBackgroundTaskTracker(opened.threadId, subagentExecutions), @@ -219,6 +241,16 @@ export async function acquireCodexStructuredSession(input: { ), ...(unbindReadingControl ? { unbindReadingControl } : {}) } + if (fastModeCatalog) { + const model = opened.model ?? fastModeCatalog.result.current.model + reconcileCodexFastModeOption(session, { + fastModeTierByModel: fastModeCatalog.fastModeTierByModel, + currentFastMode: true, + model, + modelFastModeSupport: fastModeCatalog.result.models.find((entry) => entry.id === model) + ?.supportsFastMode + }) + } turnCancellation.register(session) sessions.set(sessionId, session) for (const event of acquisition.drain()) { diff --git a/src/main/codex/codex-structured-session-adapter-fixture.ts b/src/main/codex/codex-structured-session-adapter-fixture.ts new file mode 100644 index 00000000000..3f2d32ee2eb --- /dev/null +++ b/src/main/codex/codex-structured-session-adapter-fixture.ts @@ -0,0 +1,129 @@ +import type { + AgentJournalMessageItem, + AgentSessionJournalIdentity +} from '../../shared/agent-session-journal-types' +import type { + CodexAppServerConnection, + CodexAppServerConnectionHandlers, + CodexAppServerLaunch, + openCodexAppServerConnection +} from './codex-app-server-connection' +import { + CodexStructuredSessionAdapter, + type CodexStructuredLaunch, + type CodexStructuredSessionAdapterDeps, + type CodexStructuredSessionEvent +} from './codex-structured-session-adapter' + +export const THREAD_ID = 'thread-abc' + +export function identityFor(sessionId: string): AgentSessionJournalIdentity { + return { + sessionId, + workspaceId: 'ws-1', + hostId: 'host-1', + agent: 'codex', + providerHandle: { kind: 'codex', threadId: THREAD_ID } + } +} + +export const USER_MESSAGE: AgentJournalMessageItem = { + kind: 'message', + role: 'user', + blocks: [{ type: 'text', text: 'ship it' }] +} + +export type Route = (params: Record | undefined) => unknown + +type FakeConnection = Omit & { + closed: boolean + launch: CodexAppServerLaunch + handlers: CodexAppServerConnectionHandlers + calls: { method: string; params?: Record }[] + replies: { id: number | string; result?: unknown; code?: number; message?: string }[] + closeCount: number +} + +export function fakeCodex(routes: Record = {}): { + connections: FakeConnection[] + openConnection: typeof openCodexAppServerConnection + routes: Record +} { + const connections: FakeConnection[] = [] + const openConnection = (async (launch, handlers = {}) => { + const connection: FakeConnection = { + launch, + handlers, + calls: [], + replies: [], + closeCount: 0, + pid: 4321, + closed: false, + request: async (method, params) => { + connection.calls.push({ method, params }) + const route = routes[method] + return route ? route(params) : {} + }, + notify: () => {}, + respond: (id, result) => connection.replies.push({ id, result }), + respondWithError: (id, code, message) => connection.replies.push({ id, code, message }), + close: async () => { + connection.closeCount += 1 + connection.closed = true + return true + } + } + connections.push(connection) + return connection + }) as typeof openCodexAppServerConnection + routes['thread/start'] ??= () => ({ + thread: { id: THREAD_ID, path: '/rollouts/abc.jsonl' }, + model: 'gpt-live', + reasoningEffort: 'medium' + }) + routes['thread/resume'] ??= (params) => ({ + thread: { id: (params as { threadId: string }).threadId }, + model: 'gpt-live', + reasoningEffort: 'medium' + }) + return { connections, openConnection, routes } +} + +export function adapterFor( + codex: ReturnType, + launch: Partial = {}, + events: CodexStructuredSessionEvent[] = [], + processControl: Partial< + Pick + > = {} +): CodexStructuredSessionAdapter { + let acquisitionGeneration = 0 + return new CodexStructuredSessionAdapter({ + resolveLaunch: async () => ({ + command: 'codex', + args: ['app-server'], + cwd: '/work/repo', + codexHome: null, + resumeThreadId: null, + ...launch + }), + onEvent: (event) => events.push(event), + openConnection: codex.openConnection, + readProcessStartTime: async () => 1_700_000_000_000, + captureTurnProcesses: async () => ({ platform: 'win32', identities: new Map() }), + terminateTurnProcesses: async () => true, + now: () => 1_700_000_000_500, + mintAcquisitionGeneration: () => `generation-${++acquisitionGeneration}`, + ...processControl + }) +} + +export async function acquired( + codex: ReturnType, + launch: Partial = {}, + events: CodexStructuredSessionEvent[] = [] +): Promise { + const adapter = adapterFor(codex, launch, events) + await adapter.acquire({ identity: identityFor('session-1'), fence: 7, spawnToken: 'spawn-9' }) + return adapter +} diff --git a/src/main/codex/codex-structured-session-adapter.test.ts b/src/main/codex/codex-structured-session-adapter.test.ts index 32492762121..b32c7e69a1b 100644 --- a/src/main/codex/codex-structured-session-adapter.test.ts +++ b/src/main/codex/codex-structured-session-adapter.test.ts @@ -1,14 +1,7 @@ import { describe, expect, it, vi } from 'vitest' -import type { - AgentJournalMessageItem, - AgentSessionJournalIdentity -} from '../../shared/agent-session-journal-types' -import { CodexAppServerRequestError } from './codex-app-server-connection' -import type { - CodexAppServerConnection, - CodexAppServerConnectionHandlers, - CodexAppServerLaunch, - openCodexAppServerConnection +import { + CodexAppServerRequestError, + type openCodexAppServerConnection } from './codex-app-server-connection' import type { StructuredAgentSessionEventSink } from '../native-chat/agent-session-wire/structured-agent-session-event-sink' import { CODEX_SPAWN_TOKEN_ENV } from './codex-structured-owner-identity' @@ -17,126 +10,16 @@ import { encodeCodexQuestionOptionId } from './codex-structured-prompt-replies' import { CodexStructuredSessionAdapter, type CodexStructuredLaunch, - type CodexStructuredSessionAdapterDeps, type CodexStructuredSessionEvent } from './codex-structured-session-adapter' - -const THREAD_ID = 'thread-abc' - -function identityFor(sessionId: string): AgentSessionJournalIdentity { - return { - sessionId, - workspaceId: 'ws-1', - hostId: 'host-1', - agent: 'codex', - providerHandle: { kind: 'codex', threadId: THREAD_ID } - } -} - -const USER_MESSAGE: AgentJournalMessageItem = { - kind: 'message', - role: 'user', - blocks: [{ type: 'text', text: 'ship it' }] -} - -type Route = (params: Record | undefined) => unknown - -// `closed` is readonly on the real connection; the fake flips it so a test can -// kill the child at a chosen moment. -type FakeConnection = Omit & { - closed: boolean - launch: CodexAppServerLaunch - handlers: CodexAppServerConnectionHandlers - calls: { method: string; params?: Record }[] - replies: { id: number | string; result?: unknown; code?: number; message?: string }[] - closeCount: number -} - -/** Stands in for a live `codex app-server`: every RPC is answered from `routes`, - * and the test drives Codex's own traffic through `handlers`. */ -function fakeCodex(routes: Record = {}): { - connections: FakeConnection[] - openConnection: typeof openCodexAppServerConnection - routes: Record -} { - const connections: FakeConnection[] = [] - const openConnection = (async (launch, handlers = {}) => { - const connection: FakeConnection = { - launch, - handlers, - calls: [], - replies: [], - closeCount: 0, - pid: 4321, - closed: false, - request: async (method, params) => { - connection.calls.push({ method, params }) - const route = routes[method] - return route ? route(params) : {} - }, - notify: () => {}, - respond: (id, result) => connection.replies.push({ id, result }), - respondWithError: (id, code, message) => connection.replies.push({ id, code, message }), - close: async () => { - connection.closeCount += 1 - connection.closed = true - return true - } - } - connections.push(connection) - return connection - }) as typeof openCodexAppServerConnection - routes['thread/start'] ??= () => ({ - thread: { id: THREAD_ID, path: '/rollouts/abc.jsonl' }, - model: 'gpt-live', - reasoningEffort: 'medium' - }) - routes['thread/resume'] ??= (params) => ({ - thread: { id: (params as { threadId: string }).threadId }, - model: 'gpt-live', - reasoningEffort: 'medium' - }) - return { connections, openConnection, routes } -} - -function adapterFor( - codex: ReturnType, - launch: Partial = {}, - events: CodexStructuredSessionEvent[] = [], - processControl: Partial< - Pick - > = {} -): CodexStructuredSessionAdapter { - let acquisitionGeneration = 0 - return new CodexStructuredSessionAdapter({ - resolveLaunch: async () => ({ - command: 'codex', - args: ['app-server'], - cwd: '/work/repo', - codexHome: null, - resumeThreadId: null, - ...launch - }), - onEvent: (event) => events.push(event), - openConnection: codex.openConnection, - readProcessStartTime: async () => 1_700_000_000_000, - captureTurnProcesses: async () => ({ platform: 'win32', identities: new Map() }), - terminateTurnProcesses: async () => true, - now: () => 1_700_000_000_500, - mintAcquisitionGeneration: () => `generation-${++acquisitionGeneration}`, - ...processControl - }) -} - -async function acquired( - codex: ReturnType, - launch: Partial = {}, - events: CodexStructuredSessionEvent[] = [] -): Promise { - const adapter = adapterFor(codex, launch, events) - await adapter.acquire({ identity: identityFor('session-1'), fence: 7, spawnToken: 'spawn-9' }) - return adapter -} +import { + THREAD_ID, + USER_MESSAGE, + acquired, + adapterFor, + fakeCodex, + identityFor +} from './codex-structured-session-adapter-fixture' describe('CodexStructuredSessionAdapter.acquire', () => { it('starts a new thread and reports the process and link the lease will prove', async () => { diff --git a/src/main/codex/codex-structured-session-background-tasks.test.ts b/src/main/codex/codex-structured-session-background-tasks.test.ts index 54282e3d107..97b6f4e47a5 100644 --- a/src/main/codex/codex-structured-session-background-tasks.test.ts +++ b/src/main/codex/codex-structured-session-background-tasks.test.ts @@ -198,7 +198,6 @@ describe('codex background tasks reach the strip', () => { await vi.waitFor(() => expect(adapter.backgroundTaskState('session-1')).toBeUndefined()) // The open turn's lifecycle row is revised to interrupted, never tombstoned. expect(appendItem.mock.calls.map((call) => call[1])).toEqual([ - { kind: 'status', text: 'Provider exited: notification admission failed (failed)' }, expect.objectContaining({ kind: 'turn', state: 'interrupted' }) ]) expect(observed).toEqual([ diff --git a/src/main/codex/codex-structured-session-close.test.ts b/src/main/codex/codex-structured-session-close.test.ts index 45bfbbf45a1..58c5bc5f50a 100644 --- a/src/main/codex/codex-structured-session-close.test.ts +++ b/src/main/codex/codex-structured-session-close.test.ts @@ -89,6 +89,7 @@ describe('Codex structured session close lifecycle', () => { handle: vi.fn().mockReturnValueOnce({ accepted: false, reason: 'backpressure' as const }), dispose: vi.fn() } as unknown as NonNullable + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the literal supplies every CodexSession field the close path reads; the rest are unused by it. const session = { connection, backgroundTasks: new CodexBackgroundTaskTracker('thread-1'), @@ -101,6 +102,7 @@ describe('Codex structured session close lifecycle', () => { prompts, options: new Map(), reportedOptions: {}, + fastModeTierByModel: new Map(), turnIdWaiters: [], translator } as CodexSession diff --git a/src/main/codex/codex-structured-session-options.test.ts b/src/main/codex/codex-structured-session-options.test.ts index b081e52dd6a..4e9abfc17b5 100644 --- a/src/main/codex/codex-structured-session-options.test.ts +++ b/src/main/codex/codex-structured-session-options.test.ts @@ -4,11 +4,13 @@ import { CodexAcquisitionWindow } from './codex-structured-acquisition-window' import { applyCodexStructuredSessionOption, readCodexStructuredSessionOptions, - reportedCodexThreadOptions, + readLiveCodexSessionOptions, restoredCodexSessionOptions } from './codex-structured-session-options' +import { reportedCodexThreadOptions } from './codex-structured-fast-mode' import { CodexBackgroundTaskTracker } from './codex-background-task-tracker' import type { CodexSession } from './codex-structured-session-state' +import { startCodexTurn } from './codex-structured-turn-start' function optionSession(request: CodexAppServerConnection['request']): CodexSession { return { @@ -31,6 +33,7 @@ function optionSession(request: CodexAppServerConnection['request']): CodexSessi prompts: new CodexAcquisitionWindow().prompts, options: new Map(), reportedOptions: { model: 'gpt-live', effort: 'high' }, + fastModeTierByModel: new Map(), turnIdWaiters: [], translator: null } @@ -48,6 +51,9 @@ describe('structured Codex session options', () => { }) ) ).toEqual({ model: 'gpt-live', effort: 'high' }) + expect(Object.fromEntries(restoredCodexSessionOptions({ serviceTier: 'default' }))).toEqual({ + fastMode: 'false' + }) }) it('hydrates paged provider models and their supported efforts', async () => { @@ -173,4 +179,306 @@ describe('structured Codex session options', () => { applyCodexStructuredSessionOption(session, 'effort', 'high', undefined) ).rejects.toThrow('does not support high') }) + + it('maps canonical Fast on and off to the exact advertised tier and Standard', async () => { + const requests: { method: string; params?: Record }[] = [] + const request = vi.fn(async (method: string, params?: Record) => { + requests.push({ method, params }) + return method === 'model/list' + ? { + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + serviceTiers: [ + { id: 'rush-v7', name: 'Fast', description: 'Provider-routed Fast tier' } + ] + } + ], + nextCursor: null + } + : { turn: { id: `turn-${requests.length}` } } + }) + const session = optionSession(request) + + await expect( + applyCodexStructuredSessionOption(session, 'fastMode', 'true', undefined) + ).resolves.toMatchObject({ fastMode: 'true' }) + await startCodexTurn(session, { + clientMessageId: 'message-on', + body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'on' }] } + }) + expect(requests.find((entry) => entry.method === 'turn/start')?.params).toMatchObject({ + serviceTier: 'rush-v7' + }) + + await applyCodexStructuredSessionOption(session, 'fastMode', 'false', undefined) + await startCodexTurn(session, { + clientMessageId: 'message-off', + body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'off' }] } + }) + expect(requests.filter((entry) => entry.method === 'turn/start')[1]?.params).toMatchObject({ + serviceTier: 'default' + }) + }) + + it('reports the current Fast value only when the opened thread tier matches the catalog', async () => { + const connection = { + request: vi.fn(async () => ({ + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + serviceTiers: [{ id: 'priority-current', name: 'Fast' }] + } + ], + nextCursor: null + })) + } + + await expect( + readCodexStructuredSessionOptions({ + connection, + current: { model: 'gpt-live' }, + reportedServiceTier: 'priority-current', + reportedServiceTierKnown: true + }) + ).resolves.toMatchObject({ current: { fastMode: true, confirmed: ['fastMode'] } }) + const unknown = await readCodexStructuredSessionOptions({ + connection, + current: { model: 'gpt-live' }, + reportedServiceTier: 'unrecognized-tier', + reportedServiceTierKnown: true + }) + expect(unknown.current).toEqual({ model: 'gpt-live' }) + }) + + it('hides and rejects Fast mode when the running catalog does not advertise it', async () => { + const session = optionSession( + vi.fn(async () => ({ + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + serviceTiers: [] + } + ], + nextCursor: null + })) + ) + + await expect( + readCodexStructuredSessionOptions({ + connection: session.connection, + current: { model: 'gpt-live' } + }) + ).resolves.toMatchObject({ + models: [expect.objectContaining({ supportsFastMode: false })], + fastModeSupport: { supported: false } + }) + await expect( + applyCodexStructuredSessionOption(session, 'fastMode', 'true', undefined) + ).rejects.toThrow('does not support Fast mode') + }) + + it('reconciles restored Fast on to explicit Standard when the selected model lost support', async () => { + const requests: { method: string; params?: Record }[] = [] + const session = optionSession( + vi.fn(async (method: string, params?: Record) => { + requests.push({ method, params }) + return method === 'model/list' + ? { + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + serviceTiers: [] + } + ], + nextCursor: null + } + : { turn: { id: 'turn-standard' } } + }) + ) + session.options.set('fastMode', 'true') + + await expect(readLiveCodexSessionOptions(session, undefined)).resolves.toMatchObject({ + current: { fastMode: false } + }) + expect(Object.fromEntries(session.options)).toEqual({ fastMode: 'false' }) + + await startCodexTurn(session, { + clientMessageId: 'message-standard', + body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'standard' }] } + }) + expect(requests.find((entry) => entry.method === 'turn/start')?.params).toMatchObject({ + serviceTier: 'default' + }) + }) + + it('uses Standard until a missing Fast catalog recovers without losing restored intent', async () => { + const requests: { method: string; params?: Record }[] = [] + let catalogRecovered = false + const request = vi.fn(async (method: string, params?: Record) => { + requests.push({ method, params }) + if (method === 'turn/start') { + return { turn: { id: `turn-${requests.length}` } } + } + return { + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + ...(catalogRecovered + ? { serviceTiers: [{ id: 'priority-recovered', name: 'Fast' }] } + : {}) + } + ], + nextCursor: null + } + }) + const session = optionSession(request) + session.options.set('fastMode', 'true') + + const unknown = await readLiveCodexSessionOptions(session, undefined) + expect(unknown).toMatchObject({ + current: { fastMode: true } + }) + expect(unknown.fastModeSupport).toBeUndefined() + expect(unknown.models[0]?.supportsFastMode).toBeUndefined() + expect(session.options.get('fastMode')).toBe('true') + await startCodexTurn(session, { + clientMessageId: 'message-unverified', + body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'unverified' }] } + }) + expect(requests.find((entry) => entry.method === 'turn/start')?.params).toMatchObject({ + serviceTier: 'default' + }) + expect(session.options.get('fastMode')).toBe('true') + + catalogRecovered = true + await expect(readLiveCodexSessionOptions(session, undefined)).resolves.toMatchObject({ + models: [expect.objectContaining({ supportsFastMode: true })], + fastModeSupport: { supported: true }, + current: { fastMode: true } + }) + await startCodexTurn(session, { + clientMessageId: 'message-recovered', + body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'recovered' }] } + }) + expect(requests.filter((entry) => entry.method === 'turn/start')[1]?.params).toMatchObject({ + serviceTier: 'priority-recovered' + }) + }) + + it('allows explicit Fast off without positive model support', async () => { + const requests: { method: string; params?: Record }[] = [] + const session = optionSession( + vi.fn(async (method: string, params?: Record) => { + requests.push({ method, params }) + return method === 'model/list' + ? { + data: [{ model: 'gpt-live', supportedReasoningEfforts: [] }], + nextCursor: null + } + : { turn: { id: 'turn-standard' } } + }) + ) + + await expect( + applyCodexStructuredSessionOption(session, 'fastMode', 'false', undefined) + ).resolves.toMatchObject({ fastMode: 'false' }) + await startCodexTurn(session, { + clientMessageId: 'message-standard', + body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'standard' }] } + }) + expect(requests.find((entry) => entry.method === 'turn/start')?.params).toMatchObject({ + serviceTier: 'default' + }) + }) + + it('uses only the bounded legacy Fast tier value the provider advertised', async () => { + const result = await readCodexStructuredSessionOptions({ + connection: { + request: vi.fn(async () => ({ + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + additionalSpeedTiers: ['fast'] + } + ], + nextCursor: null + })) + }, + current: { model: 'gpt-live' } + }) + expect(result.models[0]).toMatchObject({ supportsFastMode: true }) + expect(result.fastModeSupport).toEqual({ supported: true }) + }) + + it('normalizes a legacy durable tier while preserving a canonical explicit choice', async () => { + const request = vi.fn(async () => ({ + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + serviceTiers: [{ id: 'priority-migrated', name: 'Fast' }] + } + ], + nextCursor: null + })) + const migrated = optionSession(request) + migrated.options.set('serviceTier', 'priority-migrated') + + await expect(readLiveCodexSessionOptions(migrated, undefined)).resolves.toMatchObject({ + current: { fastMode: true } + }) + expect(Object.fromEntries(migrated.options)).toEqual({ fastMode: 'true' }) + + const canonical = optionSession(request) + canonical.options.set('fastMode', 'false') + canonical.options.set('serviceTier', 'priority-migrated') + await readLiveCodexSessionOptions(canonical, undefined) + expect(Object.fromEntries(canonical.options)).toEqual({ fastMode: 'false' }) + }) + + it('reconciles Fast off when switching to an unsupported model', async () => { + const session = optionSession( + vi.fn(async () => ({ + data: [ + { + model: 'gpt-live', + supportedReasoningEfforts: [], + serviceTiers: [{ id: 'priority-x', name: 'Fast', description: 'Fast' }] + }, + { model: 'gpt-standard', supportedReasoningEfforts: [], serviceTiers: [] } + ], + nextCursor: null + })) + ) + session.options.set('fastMode', 'true') + + await expect( + applyCodexStructuredSessionOption(session, 'model', 'gpt-standard', undefined) + ).resolves.toMatchObject({ model: 'gpt-standard', fastMode: 'false' }) + }) +}) + +describe('Codex service tier is not a settable option', () => { + /** The turn derives the tier from `fastMode`, so accepting a direct write would + * report success for a value the next turn discards. Restore still reads the key + * so a session persisted before Fast existed migrates. */ + it('refuses a direct serviceTier write while still restoring a legacy one', async () => { + const session = optionSession(async () => ({ data: [] })) + + await expect( + applyCodexStructuredSessionOption(session, 'serviceTier', 'priority', undefined) + ).rejects.toThrow('cannot be set directly') + expect(session.options.has('serviceTier')).toBe(false) + + expect(Object.fromEntries(restoredCodexSessionOptions({ serviceTier: 'default' }))).toEqual({ + fastMode: 'false' + }) + }) }) diff --git a/src/main/codex/codex-structured-session-options.ts b/src/main/codex/codex-structured-session-options.ts index e7ff155625c..d4940771069 100644 --- a/src/main/codex/codex-structured-session-options.ts +++ b/src/main/codex/codex-structured-session-options.ts @@ -1,132 +1,43 @@ -import type { - AgentSessionModelOption, - AgentSessionOptionChoice, - AgentSessionOptionsResult -} from '../../shared/agent-session-wire' +import type { AgentSessionOptionsResult } from '../../shared/agent-session-wire' import type { CodexAppServerConnection } from './codex-app-server-connection' -import type { CodexOpenedThread } from './codex-structured-thread-open' import type { CodexSession } from './codex-structured-session-state' import { isCodexTurnOptionKey } from './codex-structured-turn-start' import { AgentSessionOptionRejectedError } from '../native-chat/agent-session-wire/structured-agent-session-option-error' - -const MODEL_PAGE_LIMIT = 100 -const MAX_MODEL_PAGES = 20 +import { decodeStructuredAgentSessionOptionValue } from '../../shared/structured-agent-session-option-codec' +import { decodeCodexFastMode, reconcileCodexFastModeOption } from './codex-structured-fast-mode' +import { readCodexStructuredSessionOptionCatalog } from './codex-structured-model-catalog' export function restoredCodexSessionOptions( options: Readonly> | undefined ): Map { - return new Map(Object.entries(options ?? {}).filter(([key]) => isCodexTurnOptionKey(key))) + const restored = new Map( + Object.entries(options ?? {}).filter(([key, value]) => { + return ( + isCodexTurnOptionKey(key) && + (key !== 'fastMode' || + typeof decodeStructuredAgentSessionOptionValue('fastMode', value) === 'boolean') + ) + }) + ) + if (!restored.has('fastMode') && restored.get('serviceTier') === 'default') { + restored.delete('serviceTier') + restored.set('fastMode', 'false') + } + return restored } -function record(value: unknown): Record | null { - return typeof value === 'object' && value !== null ? (value as Record) : null -} +export type { CodexSessionOptionCatalog } from './codex-structured-model-catalog' -function text(value: unknown): string | null { - return typeof value === 'string' && value.trim() ? value : null -} - -function effortLabel(value: string): string { - return value === 'xhigh' - ? 'Extra high' - : value === 'minimal' - ? 'Minimal' - : `${value.charAt(0).toUpperCase()}${value.slice(1)}` -} - -function effortChoice(value: unknown): AgentSessionOptionChoice | null { - const row = record(value) - const effort = text(row?.reasoningEffort) - if (!effort) { - return null - } - const description = text(row?.description) - return { - value: effort, - label: effortLabel(effort), - ...(description ? { description } : {}) - } -} - -function modelOption(value: unknown): AgentSessionModelOption | null { - const row = record(value) - if (!row) { - return null - } - const id = text(row.model) ?? text(row.id) - const label = text(row.displayName) ?? id - if (!id || !label || row.hidden === true) { - return null - } - const description = text(row.description) - const defaultEffort = text(row.defaultReasoningEffort) - const efforts = Array.isArray(row.supportedReasoningEfforts) - ? row.supportedReasoningEfforts - .map(effortChoice) - .filter((choice): choice is AgentSessionOptionChoice => choice !== null) - : [] - return { - id, - label, - ...(description ? { description } : {}), - isDefault: row.isDefault === true, - ...(defaultEffort ? { defaultEffort } : {}), - efforts - } -} +export { readCodexStructuredSessionOptionCatalog } from './codex-structured-model-catalog' export async function readCodexStructuredSessionOptions(input: { connection: Pick - current: { model?: string; effort?: string } + current: { model?: string; effort?: string; fastMode?: boolean } + reportedServiceTier?: string | null + reportedServiceTierKnown?: boolean timeoutMs?: number }): Promise { - const models: AgentSessionModelOption[] = [] - let cursor: string | null = null - for (let page = 0; page < MAX_MODEL_PAGES; page += 1) { - const response = record( - await input.connection.request( - 'model/list', - { limit: MODEL_PAGE_LIMIT, includeHidden: false, ...(cursor ? { cursor } : {}) }, - { timeoutMs: input.timeoutMs } - ) - ) - const rows = Array.isArray(response?.data) ? response.data : [] - for (const row of rows) { - const parsed = modelOption(row) - if (parsed && !models.some((model) => model.id === parsed.id)) { - models.push(parsed) - } - } - cursor = text(response?.nextCursor) - if (!cursor) { - break - } - } - if (input.current.model && !models.some((model) => model.id === input.current.model)) { - models.push({ - id: input.current.model, - label: input.current.model, - isDefault: false, - efforts: [] - }) - } - const model = input.current.model ?? models.find((entry) => entry.isDefault)?.id ?? models[0]?.id - if (!model) { - throw new Error('codex app-server returned no available models') - } - return { - models, - current: { model, ...(input.current.effort ? { effort: input.current.effort } : {}) } - } -} - -export function reportedCodexThreadOptions( - opened: CodexOpenedThread -): CodexSession['reportedOptions'] { - return { - ...(opened.model ? { model: opened.model } : {}), - ...(opened.effort ? { effort: opened.effort } : {}) - } + return (await readCodexStructuredSessionOptionCatalog(input)).result } export function readLiveCodexSessionOptions( @@ -135,10 +46,35 @@ export function readLiveCodexSessionOptions( ): Promise { const model = session.options.get('model') ?? session.reportedOptions.model const effort = session.options.get('effort') ?? session.reportedOptions.effort - return readCodexStructuredSessionOptions({ + return readCodexStructuredSessionOptionCatalog({ connection: session.connection, - current: { ...(model ? { model } : {}), ...(effort ? { effort } : {}) }, + current: { + ...(model ? { model } : {}), + ...(effort ? { effort } : {}), + ...(decodeCodexFastMode(session.options) !== undefined + ? { fastMode: decodeCodexFastMode(session.options) } + : {}) + }, + ...(session.reportedOptions.serviceTierKnown + ? { + reportedServiceTier: session.reportedOptions.serviceTier ?? null, + reportedServiceTierKnown: true + } + : {}), timeoutMs + }).then((catalog) => { + reconcileCodexFastModeOption(session, { + fastModeTierByModel: catalog.fastModeTierByModel, + currentFastMode: catalog.result.current.fastMode, + model: catalog.result.current.model, + modelFastModeSupport: catalog.result.models.find( + (entry) => entry.id === catalog.result.current.model + )?.supportsFastMode + }) + const fastMode = decodeCodexFastMode(session.options) + return fastMode === undefined + ? catalog.result + : { ...catalog.result, current: { ...catalog.result.current, fastMode } } }) } @@ -161,13 +97,19 @@ async function applyValidatedCodexStructuredSessionOption( value: string, timeoutMs: number | undefined ): Promise>> { - if (key !== 'model' && key !== 'effort') { + // `serviceTier` still restores, so a session persisted before Fast existed migrates, + // but the turn now derives the tier from `fastMode`. Accepting a direct write would + // report success for a value the next turn discards. + if (key === 'serviceTier') { + throw new Error('codex service tier is derived from Fast mode and cannot be set directly') + } + if (key !== 'model' && key !== 'effort' && key !== 'fastMode') { session.options.set(key, value) return Object.fromEntries(session.options) } const priorModel = session.options.get('model') ?? session.reportedOptions.model const priorEffort = session.options.get('effort') ?? session.reportedOptions.effort - const catalog = await readCodexStructuredSessionOptions({ + const catalog = await readCodexStructuredSessionOptionCatalog({ connection: session.connection, current: { ...(priorModel ? { model: priorModel } : {}), @@ -175,11 +117,33 @@ async function applyValidatedCodexStructuredSessionOption( }, timeoutMs }) - if (key === 'model' && !catalog.models.some((entry) => entry.id === value)) { + reconcileCodexFastModeOption(session, { + fastModeTierByModel: catalog.fastModeTierByModel, + currentFastMode: catalog.result.current.fastMode, + model: priorModel ?? catalog.result.current.model, + modelFastModeSupport: catalog.result.models.find( + (entry) => entry.id === (priorModel ?? catalog.result.current.model) + )?.supportsFastMode + }) + if (key === 'model' && !catalog.result.models.some((entry) => entry.id === value)) { throw new Error(`codex app-server does not offer model ${value}`) } - const modelId = key === 'model' ? value : catalog.current.model - const model = catalog.models.find((entry) => entry.id === modelId) + const modelId = key === 'model' ? value : catalog.result.current.model + const model = catalog.result.models.find((entry) => entry.id === modelId) + if (key === 'fastMode') { + const requested = decodeStructuredAgentSessionOptionValue('fastMode', value) + if (typeof requested !== 'boolean') { + throw new Error('codex fast mode must be encoded as true or false') + } + if ( + requested && + (model?.supportsFastMode !== true || !catalog.fastModeTierByModel.has(modelId)) + ) { + throw new Error(`codex app-server model ${modelId} does not support Fast mode`) + } + session.options.set('fastMode', value) + return Object.fromEntries(session.options) + } const requestedEffort = key === 'effort' ? value : priorEffort if ( key === 'effort' && @@ -199,5 +163,12 @@ async function applyValidatedCodexStructuredSessionOption( } else { session.options.delete('effort') } + if ( + key === 'model' && + session.options.get('fastMode') === 'true' && + model?.supportsFastMode === false + ) { + session.options.set('fastMode', 'false') + } return Object.fromEntries(session.options) } diff --git a/src/main/codex/codex-structured-session-state.ts b/src/main/codex/codex-structured-session-state.ts index b341862d218..625e222ecfb 100644 --- a/src/main/codex/codex-structured-session-state.ts +++ b/src/main/codex/codex-structured-session-state.ts @@ -86,7 +86,14 @@ export type CodexSession = { dispatchPending?: boolean prompts: CodexAcquisitionWindow['prompts'] options: Map - reportedOptions: { model?: string; effort?: string } + reportedOptions: { + model?: string + effort?: string + serviceTier?: string | null + serviceTierKnown?: true + } + /** Exact provider-advertised Fast request value for each discovered model. */ + fastModeTierByModel: Map turnIdWaiters: ((turnId: string) => void)[] translator: CodexJournalTranslator | null /** Ephemeral roster behind the background-tasks strip; never durable state. */ diff --git a/src/main/codex/codex-structured-thread-open.test.ts b/src/main/codex/codex-structured-thread-open.test.ts index 39c66468ca5..42e1f9deb18 100644 --- a/src/main/codex/codex-structured-thread-open.test.ts +++ b/src/main/codex/codex-structured-thread-open.test.ts @@ -13,6 +13,26 @@ function connectionFor( } describe('openCodexThread', () => { + it('preserves an explicitly reported service tier, including Standard', async () => { + const priority = vi.fn(async () => ({ + thread: { id: 'thread-fast' }, + serviceTier: 'priority-live' + })) + await expect( + openCodexThread(connectionFor(priority), { cwd: '/workspace', resumeThreadId: null }, 2_000) + ).resolves.toMatchObject({ threadId: 'thread-fast', serviceTier: 'priority-live' }) + + const standard = vi.fn(async () => ({ thread: { id: 'thread-standard' }, serviceTier: null })) + await expect( + openCodexThread(connectionFor(standard), { cwd: '/workspace', resumeThreadId: null }, 2_000) + ).resolves.toEqual({ + threadId: 'thread-standard', + thread: { id: 'thread-standard' }, + historyPath: null, + serviceTier: null + }) + }) + it('requests metadata-only state when resuming an existing thread', async () => { const request = vi.fn(async () => ({ thread: { id: 'thread-1', path: '/history/thread-1.jsonl' }, diff --git a/src/main/codex/codex-structured-thread-open.ts b/src/main/codex/codex-structured-thread-open.ts index ac4c16d8a6a..1ab91e9898e 100644 --- a/src/main/codex/codex-structured-thread-open.ts +++ b/src/main/codex/codex-structured-thread-open.ts @@ -19,6 +19,8 @@ export type CodexOpenedThread = { historyMode?: 'legacy' | 'paginated' model?: string effort?: string + /** Present, including null, only when this app-server reports the effective tier. */ + serviceTier?: string | null } function nonEmptyString(value: unknown): string | null { @@ -89,6 +91,8 @@ export async function openCodexThread( : {} const model = nonEmptyString(result.model) const effort = nonEmptyString(result.reasoningEffort) + const serviceTierKnown = Object.hasOwn(result, 'serviceTier') + const serviceTier = nonEmptyString(result.serviceTier) return { threadId, thread, @@ -97,6 +101,7 @@ export async function openCodexThread( ? { historyMode: thread.historyMode } : {}), ...(model ? { model } : {}), - ...(effort ? { effort } : {}) + ...(effort ? { effort } : {}), + ...(serviceTierKnown ? { serviceTier } : {}) } } diff --git a/src/main/codex/codex-structured-turn-start.ts b/src/main/codex/codex-structured-turn-start.ts index a24c5b6d5b8..e6a53925fc6 100644 --- a/src/main/codex/codex-structured-turn-start.ts +++ b/src/main/codex/codex-structured-turn-start.ts @@ -8,6 +8,7 @@ import { import { isCodexAppServerUnsupportedError } from './codex-app-server-session' import { readCodexTurnId } from './codex-structured-thread-facts' import { DISPATCH_DOUBT_CODEX_TURN_UNNAMED } from '../native-chat/agent-session-journal/journal-dispatch-doubt-reasons' +import { decodeStructuredAgentSessionOptionValue } from '../../shared/structured-agent-session-option-codec' // Starting a Codex turn and learning its id, which are not the same event: // `turn/start` returns the id on newer builds and acks before it exists on @@ -29,7 +30,8 @@ const CODEX_TURN_OPTION_KEYS = new Set([ 'approvalPolicy', 'approvalsReviewer', 'personality', - 'serviceTier' + 'serviceTier', + 'fastMode' ]) export function isCodexTurnOptionKey(key: string): boolean { @@ -43,6 +45,8 @@ export type CodexTurnHost = { connection: Pick threadId: string options: Map + reportedOptions?: { model?: string } + fastModeTierByModel: ReadonlyMap turnIdWaiters: ((turnId: string) => void)[] } @@ -60,6 +64,33 @@ function turnInputFor(body: AgentJournalMessageItem): Record[] return input } +function codexTurnOptions(host: CodexTurnHost): Record { + const options = Object.fromEntries( + [...host.options].filter(([key]) => key !== 'fastMode' && key !== 'serviceTier') + ) + const encodedFastMode = host.options.get('fastMode') + if (encodedFastMode === undefined) { + return options + } + const fastMode = decodeStructuredAgentSessionOptionValue('fastMode', encodedFastMode) + if (typeof fastMode !== 'boolean') { + throw new Error('codex fast mode must be encoded as true or false') + } + if (!fastMode) { + return { ...options, serviceTier: 'default' } + } + const model = host.options.get('model') ?? host.reportedOptions?.model + const tierId = model ? host.fastModeTierByModel.get(model) : undefined + // Fast is on but nothing has named the tier for this model yet, so there is no + // value to route to. Deliberately Standard rather than an omission: the tier + // persists on the thread, so omitting would silently keep routing a paid tier we + // cannot currently name, and discovery recovers the exact tier on a later turn. + if (!tierId) { + return { ...options, serviceTier: 'default' } + } + return { ...options, serviceTier: tierId } +} + /** * Resolves the turn id, or null when Codex owns a turn it never named. Throws * only for outcomes the wire must not read as acceptance. @@ -83,7 +114,7 @@ export async function startCodexTurn( threadId: host.threadId, clientUserMessageId: input.clientMessageId, input: turnInputFor(input.body), - ...Object.fromEntries(host.options) + ...codexTurnOptions(host) }, { timeoutMs: input.timeoutMs } ) diff --git a/src/main/cursor/hook-script.ts b/src/main/cursor/hook-script.ts index 94563337131..739026aa6a8 100644 --- a/src/main/cursor/hook-script.ts +++ b/src/main/cursor/hook-script.ts @@ -9,6 +9,10 @@ import { buildWindowsHookEnvironmentGuardLines, buildWindowsHookStdinDrainEpilogue } from '../agent-hooks/hook-stdin-contract' +import { + buildPosixGrokReplayGuardLines, + buildWindowsGrokReplayGuardLines +} from '../agent-hooks/grok-replay-guard' import { getCursorHookResponse, type CursorEvent } from './hook-events' const CURSOR_HOOK_RESPONSE_ENV = 'ORCA_CURSOR_HOOK_RESPONSE' @@ -43,6 +47,7 @@ export function getManagedScript(target: 'local' | 'posix' = 'local'): string { // Why: source current endpoint coordinates for PTYs surviving an Orca restart. 'if defined ORCA_AGENT_HOOK_ENDPOINT if exist "%ORCA_AGENT_HOOK_ENDPOINT%" call "%ORCA_AGENT_HOOK_ENDPOINT%" 2>nul', ...buildWindowsHookEnvironmentGuardLines(), + ...buildWindowsGrokReplayGuardLines(), buildWindowsAgentHookPostCommand('cursor'), 'exit /b 0', ...buildWindowsHookStdinDrainEpilogue(), @@ -59,6 +64,7 @@ export function getManagedScript(target: 'local' | 'posix' = 'local'): string { ' printf "{}\\n"', 'fi', ...buildPosixHookPayloadCapture(), + ...buildPosixGrokReplayGuardLines(), ...buildPosixHookSpoolLines('cursor'), // Why: refresh endpoint coordinates so surviving PTYs keep reporting. 'if [ -n "$ORCA_AGENT_HOOK_ENDPOINT" ] && [ -r "$ORCA_AGENT_HOOK_ENDPOINT" ]; then', diff --git a/src/main/cursor/hook-service.test.ts b/src/main/cursor/hook-service.test.ts index f5f25295a60..3f93e91f7fe 100644 --- a/src/main/cursor/hook-service.test.ts +++ b/src/main/cursor/hook-service.test.ts @@ -131,6 +131,7 @@ describe('CursorHookService', () => { 'utf8' ) expect(script).toContain('/hook/cursor') + expect(script).toContain('GROK_HOOK_EVENT') if (process.platform === 'win32') { expect(script).toContain('%SystemRoot%\\System32\\curl.exe') } else { diff --git a/src/main/git/remote-name-listing.test.ts b/src/main/git/remote-name-listing.test.ts new file mode 100644 index 00000000000..ebf78e31367 --- /dev/null +++ b/src/main/git/remote-name-listing.test.ts @@ -0,0 +1,200 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' + +const { + gitExecFileAsyncMock, + getSshGitProviderMock, + getSshGitProviderGenerationMock, + readLocalGitConfigSignatureMock +} = vi.hoisted(() => ({ + gitExecFileAsyncMock: vi.fn(), + getSshGitProviderMock: vi.fn(), + getSshGitProviderGenerationMock: vi.fn(() => 0), + readLocalGitConfigSignatureMock: vi.fn<() => Promise>(async () => 'sig-1') +})) + +vi.mock('./runner', () => ({ gitExecFileAsync: gitExecFileAsyncMock })) +vi.mock('../providers/ssh-git-dispatch', () => ({ + getSshGitProvider: getSshGitProviderMock, + getSshGitProviderGeneration: getSshGitProviderGenerationMock +})) +vi.mock('../github/local-git-config-signature', () => ({ + readLocalGitConfigSignature: readLocalGitConfigSignatureMock +})) + +import { REMOTE_URL_PROBE_TIMEOUT_MS } from './remote-url-probe' +import { + _resetRemoteNameListingCache, + listCachedRemoteNames, + shouldProbeGitRemote +} from './remote-name-listing' + +function remoteListCalls(): unknown[][] { + return gitExecFileAsyncMock.mock.calls.filter( + ([args]) => Array.isArray(args) && args[0] === 'remote' && args[1] !== 'get-url' + ) +} + +describe('cached git remote name listing', () => { + beforeEach(() => { + _resetRemoteNameListingCache() + gitExecFileAsyncMock.mockReset() + getSshGitProviderMock.mockReset() + getSshGitProviderGenerationMock.mockReset() + getSshGitProviderGenerationMock.mockReturnValue(0) + readLocalGitConfigSignatureMock.mockReset() + readLocalGitConfigSignatureMock.mockImplementation(async () => 'sig-1') + }) + + it('skips probing upstream when listing only has origin', async () => { + gitExecFileAsyncMock.mockResolvedValue({ stdout: 'origin\n' }) + + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + await expect(listCachedRemoteNames('/repo')).resolves.toEqual(['origin']) + expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(1) + expect(gitExecFileAsyncMock).toHaveBeenCalledWith(['remote'], { + cwd: '/repo', + timeout: REMOTE_URL_PROBE_TIMEOUT_MS + }) + }) + + it('still probes upstream when listing includes that remote', async () => { + gitExecFileAsyncMock.mockResolvedValue({ stdout: 'origin\nupstream\n' }) + + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(true) + expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(1) + }) + + it('reuses a signed listing instead of spawning git remote again', async () => { + gitExecFileAsyncMock.mockResolvedValue({ stdout: 'origin\n' }) + + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + await expect(shouldProbeGitRemote('/repo', 'origin')).resolves.toBe(true) + + expect(remoteListCalls()).toHaveLength(1) + }) + + it('re-lists as soon as the git config signature changes', async () => { + gitExecFileAsyncMock + .mockResolvedValueOnce({ stdout: 'origin\n' }) + .mockResolvedValueOnce({ stdout: 'origin\nupstream\n' }) + + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + readLocalGitConfigSignatureMock.mockImplementation(async () => 'sig-2') + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(true) + expect(remoteListCalls()).toHaveLength(2) + }) + + it('uses the short TTL when config changes during remote listing', async () => { + vi.useFakeTimers() + try { + readLocalGitConfigSignatureMock + .mockResolvedValueOnce('sig-1') + .mockResolvedValueOnce('sig-2') + .mockResolvedValue('sig-2') + gitExecFileAsyncMock + .mockResolvedValueOnce({ stdout: 'origin\n' }) + .mockResolvedValueOnce({ stdout: 'origin\nupstream\n' }) + + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + await vi.advanceTimersByTimeAsync(30_001) + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(true) + expect(remoteListCalls()).toHaveLength(2) + } finally { + vi.useRealTimers() + } + }) + + it('expires an unsigned listing after the short TTL', async () => { + vi.useFakeTimers() + try { + readLocalGitConfigSignatureMock.mockImplementation(async () => undefined) + gitExecFileAsyncMock + .mockResolvedValueOnce({ stdout: 'origin\n' }) + .mockResolvedValueOnce({ stdout: 'origin\nupstream\n' }) + + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + await vi.advanceTimersByTimeAsync(30_001) + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(true) + expect(remoteListCalls()).toHaveLength(2) + } finally { + vi.useRealTimers() + } + }) + + it('holds a signed listing past the unsigned TTL', async () => { + vi.useFakeTimers() + try { + gitExecFileAsyncMock.mockResolvedValue({ stdout: 'origin\n' }) + + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + await vi.advanceTimersByTimeAsync(4 * 60_000) + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + expect(remoteListCalls()).toHaveLength(1) + } finally { + vi.useRealTimers() + } + }) + + it('fails open and does not cache when listing throws', async () => { + gitExecFileAsyncMock + .mockRejectedValueOnce(new Error('git timed out.')) + .mockResolvedValueOnce({ stdout: 'origin\n' }) + + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(true) + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + expect(remoteListCalls()).toHaveLength(2) + }) + + it('coalesces concurrent listings onto one spawn', async () => { + gitExecFileAsyncMock.mockImplementation(async () => { + await Promise.resolve() + return { stdout: 'origin\n' } + }) + + await expect( + Promise.all([ + shouldProbeGitRemote('/repo', 'upstream'), + shouldProbeGitRemote('/repo', 'upstream'), + listCachedRemoteNames('/repo') + ]) + ).resolves.toEqual([false, false, ['origin']]) + expect(remoteListCalls()).toHaveLength(1) + }) + + it('keeps host and WSL listings separate', async () => { + gitExecFileAsyncMock.mockImplementation( + async (_args: string[], options: { wslDistro?: string } = {}) => ({ + stdout: options.wslDistro ? 'origin\nupstream\n' : 'origin\n' + }) + ) + + await expect(shouldProbeGitRemote('/repo', 'upstream')).resolves.toBe(false) + await expect( + shouldProbeGitRemote('/repo', 'upstream', null, { wslDistro: 'Ubuntu' }) + ).resolves.toBe(true) + expect(gitExecFileAsyncMock).toHaveBeenNthCalledWith(2, ['remote'], { + cwd: '/repo', + timeout: REMOTE_URL_PROBE_TIMEOUT_MS, + wslDistro: 'Ubuntu' + }) + }) + + it('lists remotes through the SSH git provider', async () => { + const exec = vi.fn(async () => ({ stdout: 'origin\n', stderr: '' })) + getSshGitProviderMock.mockReturnValue({ exec }) + + await expect(shouldProbeGitRemote('/remote/repo', 'upstream', 'ssh-1')).resolves.toBe(false) + expect(gitExecFileAsyncMock).not.toHaveBeenCalled() + expect(exec).toHaveBeenCalledWith(['remote'], '/remote/repo', { + signal: expect.any(AbortSignal) + }) + }) + + it('fails open when the SSH git provider is missing instead of listing locally', async () => { + getSshGitProviderMock.mockReturnValue(undefined) + + await expect(shouldProbeGitRemote('/remote/repo', 'upstream', 'ssh-1')).resolves.toBe(true) + expect(gitExecFileAsyncMock).not.toHaveBeenCalled() + }) +}) diff --git a/src/main/git/remote-name-listing.ts b/src/main/git/remote-name-listing.ts new file mode 100644 index 00000000000..17aa9c9444a --- /dev/null +++ b/src/main/git/remote-name-listing.ts @@ -0,0 +1,174 @@ +import { readLocalGitConfigSignature } from '../github/local-git-config-signature' +import { getSshGitProvider, getSshGitProviderGeneration } from '../providers/ssh-git-dispatch' +import { runCoalescedProbe, type CoalescedProbes } from './coalesced-probe' +import type { GitAdmissionTier } from './command-runner/git-exec-options' +import { REMOTE_URL_PROBE_TIMEOUT_MS } from './remote-url-probe' +import { gitExecFileAsync } from './runner' + +export type RemoteNameListingGitOptions = { + wslDistro?: string + admissionTier?: GitAdmissionTier +} + +const SIGNED_REMOTE_NAME_LISTING_TTL_MS = 5 * 60_000 +const UNSIGNED_REMOTE_NAME_LISTING_TTL_MS = 30_000 +const REMOTE_NAME_LISTING_CACHE_MAX_ENTRIES = 512 + +type CachedRemoteNames = { + remotes: string[] + expiresAt: number + configSignature?: string +} + +const remoteNameListingCache = new Map() +const remoteNameListingInFlight: CoalescedProbes = new Map() + +/** @internal - exposed for tests only */ +export function _resetRemoteNameListingCache(): void { + remoteNameListingCache.clear() + remoteNameListingInFlight.clear() +} + +function parseRemoteNames(stdout: string): string[] { + return stdout + .split(/\r?\n/) + .map((line) => line.trim()) + .filter(Boolean) +} + +function remoteNameListingCacheKey( + repoPath: string, + connectionId?: string | null, + localGitOptions: RemoteNameListingGitOptions = {} +): string { + const runtimeKey = connectionId + ? `ssh:${connectionId}:${getSshGitProviderGeneration(connectionId)}` + : `local:${localGitOptions.wslDistro ?? 'host'}` + return `${runtimeKey}\0${repoPath}` +} + +function pruneRemoteNameListingCache(now: number): void { + for (const [key, entry] of remoteNameListingCache) { + if (entry.expiresAt <= now) { + remoteNameListingCache.delete(key) + } + } + while (remoteNameListingCache.size > REMOTE_NAME_LISTING_CACHE_MAX_ENTRIES) { + const oldestKey = remoteNameListingCache.keys().next().value + if (oldestKey === undefined) { + return + } + remoteNameListingCache.delete(oldestKey) + } +} + +function listingGitConfigContext( + repoPath: string, + connectionId?: string | null, + localGitOptions: RemoteNameListingGitOptions = {} +): { repoPath: string; connectionId: string | null; wslDistro?: string } { + return { + repoPath, + connectionId: connectionId ?? null, + ...(localGitOptions.wslDistro ? { wslDistro: localGitOptions.wslDistro } : {}) + } +} + +/** + * `git remote` names for one repo/runtime. Failed listings are not cached: a + * missed `upstream` would otherwise send issue/PR resolvers to origin on a + * contributor clone (#7331). + */ +export async function listCachedRemoteNames( + repoPath: string, + connectionId?: string | null, + localGitOptions: RemoteNameListingGitOptions = {} +): Promise { + const cacheKey = remoteNameListingCacheKey(repoPath, connectionId, localGitOptions) + const now = Date.now() + pruneRemoteNameListingCache(now) + const cached = remoteNameListingCache.get(cacheKey) + if (cached && cached.expiresAt > now) { + if (cached.configSignature !== undefined) { + const currentSignature = await readLocalGitConfigSignature( + listingGitConfigContext(repoPath, connectionId, localGitOptions) + ) + if (currentSignature === cached.configSignature) { + return cached.remotes + } + remoteNameListingCache.delete(cacheKey) + } else { + return cached.remotes + } + } + + return runCoalescedProbe(remoteNameListingInFlight, cacheKey, async (ownsKey) => { + const configContext = listingGitConfigContext(repoPath, connectionId, localGitOptions) + const configSignatureBefore = await readLocalGitConfigSignature(configContext) + const remotes = await listUncachedRemoteNames(repoPath, connectionId, localGitOptions) + if (remotes === null) { + return null + } + if (ownsKey()) { + const configSignatureAfter = await readLocalGitConfigSignature(configContext) + const configSignature = + configSignatureBefore !== undefined && configSignatureBefore === configSignatureAfter + ? configSignatureAfter + : undefined + remoteNameListingCache.set(cacheKey, { + remotes, + expiresAt: + Date.now() + + (configSignature + ? SIGNED_REMOTE_NAME_LISTING_TTL_MS + : UNSIGNED_REMOTE_NAME_LISTING_TTL_MS), + ...(configSignature ? { configSignature } : {}) + }) + pruneRemoteNameListingCache(Date.now()) + } + return remotes + }) +} + +async function listUncachedRemoteNames( + repoPath: string, + connectionId?: string | null, + localGitOptions: RemoteNameListingGitOptions = {} +): Promise { + if (connectionId) { + const provider = getSshGitProvider(connectionId) + if (!provider) { + return null + } + try { + const { stdout } = await provider.exec(['remote'], repoPath, { + signal: AbortSignal.timeout(REMOTE_URL_PROBE_TIMEOUT_MS) + }) + return parseRemoteNames(stdout) + } catch { + return null + } + } + try { + const { stdout } = await gitExecFileAsync(['remote'], { + cwd: repoPath, + timeout: REMOTE_URL_PROBE_TIMEOUT_MS, + ...(localGitOptions.wslDistro ? { wslDistro: localGitOptions.wslDistro } : {}), + ...(localGitOptions.admissionTier ? { admissionTier: localGitOptions.admissionTier } : {}) + }) + return parseRemoteNames(stdout) + } catch { + return null + } +} + +/** Probe a named remote only when listing says it exists, or listing failed. */ +export async function shouldProbeGitRemote( + repoPath: string, + remoteName: string, + connectionId?: string | null, + localGitOptions: RemoteNameListingGitOptions = {} +): Promise { + const remotes = await listCachedRemoteNames(repoPath, connectionId, localGitOptions) + return remotes === null || remotes.includes(remoteName) +} diff --git a/src/main/github/__fixtures__/work-item-search-api.ts b/src/main/github/__fixtures__/work-item-search-api.ts new file mode 100644 index 00000000000..e48a5818cb9 --- /dev/null +++ b/src/main/github/__fixtures__/work-item-search-api.ts @@ -0,0 +1,214 @@ +import { z } from 'zod' +type Captured = { args: string[]; cwd?: string; fixtureCredential?: string } +type Issue = Record +export class WorkItemSearchApi { + calls: Captured[] = [] + restSearches = 0 + graphqlCalls = 0 + graphqlFields = 0 + restDetails = 0 + rejected = 0 + graphqlAvailable = true + searchAvailable = true + rowsPerRepo = 120 + specialNodes: Issue[] | undefined + aliasErrorRepo: string | undefined + expectedSearch: string | undefined + reportedCount: number | undefined + private nextCursor = 0 + private cursors = new Map() + private cache = new Map() + + private rows(query: string): Issue[] { + if (this.expectedSearch && query.replace(/ sort:created-desc$/, '') !== this.expectedSearch) { + throw new Error(`Unexpected fixture search ${query}`) + } + const repo = /repo:([^\s]+)/.exec(query)?.[1] ?? 'unknown/repo' + return ( + this.specialNodes ?? + Array.from({ length: this.rowsPerRepo }, (_, index) => ({ + __typename: 'Issue', + number: 10000 - index, + title: `${repo} issue ${index}`, + state: 'OPEN', + url: `https://github.com/${repo}/issues/${10000 - index}`, + updatedAt: '2026-09-11T00:00:00Z', + author: { + __typename: 'User', + login: 'author', + avatarUrl: 'https://avatars.githubusercontent.com/u/42?u=profile&v=4' + }, + labels: { nodes: [{ name: 'bug' }], pageInfo: { hasNextPage: false } }, + assignees: { nodes: [], pageInfo: { hasNextPage: false } } + })) + ) + } + + async capture( + _binary: string, + args: string[], + options: { cwd?: string; env?: NodeJS.ProcessEnv } + ): Promise<{ stdout: string; stderr: string }> { + const credential = options.env?.GH_TOKEN + this.calls.push({ + args: [...args], + cwd: options.cwd, + fixtureCredential: credential?.startsWith('fixture-') ? credential : undefined + }) + if (args.includes('rate_limit')) { + const bucket = { limit: 5000, remaining: 4500, reset: 3600 } + return { + stdout: JSON.stringify({ + resources: { + core: bucket, + graphql: { ...bucket, remaining: this.graphqlAvailable ? 4500 : 0 }, + search: { + limit: 30, + remaining: this.searchAvailable ? Math.max(0, 30 - this.restSearches) : 0, + reset: 60 + } + } + }), + stderr: '' + } + } + if (args[0] === 'pr') { + return { stdout: '[]', stderr: '' } + } + const endpoint = args.find((arg) => arg.startsWith('search/issues?')) + if (endpoint) { + const cached = args.includes('--cache') + ? this.cache.get(JSON.stringify([options.cwd, args])) + : undefined + if (cached !== undefined) { + return { stdout: cached, stderr: '' } + } + this.restSearches++ + if (!this.searchAvailable || this.restSearches > 30) { + this.rejected++ + throw Object.assign(new Error('HTTP 403: API rate limit exceeded'), { + stderr: 'HTTP 403: API rate limit exceeded' + }) + } + const url = new URL(endpoint, 'https://api.github.com') + const query = url.searchParams.get('q') ?? '' + const rows = this.rows(query) + const limit = Number(url.searchParams.get('per_page') ?? 1) + const page = Number(url.searchParams.get('page') ?? 1) + if (page * limit > 1000) { + throw Object.assign( + new Error('Only the first 1000 search results are available (HTTP 422)'), + { stderr: 'Only the first 1000 search results are available (HTTP 422)' } + ) + } + const stdout = args.includes('.total_count') + ? String(this.reportedCount ?? rows.length) + : JSON.stringify(rows.slice((page - 1) * limit, page * limit).map(this.restIssue)) + if (args.includes('--cache')) { + this.cache.set(JSON.stringify([options.cwd, args]), stdout) + } + return { stdout, stderr: '' } + } + const detail = args.find((arg) => /^repos\/.+\/issues\/\d+$/.test(arg)) + if (detail) { + this.restDetails++ + const row = this.rows('repo:fixture/repo').find( + (row) => row.number === Number(detail.split('/').at(-1)) + ) + return { + stdout: JSON.stringify({ + ...this.restIssue(row!), + labels: Array.from({ length: 125 }, (_, index) => ({ name: `label-${index}` })) + }), + stderr: '' + } + } + if (!args.includes('graphql')) { + throw new Error(`Unexpected fixture request ${args.join(' ')}`) + } + this.graphqlCalls++ + if (!this.graphqlAvailable) { + throw Object.assign(new Error('HTTP 403: API rate limit exceeded'), { + stderr: 'HTTP 403: API rate limit exceeded' + }) + } + const query = args.find((arg) => arg.startsWith('query='))?.slice(6) ?? '' + const fields = [ + ...query.matchAll( + /(r\d+): search\(type: ISSUE, query: ("(?:[^"\\]|\\.)*"), first: (\d+)(?:, after: ("(?:[^"\\]|\\.)*"))?\)/g + ) + ] + if (!fields.length) { + throw new Error(`Unexpected GraphQL fixture query ${query}`) + } + const data: Record = { rateLimit: { cost: 1 } } + const errors: unknown[] = [] + for (let index = 0; index < fields.length; index++) { + const field = fields[index] + this.graphqlFields++ + const search = z.string().parse(JSON.parse(field[2])) + if (this.aliasErrorRepo && search.includes(`repo:${this.aliasErrorRepo} `)) { + data[field[1]] = null + errors.push({ message: 'fixture repository search unavailable', path: [field[1]] }) + continue + } + const first = Number(field[3]) + const cursor = field[4] ? z.string().parse(JSON.parse(field[4])) : undefined + const saved = cursor ? this.cursors.get(cursor) : undefined + if (cursor && (!saved || saved.query !== search)) { + throw new Error('Unknown or cross-query opaque cursor') + } + const offset = saved?.offset ?? 0 + const rows = this.rows(search) + const page = rows.slice(offset, offset + first) + const next = offset + page.length + const endCursor = `opaque:${++this.nextCursor}:cursor` + this.cursors.set(endCursor, { query: search, offset: next }) + const selection = query.slice(field.index, fields[index + 1]?.index ?? query.length) + data[field[1]] = { + issueCount: this.reportedCount ?? rows.length, + pageInfo: { hasNextPage: next < rows.length, endCursor }, + ...(selection.includes(' nodes {') ? { nodes: page } : {}) + } + } + const stdout = JSON.stringify({ data, ...(errors.length ? { errors } : {}) }) + if (errors.length) { + throw Object.assign(new Error('GraphQL partial failure'), { + stdout, + stderr: 'GraphQL partial failure' + }) + } + return { stdout, stderr: '' } + } + + private restIssue(row: Issue): Issue { + const actor = (value: unknown) => { + const user = z + .object({ + __typename: z.string().optional(), + login: z.string(), + avatarUrl: z.string().optional() + }) + .nullable() + .parse(value) + return user + ? { + login: user.login + (user.__typename === 'Bot' ? '[bot]' : ''), + avatar_url: user.avatarUrl?.replace(/\?u=[^&]+&/, '?') + } + : null + } + return { + ...row, + state: String(row.state).toLowerCase(), + html_url: row.url, + updated_at: row.updatedAt, + user: actor(row.author), + labels: z.object({ nodes: z.array(z.unknown()) }).parse(row.labels).nodes, + assignees: z + .object({ nodes: z.array(z.unknown()) }) + .parse(row.assignees) + .nodes.map(actor) + } + } +} diff --git a/src/main/github/__fixtures__/work-item-search-metadata.json b/src/main/github/__fixtures__/work-item-search-metadata.json new file mode 100644 index 00000000000..d8fa785f853 --- /dev/null +++ b/src/main/github/__fixtures__/work-item-search-metadata.json @@ -0,0 +1,248 @@ +[ + { + "graphql": { + "number": 19933, + "title": "[Bug]: Browser element annotations cleared and overlay removed when scrolling the page (no reload)", + "state": "OPEN", + "url": "https://github.com/stablyai/orca/issues/19933", + "updatedAt": "2026-09-12T01:57:20Z", + "labels": { + "nodes": [ + { + "name": "bug" + }, + { + "name": "os:linux" + } + ], + "pageInfo": { + "hasNextPage": false + } + }, + "author": { + "__typename": "User", + "login": "peeraponw", + "avatarUrl": "https://avatars.githubusercontent.com/u/13129669?u=bf337820b1f6d507dfac4e48db7cf61e6c2c8b95&v=4" + }, + "assignees": { + "nodes": [ + { + "login": "AmethystLiang", + "avatarUrl": "https://avatars.githubusercontent.com/u/6427696?u=86a210ddf931a6a557a4664cc17a97dc02c9de36&v=4" + } + ], + "pageInfo": { + "hasNextPage": false + } + }, + "__typename": "Issue" + }, + "rest": { + "number": 19933, + "title": "[Bug]: Browser element annotations cleared and overlay removed when scrolling the page (no reload)", + "state": "open", + "html_url": "https://github.com/stablyai/orca/issues/19933", + "updated_at": "2026-09-12T01:57:20Z", + "labels": [ + { + "name": "bug" + }, + { + "name": "os:linux" + } + ], + "user": { + "login": "peeraponw", + "avatar_url": "https://avatars.githubusercontent.com/u/13129669?v=4" + }, + "assignees": [ + { + "login": "AmethystLiang", + "avatar_url": "https://avatars.githubusercontent.com/u/6427696?v=4" + } + ] + } + }, + { + "graphql": { + "number": 19932, + "title": "[Bug] Incorrect status after /usage", + "state": "OPEN", + "url": "https://github.com/stablyai/orca/issues/19932", + "updatedAt": "2026-09-10T21:44:41Z", + "labels": { + "nodes": [ + { + "name": "bug" + } + ], + "pageInfo": { + "hasNextPage": false + } + }, + "author": { + "__typename": "Bot", + "login": "orca-discord-issues", + "avatarUrl": "https://avatars.githubusercontent.com/u/127256420?v=4" + }, + "assignees": { + "nodes": [], + "pageInfo": { + "hasNextPage": false + } + }, + "__typename": "Issue" + }, + "rest": { + "number": 19932, + "title": "[Bug] Incorrect status after /usage", + "state": "open", + "html_url": "https://github.com/stablyai/orca/issues/19932", + "updated_at": "2026-09-10T21:44:41Z", + "labels": [ + { + "name": "bug" + } + ], + "user": { + "login": "orca-discord-issues[bot]", + "avatar_url": "https://avatars.githubusercontent.com/u/127256420?v=4" + }, + "assignees": [] + } + }, + { + "graphql": { + "number": 19926, + "title": "[Bug]: Copying assistant response adds visual-wrap line breaks when pasted into Google Chat (macOS)", + "state": "OPEN", + "url": "https://github.com/stablyai/orca/issues/19926", + "updatedAt": "2026-09-11T17:14:42Z", + "labels": { + "nodes": [], + "pageInfo": { + "hasNextPage": false + } + }, + "author": { + "__typename": "User", + "login": "JanPlessow", + "avatarUrl": "https://avatars.githubusercontent.com/u/202702070?u=6cdc81f81e27630db038e80eea4924c9ded7ddc2&v=4" + }, + "assignees": { + "nodes": [], + "pageInfo": { + "hasNextPage": false + } + }, + "__typename": "Issue" + }, + "rest": { + "number": 19926, + "title": "[Bug]: Copying assistant response adds visual-wrap line breaks when pasted into Google Chat (macOS)", + "state": "open", + "html_url": "https://github.com/stablyai/orca/issues/19926", + "updated_at": "2026-09-11T17:14:42Z", + "labels": [], + "user": { + "login": "JanPlessow", + "avatar_url": "https://avatars.githubusercontent.com/u/202702070?v=4" + }, + "assignees": [] + } + }, + { + "graphql": { + "number": 19919, + "title": "[Bug]: v1.4.199 Windows NSIS installer reports success but never installs Orca.exe (partial install)", + "state": "OPEN", + "url": "https://github.com/stablyai/orca/issues/19919", + "updatedAt": "2026-09-10T20:08:25Z", + "labels": { + "nodes": [], + "pageInfo": { + "hasNextPage": false + } + }, + "author": { + "__typename": "User", + "login": "Subdij", + "avatarUrl": "https://avatars.githubusercontent.com/u/105368200?u=d379763ab273d375d0cfff0215daf325bd59f4d6&v=4" + }, + "assignees": { + "nodes": [], + "pageInfo": { + "hasNextPage": false + } + }, + "__typename": "Issue" + }, + "rest": { + "number": 19919, + "title": "[Bug]: v1.4.199 Windows NSIS installer reports success but never installs Orca.exe (partial install)", + "state": "open", + "html_url": "https://github.com/stablyai/orca/issues/19919", + "updated_at": "2026-09-10T20:08:25Z", + "labels": [], + "user": { + "login": "Subdij", + "avatar_url": "https://avatars.githubusercontent.com/u/105368200?v=4" + }, + "assignees": [] + } + }, + { + "graphql": { + "number": 19918, + "title": "[Bug]: Svelte files do not get parsed or highlighted correctly", + "state": "OPEN", + "url": "https://github.com/stablyai/orca/issues/19918", + "updatedAt": "2026-09-10T20:06:53Z", + "labels": { + "nodes": [ + { + "name": "bug" + }, + { + "name": "os:macos" + } + ], + "pageInfo": { + "hasNextPage": false + } + }, + "author": { + "__typename": "User", + "login": "futuraprime", + "avatarUrl": "https://avatars.githubusercontent.com/u/181752?v=4" + }, + "assignees": { + "nodes": [], + "pageInfo": { + "hasNextPage": false + } + }, + "__typename": "Issue" + }, + "rest": { + "number": 19918, + "title": "[Bug]: Svelte files do not get parsed or highlighted correctly", + "state": "open", + "html_url": "https://github.com/stablyai/orca/issues/19918", + "updated_at": "2026-09-10T20:06:53Z", + "labels": [ + { + "name": "bug" + }, + { + "name": "os:macos" + } + ], + "user": { + "login": "futuraprime", + "avatar_url": "https://avatars.githubusercontent.com/u/181752?v=4" + }, + "assignees": [] + } + } +] diff --git a/src/main/github/client-issue-source.test.ts b/src/main/github/client-issue-source.test.ts index 17820ddd0f1..d9c593be3a0 100644 --- a/src/main/github/client-issue-source.test.ts +++ b/src/main/github/client-issue-source.test.ts @@ -2,6 +2,9 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import type * as GithubApiRepositoryModule from './github-api-repository' import type * as GhUtils from './gh-utils' +// Keep legacy REST request/failure coverage; API-boundary suites exercise the GraphQL path. +vi.mock('./client/list/work-item-search-page', () => ({ usesGraphqlWorkItemSearch: () => false })) + const { execFileAsyncMock, ghExecFileAsyncMock, diff --git a/src/main/github/client-work-items-query-paging.test.ts b/src/main/github/client-work-items-query-paging.test.ts index 0e8b62bdfcf..6ff7ace0cc9 100644 --- a/src/main/github/client-work-items-query-paging.test.ts +++ b/src/main/github/client-work-items-query-paging.test.ts @@ -1,6 +1,9 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import type * as GithubApiRepositoryModule from './github-api-repository' +// Keep legacy REST request/failure coverage; API-boundary suites exercise the GraphQL path. +vi.mock('./client/list/work-item-search-page', () => ({ usesGraphqlWorkItemSearch: () => false })) + const { execFileAsyncMock, ghExecFileAsyncMock, diff --git a/src/main/github/client-work-items.test.ts b/src/main/github/client-work-items.test.ts index f26ccfc12d9..31878409768 100644 --- a/src/main/github/client-work-items.test.ts +++ b/src/main/github/client-work-items.test.ts @@ -1,6 +1,9 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import type * as GithubApiRepositoryModule from './github-api-repository' +// Keep legacy REST request/failure coverage; API-boundary suites exercise the GraphQL path. +vi.mock('./client/list/work-item-search-page', () => ({ usesGraphqlWorkItemSearch: () => false })) + const { execFileAsyncMock, ghExecFileAsyncMock, @@ -113,6 +116,7 @@ import { _resetOwnerRepoCache } from './client' import { GITHUB_WORK_ITEMS_QUERY_MAX_BYTES } from '../../shared/github/work-items-query-bounds' +import { _resetRemoteNameListingCache } from '../git/remote-name-listing' import { _resetOriginGitHubApiRepositoryCache } from './github-api-repository' @@ -153,6 +157,7 @@ describe('listWorkItems', () => { remoteName === 'origin' ? getOwnerRepoMock(repoPath, connectionId, opts) : null ) _resetOwnerRepoCache() + _resetRemoteNameListingCache() _resetMergeQueueCacheForTests() }) @@ -380,6 +385,31 @@ describe('listWorkItems', () => { ) }) + it('skips upstream PR source probing when the clone only has origin', async () => { + getIssueOwnerRepoMock.mockResolvedValue(null) + getOwnerRepoMock.mockResolvedValue({ owner: 'fork', repo: 'orca' }) + gitExecFileAsyncMock.mockResolvedValue({ stdout: 'origin\n' }) + ghExecFileAsyncMock.mockResolvedValue({ stdout: '[]' }) + + await expect(listWorkItems('/origin-only-repo', 10, 'is:pr')).resolves.toMatchObject({ + items: [], + sources: { + issues: null, + prs: { owner: 'fork', repo: 'orca' }, + originCandidate: { owner: 'fork', repo: 'orca' }, + upstreamCandidate: null + } + }) + + expect(getOwnerRepoForRemoteMock.mock.calls.map(([, remote]) => remote)).not.toContain( + 'upstream' + ) + expect(gitExecFileAsyncMock).toHaveBeenCalledWith( + ['remote'], + expect.objectContaining({ cwd: '/origin-only-repo' }) + ) + }) + it('rejects oversized queries before resolving repo sources or executing gh', async () => { const secret = 'main-github-work-items-secret' const oversizedQuery = secret + 'x'.repeat(GITHUB_WORK_ITEMS_QUERY_MAX_BYTES) diff --git a/src/main/github/client/fetch/work-item-fetch.ts b/src/main/github/client/fetch/work-item-fetch.ts index aa4dd0794a8..f0c227d05e7 100644 --- a/src/main/github/client/fetch/work-item-fetch.ts +++ b/src/main/github/client/fetch/work-item-fetch.ts @@ -22,11 +22,13 @@ export async function fetchIssueWorkItem( ownerRepo: GitHubApiRepository | null, number: number, connectionId?: string | null, - localGitOptions: LocalGitExecOptions = {} + localGitOptions: LocalGitExecOptions = {}, + environment?: NodeJS.ProcessEnv ): Promise { const ghOptions = { ...ghRepoExecOptions(githubRepoContext(repoPath, connectionId, localGitOptions)), - ...githubHostExecOptions(ownerRepo) + ...githubHostExecOptions(ownerRepo), + ...(environment ? { env: environment } : {}) } if (ownerRepo) { const { stdout } = await ghExecFileAsync( diff --git a/src/main/github/client/list/count-work-items.ts b/src/main/github/client/list/count-work-items.ts index e742597685e..570220586f9 100644 --- a/src/main/github/client/list/count-work-items.ts +++ b/src/main/github/client/list/count-work-items.ts @@ -12,7 +12,8 @@ import { } from '../../gh-utils' import { githubHostExecOptions, - resolveIssueGitHubApiRepositorySource + resolveIssueGitHubApiRepositorySource, + type GitHubRepoExecOptions } from '../../github-api-repository' import { getRateLimit, @@ -23,6 +24,7 @@ import { import { sameOwnerRepo } from './../github-exec-scope' import { resolvePrWorkItemSource } from './work-item-list-request' import { buildSearchQueryString, defaultOpenWorkItemQuery } from './work-item-search-query' +import { searchWorkItemCount, usesGraphqlWorkItemSearch } from './work-item-search-page' export async function countWorkItemsForQuery( repoPath: string, ownerRepo: OwnerRepo, @@ -31,10 +33,23 @@ export async function countWorkItemsForQuery( localGitOptions: LocalGitExecOptions = {} ): Promise { const searchQ = buildSearchQueryString(ownerRepo, query) - const ghOptions = { + const ghOptions: GitHubRepoExecOptions = { ...ghRepoExecOptions(githubRepoContext(repoPath, connectionId, localGitOptions)), ...githubHostExecOptions(ownerRepo) } + if (usesGraphqlWorkItemSearch(ownerRepo, ghOptions)) { + ghOptions.env = { ...process.env } + try { + return await searchWorkItemCount(searchQ, ghOptions) + } catch (error) { + if (error instanceof Error && error.name === 'AbortError') { + throw error + } + } + } + if (repositoryRateLimitGuard(ownerRepo, 'search', ghOptions).blocked) { + return 0 + } const { stdout } = await ghExecFileAsync( [ 'api', @@ -85,7 +100,10 @@ export async function countWorkItems( if (spendsSharedGitHubComQuota(ownerRepo, ghOptions)) { await getRateLimit() } - if (repositoryRateLimitGuard(ownerRepo, 'search', ghOptions).blocked) { + if ( + !usesGraphqlWorkItemSearch(ownerRepo, ghOptions) && + repositoryRateLimitGuard(ownerRepo, 'search', ghOptions).blocked + ) { return 0 } diff --git a/src/main/github/client/list/list-work-items.ts b/src/main/github/client/list/list-work-items.ts index e28037a0233..10192262f6a 100644 --- a/src/main/github/client/list/list-work-items.ts +++ b/src/main/github/client/list/list-work-items.ts @@ -58,7 +58,8 @@ export async function listWorkItems( limit, requestedPage, connectionId, - localGitOptions + localGitOptions, + noCache ) const errors = diff --git a/src/main/github/client/list/work-item-issue-page.ts b/src/main/github/client/list/work-item-issue-page.ts new file mode 100644 index 00000000000..ac1273887d2 --- /dev/null +++ b/src/main/github/client/list/work-item-issue-page.ts @@ -0,0 +1,138 @@ +import { z } from 'zod' +import type { ParsedTaskQuery } from '../../../../shared/task-query' +import { ghExecFileAsync, type LocalGitExecOptions, type OwnerRepo } from '../../gh-utils' +import { noteRepositoryRateLimitSpend } from '../../rate-limit' +import type { GitHubRepoExecOptions } from '../../github-api-repository' +import { fetchIssueWorkItem } from '../fetch/work-item-fetch' +import { mapIssueWorkItem } from '../map/work-item' +import type { MainWorkItem } from '../map/work-item-field-coercion' +import { buildWorkItemListRequest } from './work-item-list-request' +import { buildSearchQueryString } from './work-item-search-query' +import { searchWorkItemPage, usesGraphqlWorkItemSearch } from './work-item-search-page' + +type Actor = { __typename?: string; login: string; avatarUrl?: string } +type IssueNode = { + __typename: string + number: number + title: string + state: string + url: string + updatedAt: string + author: Actor | null + labels: { nodes: { name: string }[]; pageInfo: { hasNextPage: boolean } } + assignees: { nodes: Actor[]; pageInfo: { hasNextPage: boolean } } +} +const ISSUE_NODE_SELECTION = `__typename ... on Issue { + number title state url updatedAt + author { __typename login avatarUrl } + labels(first: 100) { nodes { name } pageInfo { hasNextPage } } + assignees(first: 100) { nodes { __typename login avatarUrl } pageInfo { hasNextPage } } +}` + +function restActor(actor: Actor | null): Record | null { + if (!actor) { + return null + } + const login = + actor.__typename === 'Bot' && !actor.login.endsWith('[bot]') + ? `${actor.login}[bot]` + : actor.login + let avatar = actor.avatarUrl + if (avatar) { + const url = new URL(avatar) + if (url.hostname === 'avatars.githubusercontent.com') { + url.searchParams.delete('u') + avatar = url.toString() + } + } + return { login, avatar_url: avatar } +} + +export async function listIssueWorkItemPage(args: { + repoPath: string + ownerRepo: OwnerRepo + query: ParsedTaskQuery + limit: number + page: number + options: GitHubRepoExecOptions + connectionId?: string | null + localGitOptions?: LocalGitExecOptions + noCache?: boolean +}): Promise { + const preferGraphql = usesGraphqlWorkItemSearch(args.ownerRepo, args.options) + const options = preferGraphql + ? { ...args.options, env: { ...(args.options.env ?? process.env) } } + : args.options + if (preferGraphql) { + try { + const nodes = await searchWorkItemPage({ + search: buildSearchQueryString(args.ownerRepo, { ...args.query, scope: 'issue' }), + nodeSelection: ISSUE_NODE_SELECTION, + limit: args.limit, + page: args.page, + options, + noCache: args.noCache + }) + const items: MainWorkItem[] = [] + for (const node of nodes) { + if (!node || node.__typename !== 'Issue') { + throw new Error('GitHub issue search response missing issue') + } + if ( + !Number.isSafeInteger(node.number) || + node.number <= 0 || + typeof node.title !== 'string' || + typeof node.url !== 'string' || + typeof node.updatedAt !== 'string' || + !['OPEN', 'CLOSED'].includes(node.state) + ) { + throw new Error('GitHub issue search response missing fields') + } + if (!node.labels?.pageInfo || !node.assignees?.pageInfo) { + throw new Error('GitHub issue search response missing association completeness') + } + if (node.labels.pageInfo.hasNextPage || node.assignees.pageInfo.hasNextPage) { + const complete = await fetchIssueWorkItem( + args.repoPath, + args.ownerRepo, + node.number, + args.connectionId, + args.localGitOptions, + options.env + ) + if (!complete) { + throw new Error('GitHub issue detail response missing issue') + } + items.push(complete) + continue + } + items.push( + mapIssueWorkItem({ + ...node, + state: node.state.toLowerCase(), + user: restActor(node.author), + labels: node.labels.nodes, + assignees: node.assignees.nodes.map(restActor) + }) + ) + } + return items + } catch (error) { + if (error instanceof Error && error.name === 'AbortError') { + throw error + } + // REST retains exact search semantics when GraphQL is unavailable for this credential. + } + } + const request = buildWorkItemListRequest({ kind: 'issue', ...args }) + if (args.noCache) { + request.args.splice(1, 2) + } + const { stdout } = await ghExecFileAsync(request.args, options) + noteRepositoryRateLimitSpend(args.ownerRepo, 'search', 1, options) + return z + .array(z.record(z.string(), z.unknown())) + .parse(JSON.parse(stdout)) + .filter((item) => !('pull_request' in item)) + .map(mapIssueWorkItem) +} diff --git a/src/main/github/client/list/work-item-list-request.ts b/src/main/github/client/list/work-item-list-request.ts index 2bad4599237..20c1d482f1a 100644 --- a/src/main/github/client/list/work-item-list-request.ts +++ b/src/main/github/client/list/work-item-list-request.ts @@ -2,6 +2,7 @@ import type { ClassifiedError } from '../../../../shared/classified-error' import type { IssueSourcePreference } from '../../../../shared/repo-types' import type { ParsedTaskQuery } from '../../../../shared/task-query' import { GITHUB_WORK_ITEMS_SSH_REMOTE_REQUIRED_MESSAGE } from '../../../../shared/work-items' +import { shouldProbeGitRemote } from '../../../git/remote-name-listing' import type { LocalGitExecOptions, OwnerRepo } from '../../gh-utils' import { getGitHubApiRepositoryForRemote, @@ -134,9 +135,27 @@ export async function resolvePrWorkItemSource( connectionId?: string | null, localGitOptions: LocalGitExecOptions = {} ): Promise { + const originCandidatePromise = getOriginGitHubApiRepository( + repoPath, + connectionId, + localGitOptions + ) + // Why: PR list/count polling must not spawn a failing upstream lookup on + // origin-only clones, while still preserving upstream-first resolution when + // the remote is configured or remote discovery fails open. + const upstreamCandidatePromise = shouldProbeGitRemote( + repoPath, + 'upstream', + connectionId, + localGitOptions + ).then((shouldProbe) => + shouldProbe + ? getGitHubApiRepositoryForRemote(repoPath, 'upstream', connectionId, localGitOptions) + : null + ) const [originCandidate, upstreamCandidate] = await Promise.all([ - getOriginGitHubApiRepository(repoPath, connectionId, localGitOptions), - getGitHubApiRepositoryForRemote(repoPath, 'upstream', connectionId, localGitOptions) + originCandidatePromise, + upstreamCandidatePromise ]) // Why: fork-contribution PRs live on the upstream repo (the fork's own PR // list is almost always empty), so 'auto' resolves upstream-first exactly diff --git a/src/main/github/client/list/work-item-pages.ts b/src/main/github/client/list/work-item-pages.ts index 63d5e7a0098..73871ae1a45 100644 --- a/src/main/github/client/list/work-item-pages.ts +++ b/src/main/github/client/list/work-item-pages.ts @@ -15,12 +15,13 @@ import { githubHostExecOptions } from '../../github-api-repository' import { githubPRStackExecutionScope } from './../github-exec-scope' import { hydrateWorkItemRepositoryMergeMetadata } from './../detect/hydrate-work-item-merge-metadata' import type { MainWorkItem } from './../map/work-item-field-coercion' -import { mapIssueWorkItem, mapPullRequestWorkItem } from './../map/work-item' +import { mapPullRequestWorkItem } from './../map/work-item' import { buildWorkItemListRequest, assertSshRepoHasResolvedGitHubSource, type PartialWorkItemsResult } from './work-item-list-request' +import { listIssueWorkItemPage } from './work-item-issue-page' export async function listRecentWorkItems( repoPath: string, issueOwnerRepo: OwnerRepo | null, @@ -34,15 +35,6 @@ export async function listRecentWorkItems( const ghOptions = ghRepoExecOptions(githubRepoContext(repoPath, connectionId, localGitOptions)) assertSshRepoHasResolvedGitHubSource({ connectionId, issueOwnerRepo, prOwnerRepo }) const recentQuery = parseTaskQuery('is:open') - const issueRequest = issueOwnerRepo - ? buildWorkItemListRequest({ - kind: 'issue', - ownerRepo: issueOwnerRepo, - limit, - query: recentQuery, - page - }) - : null const prRequest = prOwnerRepo ? buildWorkItemListRequest({ kind: 'pr', @@ -52,18 +44,22 @@ export async function listRecentWorkItems( page }) : null - if (noCache && issueRequest) { - issueRequest.args.splice(1, 2) - } // Why: unresolved sources must stay empty — an unscoped Search API would return other public repos' issues (#9660). // Why: allSettled so a 403 on the issue side doesn't zero the PR half (partial results + banner). const [issuesSettled, prsSettled] = await Promise.allSettled([ - issueRequest && issueOwnerRepo - ? ghExecFileAsync(issueRequest.args, { - ...ghOptions, - ...githubHostExecOptions(issueOwnerRepo) + issueOwnerRepo + ? listIssueWorkItemPage({ + repoPath, + ownerRepo: issueOwnerRepo, + query: recentQuery, + limit, + page, + options: { ...ghOptions, ...githubHostExecOptions(issueOwnerRepo) }, + connectionId, + localGitOptions, + noCache }) - : Promise.resolve({ stdout: '[]' }), + : Promise.resolve([]), prRequest && prOwnerRepo ? ghExecFileAsync(prRequest.args, { ...ghOptions, @@ -75,15 +71,7 @@ export async function listRecentWorkItems( let issues: MainWorkItem[] = [] let issuesError: ClassifiedError | undefined if (issuesSettled.status === 'fulfilled') { - try { - issues = (JSON.parse(issuesSettled.value.stdout) as Record[]) - // Why: search/issues can still return PRs (pull_request marker) even with is:issue; filter them out. - .filter((item) => !('pull_request' in item)) - .map(mapIssueWorkItem) - } catch (err) { - // Why: a malformed issue payload must not discard the successfully fetched PR half. - issuesError = classifyListIssuesError(err instanceof Error ? err.message : String(err)) - } + issues = issuesSettled.value } else { const stderr = issuesSettled.reason instanceof Error @@ -130,7 +118,8 @@ export async function listQueriedWorkItems( limit: number, page?: number, connectionId?: string | null, - localGitOptions: LocalGitExecOptions = {} + localGitOptions: LocalGitExecOptions = {}, + noCache?: boolean ): Promise { const ghOptions = ghRepoExecOptions(githubRepoContext(repoPath, connectionId, localGitOptions)) assertSshRepoHasResolvedGitHubSource({ connectionId, issueOwnerRepo, prOwnerRepo }) @@ -154,27 +143,24 @@ export async function listQueriedWorkItems( if (!issueOwnerRepo) { return { items: [] } } - const request = buildWorkItemListRequest({ - kind: 'issue', - ownerRepo: issueOwnerRepo, - limit, - query, - page: page ?? 1 - }) try { - const { stdout } = await ghExecFileAsync(request.args, { - ...ghOptions, - ...githubHostExecOptions(issueOwnerRepo) + const items = await listIssueWorkItemPage({ + repoPath, + ownerRepo: issueOwnerRepo, + query, + limit, + page: page ?? 1, + options: { ...ghOptions, ...githubHostExecOptions(issueOwnerRepo) }, + connectionId, + localGitOptions, + noCache }) - const items = (JSON.parse(stdout) as Record[]) - .filter((item) => !('pull_request' in item)) - .map(mapIssueWorkItem) successfulRequestCount += 1 return { items } } catch (err) { const stderr = err instanceof Error ? err.message : String(err) if (classifyGitHubUnavailable(stderr)) { - availabilityError ??= err + availabilityError = err } else { nonAvailabilityFailureCount += 1 } diff --git a/src/main/github/client/list/work-item-search-batch.ts b/src/main/github/client/list/work-item-search-batch.ts new file mode 100644 index 00000000000..7f2154b328a --- /dev/null +++ b/src/main/github/client/list/work-item-search-batch.ts @@ -0,0 +1,194 @@ +import { z } from 'zod' +import { createHash } from 'node:crypto' +import { BoundedMap } from '../../../../shared/bounded-map' +import { runCoalescedProbe, type CoalescedProbes } from '../../../git/coalesced-probe' +import { createGhRateLimitBlockedError } from '../../../git/gh-rate-limit-breaker' +import { extractExecError, ghExecFileAsync } from '../../gh-utils' +import { noteRepositoryRateLimitSpend, repositoryRateLimitGuard } from '../../rate-limit' +import type { GitHubRepoExecOptions } from '../../github-api-repository' + +const envelopeSchema = z.object({ + data: z.record(z.string(), z.unknown()).nullish(), + errors: z + .array( + z.object({ + message: z.string().optional(), + path: z.array(z.union([z.string(), z.number()])).optional() + }) + ) + .optional() +}) +type Envelope = z.infer +type SearchRequest = { + search: string + first: number + after?: string + selection: string + options: GitHubRepoExecOptions + environment?: NodeJS.ProcessEnv + noCache?: boolean +} +type PendingSearch = { + request: SearchRequest + environment: NodeJS.ProcessEnv + resolve: (value: unknown) => void + reject: (error: unknown) => void +} + +export const WORK_ITEM_SEARCH_CACHE_MS = 120_000 +const MAX_BATCH = 10 +// Leave room for Windows argv escaping and the gh executable path. +const MAX_BATCH_QUERY_CHARS = 12_000 +const pending = new Map() +type SearchResponse = { at: number; value: T } +const inFlight: CoalescedProbes> = new Map() +const responses = new BoundedMap({ + maxEntries: 512, + maxBytes: 16 * 1024 * 1024, + sizeOf: (value, key) => Buffer.byteLength(key) + Buffer.byteLength(JSON.stringify(value)) +}) + +export function workItemSearchScope( + options: GitHubRepoExecOptions, + environment: NodeJS.ProcessEnv = options.env ?? process.env +): string { + // gh wrappers and credential selection can depend on cwd and the inherited environment. + return createHash('sha256') + .update( + JSON.stringify([ + options, + process.cwd(), + Object.entries(environment).sort(([a], [b]) => a.localeCompare(b)) + ]) + ) + .digest('hex') +} + +export function requestWorkItemSearch(request: SearchRequest): Promise> { + const environment = { ...(request.environment ?? request.options.env ?? process.env) } + const scope = workItemSearchScope(request.options, environment) + const key = JSON.stringify([ + scope, + request.search, + request.first, + request.after, + request.selection + ]) + const cached = request.noCache ? undefined : responses.get(key) + if (cached && Date.now() - cached.at < WORK_ITEM_SEARCH_CACHE_MS) { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The cache key includes the complete selection; callers validate its response shape. + return Promise.resolve(cached as SearchResponse) + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Coalescing uses the complete selection key; callers validate the selected response. + return runCoalescedProbe(inFlight, `${key}:${Boolean(request.noCache)}`, async (ownsKey) => { + const value = await new Promise((resolve, reject) => { + const batchKey = `${scope}:${Boolean(request.noCache)}` + let queue = pending.get(batchKey) + if (!queue) { + queue = [] + pending.set(batchKey, queue) + setTimeout(() => flushSearches(batchKey), 0) + } + queue.push({ request, environment, resolve, reject }) + }) + const response = { at: Date.now(), value } + if (!request.noCache && ownsKey()) { + responses.set(key, response) + } + return response + }) as Promise> +} + +function flushSearches(key: string): void { + const queue = pending.get(key) + pending.delete(key) + if (!queue) { + return + } + let batch: PendingSearch[] = [] + let characters = 0 + for (const entry of queue) { + const size = searchSelection(entry.request, batch.length).length + if (batch.length && (batch.length === MAX_BATCH || characters + size > MAX_BATCH_QUERY_CHARS)) { + void executeSearches(batch) + batch = [] + characters = 0 + } + batch.push(entry) + characters += size + } + if (batch.length) { + void executeSearches(batch) + } +} + +function searchSelection(request: SearchRequest, index: number): string { + const after = request.after ? `, after: ${JSON.stringify(request.after)}` : '' + return `r${index}: search(type: ISSUE, query: ${JSON.stringify(request.search)}, first: ${request.first}${after}) { ${request.selection} }` +} + +async function executeSearches(batch: PendingSearch[]): Promise { + const { options } = batch[0].request + try { + const guard = repositoryRateLimitGuard(options, 'graphql', options) + if (guard.blocked) { + throw createGhRateLimitBlockedError('graphql', guard.resetAt * 1000) + } + const selections = batch.map(({ request }, index) => searchSelection(request, index)) + const query = `query { ${selections.join('\n')} rateLimit { cost } }` + // One response cache owns age; a gh cache hit would otherwise renew an older response. + const args = ['api', 'graphql', '-f', `query=${query}`] + let envelope: Envelope + try { + const { stdout } = await ghExecFileAsync(args, { + ...options, + env: batch[0].environment, + idempotent: true + }) + envelope = envelopeSchema.parse(JSON.parse(stdout)) + } catch (error) { + const { stdout } = extractExecError(error) + if (!stdout) { + throw error + } + try { + envelope = envelopeSchema.parse(JSON.parse(stdout)) + } catch { + throw error + } + if (!envelope.data || !envelope.errors?.length) { + throw error + } + } + const rateLimit = envelope.data?.rateLimit + const cost = + rateLimit && typeof rateLimit === 'object' && 'cost' in rateLimit ? rateLimit.cost : undefined + noteRepositoryRateLimitSpend( + options, + 'graphql', + typeof cost === 'number' && Number.isFinite(cost) && cost >= 0 ? cost : batch.length, + options + ) + for (const [index, entry] of batch.entries()) { + const alias = `r${index}` + const errors = envelope.errors?.filter( + (error) => !error.path?.length || error.path[0] === alias + ) + const value = envelope.data?.[alias] + if (errors?.length || value === undefined || value === null) { + entry.reject( + new Error( + errors?.map((error) => error.message).join('; ') || + 'GitHub search response missing data' + ) + ) + } else { + entry.resolve(value) + } + } + } catch (error) { + for (const entry of batch) { + entry.reject(error) + } + } +} diff --git a/src/main/github/client/list/work-item-search-page.ts b/src/main/github/client/list/work-item-search-page.ts new file mode 100644 index 00000000000..e03c16e777b --- /dev/null +++ b/src/main/github/client/list/work-item-search-page.ts @@ -0,0 +1,128 @@ +import { BoundedMap } from '../../../../shared/bounded-map' +import { isDefaultGitHubHost } from '../../../../shared/github/repository-identity-key' +import type { OwnerRepo } from '../../gh-utils' +import type { GitHubRepoExecOptions } from '../../github-api-repository' +import { + requestWorkItemSearch, + workItemSearchScope, + WORK_ITEM_SEARCH_CACHE_MS +} from './work-item-search-batch' + +type PageInfo = { endCursor: string | null; hasNextPage: boolean } +export type SearchConnection = { issueCount: number; pageInfo: PageInfo; nodes: T[] } +const cursors = new BoundedMap({ + maxEntries: 1024, + maxBytes: 1024 * 1024, + sizeOf: (value, key) => Buffer.byteLength(key) + Buffer.byteLength(value.cursor) + 8 +}) + +export function usesGraphqlWorkItemSearch( + ownerRepo: OwnerRepo, + options: GitHubRepoExecOptions +): boolean { + return isDefaultGitHubHost( + ownerRepo.host ?? options.host ?? options.env?.GH_HOST ?? process.env.GH_HOST + ) +} + +export async function searchWorkItemCount( + search: string, + options: GitHubRepoExecOptions +): Promise { + const { value: result } = await requestWorkItemSearch<{ issueCount: number }>({ + search, + first: 1, + selection: 'issueCount', + options + }) + if (!Number.isSafeInteger(result.issueCount) || result.issueCount < 0) { + throw new Error('GitHub search response missing count') + } + return result.issueCount +} + +export async function searchWorkItemPage(args: { + search: string + nodeSelection: string + limit: number + page: number + options: GitHubRepoExecOptions + noCache?: boolean +}): Promise { + const { options, noCache } = args + const environment = { ...(options.env ?? process.env) } + if (!Number.isSafeInteger(args.limit) || args.limit < 1) { + throw new Error('Invalid GitHub search page limit') + } + const limit = Math.min(100, args.limit) + const offset = (args.page - 1) * limit + if (offset + limit > 1000) { + throw new Error('Only the first 1000 search results are available (HTTP 422)') + } + const search = `${args.search} sort:created-desc` + const scope = JSON.stringify([workItemSearchScope(options, environment), search]) + let position = 0 + let after: string | undefined + if (!noCache) { + for (let at = offset; at > 0; at--) { + const cached = cursors.get(`${scope}:${at}`) + if (cached && Date.now() - cached.at < WORK_ITEM_SEARCH_CACHE_MS) { + position = at + after = cached.cursor + break + } + } + } + const remember = (position: number, info: PageInfo, at: number): void => { + if ( + typeof info.hasNextPage !== 'boolean' || + (info.endCursor !== null && typeof info.endCursor !== 'string') + ) { + throw new Error('GitHub search response invalid pagination') + } + if (info.hasNextPage && !info.endCursor) { + throw new Error('GitHub search response missing cursor') + } + if (!noCache && info.endCursor) { + cursors.set(`${scope}:${position}`, { at, cursor: info.endCursor }) + } + } + while (position < offset) { + const first = Math.min(100, offset - position) + const { value: skipped, at } = await requestWorkItemSearch>({ + search, + first, + after, + selection: 'issueCount pageInfo { endCursor hasNextPage }', + options, + environment, + noCache + }) + if (!skipped.pageInfo || !Number.isSafeInteger(skipped.issueCount)) { + throw new Error('GitHub search response missing pagination') + } + if (skipped.issueCount <= offset) { + return [] + } + if (!skipped.pageInfo.hasNextPage) { + throw new Error('GitHub search pagination ended before requested page') + } + position += first + remember(position, skipped.pageInfo, at) + after = skipped.pageInfo.endCursor ?? undefined + } + const { value: result, at } = await requestWorkItemSearch>({ + search, + first: limit, + after, + selection: `issueCount pageInfo { endCursor hasNextPage } nodes { ${args.nodeSelection} }`, + options, + environment, + noCache + }) + if (!Array.isArray(result.nodes) || !result.pageInfo) { + throw new Error('GitHub search response missing page') + } + remember(offset + result.nodes.length, result.pageInfo, at) + return result.nodes +} diff --git a/src/main/github/default-branch-stale-pr.test.ts b/src/main/github/default-branch-stale-pr.test.ts index fde4b6b8b84..4361c9759e7 100644 --- a/src/main/github/default-branch-stale-pr.test.ts +++ b/src/main/github/default-branch-stale-pr.test.ts @@ -278,7 +278,13 @@ describe('issue #9171: default-branch checkout must not attach a stale non-open expect(pr?.number).toBe(8) expect(pr?.state).toBe('open') // Open results never consult git for the default branch (lazy resolution). - expect(gitExecFileAsyncMock).not.toHaveBeenCalled() + // Remote-name listing is a separate concern from default-branch resolution, + // so allow it and keep every other git command forbidden here. + expect( + gitExecFileAsyncMock.mock.calls + .map(([args]) => args[0]) + .filter((command) => command !== 'remote') + ).toEqual([]) }) it('keeps a CLOSED PR on a feature branch visible (behavior preserved)', async () => { diff --git a/src/main/github/gh-utils.test.ts b/src/main/github/gh-utils.test.ts index ba19fc13fda..5400eaeb565 100644 --- a/src/main/github/gh-utils.test.ts +++ b/src/main/github/gh-utils.test.ts @@ -21,6 +21,7 @@ vi.mock('../providers/ssh-git-dispatch', () => ({ getSshGitProvider: getSshGitProviderMock })) +import { _resetRemoteNameListingCache } from '../git/remote-name-listing' import { _getOwnerRepoCacheSize, _resetOwnerRepoCache, @@ -40,6 +41,35 @@ import { } from './local-git-config-signature' import { GITHUB_SEARCH_RESULT_WINDOW_ERROR_PATTERN } from '../../shared/github/work-items-query-bounds' +function mockGitRemoteCommands(remotes: Record): void { + gitExecFileAsyncMock.mockImplementation(async (args: string[]) => { + if (args[0] === 'remote' && args[1] !== 'get-url') { + return { stdout: `${Object.keys(remotes).join('\n')}\n` } + } + if (args[0] === 'remote' && args[1] === 'get-url') { + const url = remotes[args[2] ?? ''] + if (!url) { + throw new Error(`fatal: No such remote '${args[2]}'`) + } + return { stdout: url } + } + throw new Error(`unexpected git ${args.join(' ')}`) + }) +} + +function gitRemoteGetUrlCalls(remoteName: string): unknown[][] { + return gitExecFileAsyncMock.mock.calls.filter( + ([args]) => + Array.isArray(args) && args[0] === 'remote' && args[1] === 'get-url' && args[2] === remoteName + ) +} + +function gitRemoteListCalls(): unknown[][] { + return gitExecFileAsyncMock.mock.calls.filter( + ([args]) => Array.isArray(args) && args[0] === 'remote' && args[1] !== 'get-url' + ) +} + describe('github owner/repo resolution', () => { beforeEach(() => { gitExecFileAsyncMock.mockReset() @@ -47,6 +77,7 @@ describe('github owner/repo resolution', () => { getSshGitProviderGenerationMock.mockReturnValue(0) getSshGitProviderMock.mockReset() _resetOwnerRepoCache() + _resetRemoteNameListingCache() __resetLocalGitConfigSignatureCacheForTests() }) @@ -97,57 +128,46 @@ describe('github owner/repo resolution', () => { }) it('prefers upstream for PR owner/repo resolution (#7331)', async () => { - gitExecFileAsyncMock.mockResolvedValueOnce({ - stdout: 'git@github.com:stablyai/orca.git\n' + mockGitRemoteCommands({ + origin: 'git@github.com:fork/orca.git\n', + upstream: 'git@github.com:stablyai/orca.git\n' }) await expect(getOwnerRepo('/repo')).resolves.toEqual({ owner: 'stablyai', repo: 'orca' }) - expect(gitExecFileAsyncMock).toHaveBeenCalledWith(['remote', 'get-url', 'upstream'], { - cwd: '/repo', - timeout: 30_000 - }) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(1) }) - it('resolves GitHub HTTPS origin remotes with user info and a default port', async () => { - gitExecFileAsyncMock - .mockRejectedValueOnce(new Error("fatal: No such remote 'upstream'")) - .mockResolvedValueOnce({ - stdout: 'https://alice@github.com:443/acme/widgets.git\n' - }) + it('does not spawn git remote get-url upstream on an origin-only clone', async () => { + mockGitRemoteCommands({ + origin: 'https://alice@github.com:443/acme/widgets.git\n' + }) await expect(getOwnerRepo('/repo')).resolves.toEqual({ owner: 'acme', repo: 'widgets' }) - expect(gitExecFileAsyncMock).toHaveBeenCalledWith(['remote', 'get-url', 'origin'], { - cwd: '/repo', - timeout: 30_000 - }) + await expect(getOwnerRepo('/repo')).resolves.toEqual({ owner: 'acme', repo: 'widgets' }) + expect(gitRemoteListCalls()).toHaveLength(1) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(0) + expect(gitRemoteGetUrlCalls('origin')).toHaveLength(1) }) it('prefers upstream for issue owner/repo resolution', async () => { - gitExecFileAsyncMock.mockResolvedValueOnce({ - stdout: 'git@github.com:stablyai/orca.git\n' + mockGitRemoteCommands({ + origin: 'git@github.com:fork/orca.git\n', + upstream: 'git@github.com:stablyai/orca.git\n' }) await expect(getIssueOwnerRepo('/repo')).resolves.toEqual({ owner: 'stablyai', repo: 'orca' }) - expect(gitExecFileAsyncMock).toHaveBeenCalledWith(['remote', 'get-url', 'upstream'], { - cwd: '/repo', - timeout: 30_000 - }) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(1) }) - it('falls back to origin when upstream is missing or non-GitHub', async () => { - gitExecFileAsyncMock - .mockResolvedValueOnce({ stdout: 'git@example.com:stablyai/orca.git\n' }) - .mockResolvedValueOnce({ stdout: 'git@github.com:fork/orca.git\n' }) + it('falls back to origin when upstream is present but non-GitHub', async () => { + mockGitRemoteCommands({ + origin: 'git@github.com:fork/orca.git\n', + upstream: 'git@example.com:stablyai/orca.git\n' + }) await expect(getIssueOwnerRepo('/repo')).resolves.toEqual({ owner: 'fork', repo: 'orca' }) - expect(gitExecFileAsyncMock).toHaveBeenNthCalledWith(1, ['remote', 'get-url', 'upstream'], { - cwd: '/repo', - timeout: 30_000 - }) - expect(gitExecFileAsyncMock).toHaveBeenNthCalledWith(2, ['remote', 'get-url', 'origin'], { - cwd: '/repo', - timeout: 30_000 - }) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(1) + expect(gitRemoteGetUrlCalls('origin')).toHaveLength(1) }) it('does not mix origin and upstream cache entries for the same repo path', async () => { @@ -193,6 +213,9 @@ describe('github owner/repo resolution', () => { it('resolves SSH repo remotes through the registered SSH git provider', async () => { const sshProvider = { exec: vi.fn(async (args: string[]) => { + if (args[0] === 'remote' && args[1] !== 'get-url') { + return { stdout: 'origin\n', stderr: '' } + } if (args[2] === 'upstream') { throw new Error("fatal: No such remote 'upstream'") } @@ -219,9 +242,14 @@ describe('github owner/repo resolution', () => { it('keeps local and SSH owner/repo cache entries separate for the same path', async () => { const sshProvider = { - exec: vi.fn().mockResolvedValue({ stdout: 'git@github.com:remote/orca.git\n', stderr: '' }) + exec: vi.fn(async (args: string[]) => { + if (args[0] === 'remote' && args[1] !== 'get-url') { + return { stdout: 'origin\n', stderr: '' } + } + return { stdout: 'git@github.com:remote/orca.git\n', stderr: '' } + }) } - gitExecFileAsyncMock.mockResolvedValueOnce({ stdout: 'git@github.com:local/orca.git\n' }) + mockGitRemoteCommands({ origin: 'git@github.com:local/orca.git\n' }) getSshGitProviderMock.mockReturnValue(sshProvider) await expect(getOwnerRepo('/repo')).resolves.toEqual({ owner: 'local', repo: 'orca' }) @@ -231,6 +259,9 @@ describe('github owner/repo resolution', () => { it('keeps local host and local WSL owner/repo cache entries separate for the same path', async () => { gitExecFileAsyncMock.mockImplementation( async (args: string[], options: { wslDistro?: string } = {}) => { + if (args[0] === 'remote' && args[1] !== 'get-url') { + return { stdout: 'origin\n' } + } if (args[2] === 'upstream') { throw new Error("fatal: No such remote 'upstream'") } @@ -252,8 +283,9 @@ describe('github owner/repo resolution', () => { repo: 'orca' }) - // 2 runtimes x (1 upstream miss + 1 origin hit); repeat WSL call is cached. + // 2 runtimes x (1 remote list + 1 origin hit); repeat WSL call is cached. expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(4) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(0) expect(gitExecFileAsyncMock).toHaveBeenCalledWith(['remote', 'get-url', 'origin'], { cwd: '/repo', timeout: 30_000 @@ -272,14 +304,20 @@ describe('github owner/repo resolution', () => { gitExecFileAsyncMock.mockResolvedValueOnce({ stdout: 'git@github.com:stablyai/orca.git\n' }) - await expect(getOwnerRepo('/repo-a')).resolves.toEqual({ owner: 'stablyai', repo: 'orca' }) + await expect(getOwnerRepoForRemote('/repo-a', 'origin')).resolves.toEqual({ + owner: 'stablyai', + repo: 'orca' + }) expect(_getOwnerRepoCacheSize()).toBe(1) nowSpy.mockReturnValue(32_000) gitExecFileAsyncMock.mockResolvedValueOnce({ stdout: 'git@github.com:acme/widgets.git\n' }) - await expect(getOwnerRepo('/repo-b')).resolves.toEqual({ owner: 'acme', repo: 'widgets' }) + await expect(getOwnerRepoForRemote('/repo-b', 'origin')).resolves.toEqual({ + owner: 'acme', + repo: 'widgets' + }) expect(_getOwnerRepoCacheSize()).toBe(1) expect(gitExecFileAsyncMock).toHaveBeenCalledTimes(2) @@ -289,20 +327,38 @@ describe('github owner/repo resolution', () => { }) it('resolves PR candidates as upstream then origin and de-dupes matching slugs', async () => { - gitExecFileAsyncMock - .mockResolvedValueOnce({ stdout: 'git@github.com:Acme/Orca.git\n' }) - .mockResolvedValueOnce({ stdout: 'git@github.com:acme/orca.git\n' }) + mockGitRemoteCommands({ + origin: 'git@github.com:acme/orca.git\n', + upstream: 'git@github.com:Acme/Orca.git\n' + }) await expect(resolvePRRepositoryCandidates('/repo')).resolves.toEqual({ candidates: [{ owner: 'Acme', repo: 'Orca' }], headRepo: { owner: 'acme', repo: 'orca' } }) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(1) + }) + + it('does not spawn git remote get-url upstream for origin-only PR candidates', async () => { + mockGitRemoteCommands({ origin: 'git@github.com:fork/orca.git\n' }) + + await expect(resolvePRRepositoryCandidates('/repo')).resolves.toEqual({ + candidates: [{ owner: 'fork', repo: 'orca' }], + headRepo: { owner: 'fork', repo: 'orca' } + }) + await expect(resolvePRRepositoryCandidates('/repo')).resolves.toEqual({ + candidates: [{ owner: 'fork', repo: 'orca' }], + headRepo: { owner: 'fork', repo: 'orca' } + }) + expect(gitRemoteListCalls()).toHaveLength(1) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(0) }) it('ignores non-GitHub upstream while keeping origin as the head repo', async () => { - gitExecFileAsyncMock - .mockResolvedValueOnce({ stdout: 'git@example.com:Acme/Orca.git\n' }) - .mockResolvedValueOnce({ stdout: 'git@github.com:fork/orca.git\n' }) + mockGitRemoteCommands({ + origin: 'git@github.com:fork/orca.git\n', + upstream: 'git@example.com:Acme/Orca.git\n' + }) await expect(resolvePRRepositoryCandidates('/repo')).resolves.toEqual({ candidates: [{ owner: 'fork', repo: 'orca' }], @@ -703,23 +759,27 @@ describe('resolveIssueSource', () => { gitExecFileAsyncMock.mockReset() getSshGitProviderMock.mockReset() _resetOwnerRepoCache() + _resetRemoteNameListingCache() }) it("'auto' + upstream exists → upstream, fellBack=false", async () => { - gitExecFileAsyncMock.mockResolvedValueOnce({ - stdout: 'git@github.com:stablyai/orca.git\n' + mockGitRemoteCommands({ + origin: 'git@github.com:fork/orca.git\n', + upstream: 'git@github.com:stablyai/orca.git\n' }) await expect(resolveIssueSource('/repo', 'auto')).resolves.toEqual({ source: { owner: 'stablyai', repo: 'orca' }, fellBack: false }) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(1) }) - it("'auto' + no upstream → origin, fellBack=false", async () => { - gitExecFileAsyncMock - .mockResolvedValueOnce({ stdout: 'git@example.com:stablyai/orca.git\n' }) - .mockResolvedValueOnce({ stdout: 'git@github.com:solo/orca.git\n' }) + it("'auto' + no github upstream → origin, fellBack=false", async () => { + mockGitRemoteCommands({ + origin: 'git@github.com:solo/orca.git\n', + upstream: 'git@example.com:stablyai/orca.git\n' + }) await expect(resolveIssueSource('/repo', 'auto')).resolves.toEqual({ source: { owner: 'solo', repo: 'orca' }, @@ -779,8 +839,9 @@ describe('resolveIssueSource', () => { }) it('undefined preference is treated identically to auto', async () => { - gitExecFileAsyncMock.mockResolvedValueOnce({ - stdout: 'git@github.com:stablyai/orca.git\n' + mockGitRemoteCommands({ + origin: 'git@github.com:fork/orca.git\n', + upstream: 'git@github.com:stablyai/orca.git\n' }) await expect(resolveIssueSource('/repo', undefined)).resolves.toEqual({ diff --git a/src/main/github/github-api-repository-remote-probe.ts b/src/main/github/github-api-repository-remote-probe.ts new file mode 100644 index 00000000000..31159a4a8c4 --- /dev/null +++ b/src/main/github/github-api-repository-remote-probe.ts @@ -0,0 +1,132 @@ +import type { GitHubApiRepository } from './github-api-repository' +import { + getOwnerRepoForRemote, + type GitHubRemoteIdentityProbeOptions, + type LocalGitExecOptions +} from './gh-utils' +import { + getEnterpriseGitHubRepoSlug, + getEnterpriseGitHubRepoSlugForRemote +} from './github-enterprise-repository' +import { + githubApiRepositoryProbeCacheKey, + resolveGitHubApiRepositoryProbe +} from './github-api-repository-probe' + +// Why: cache the uncached Enterprise remote probe used by hot paths. +const ORIGIN_REPO_CACHE_TTL_MS = 30_000 +const ORIGIN_REPO_CACHE_MAX_ENTRIES = 512 +const originRepoCache = new Map() +const originRepoInFlight = new Map>() + +/** @internal - exposed for tests only */ +export function _resetOriginGitHubApiRepositoryCache(): void { + originRepoCache.clear() + originRepoInFlight.clear() +} + +function pruneOriginRepoCache(now: number): void { + for (const [key, entry] of originRepoCache) { + if (entry.expiresAt <= now) { + originRepoCache.delete(key) + } + } + while (originRepoCache.size > ORIGIN_REPO_CACHE_MAX_ENTRIES) { + const oldestKey = originRepoCache.keys().next().value + if (oldestKey === undefined) { + return + } + originRepoCache.delete(oldestKey) + } +} + +/** + * Host-qualified repository identity for one remote: github.com remotes come + * from the cached slug parser; any other GitHub-shaped host is auth-gated so a + * non-GitHub forge never routes to the GitHub provider. + */ +export async function getGitHubApiRepositoryForRemote( + repoPath: string, + remoteName: string, + connectionId?: string | null, + localGitOptions: LocalGitExecOptions = {}, + probeOptions: GitHubRemoteIdentityProbeOptions = {} +): Promise { + // Why: generic PR resolution prefers upstream, but this API represents the + // caller-selected remote exactly (#7331). + const requireVerifiedSshProbe = probeOptions.requireVerifiedSshProbe === true + const verifiedIdentityArgs = requireVerifiedSshProbe ? ([probeOptions] as const) : [] + const ownerRepo = await getOwnerRepoForRemote( + repoPath, + remoteName, + connectionId, + localGitOptions, + ...verifiedIdentityArgs + ) + if (ownerRepo) { + return { ...ownerRepo, host: 'github.com' } + } + const cacheKey = githubApiRepositoryProbeCacheKey( + repoPath, + remoteName, + connectionId, + localGitOptions, + requireVerifiedSshProbe + ) + const now = Date.now() + pruneOriginRepoCache(now) + const cached = originRepoCache.get(cacheKey) + if (cached && cached.expiresAt > now) { + return cached.value + } + const inFlight = originRepoInFlight.get(cacheKey) + if (inFlight) { + return inFlight + } + const probe = (async () => { + const enterpriseOptions = + Object.keys(localGitOptions).length > 0 ? { localGitExecOptions: localGitOptions } : {} + const verifiedEnterpriseArgs = requireVerifiedSshProbe ? ([true] as const) : [] + const slug = + remoteName === 'origin' + ? await getEnterpriseGitHubRepoSlug( + repoPath, + connectionId, + enterpriseOptions, + ...verifiedEnterpriseArgs + ) + : await getEnterpriseGitHubRepoSlugForRemote( + repoPath, + remoteName, + connectionId, + enterpriseOptions, + ...verifiedEnterpriseArgs + ) + // Why: undefined means the gh auth inventory could not be read. Caching it + // as a negative would turn a transient spawn failure into a 30-second miss. + if (slug !== undefined) { + originRepoCache.set(cacheKey, { + value: slug, + expiresAt: Date.now() + ORIGIN_REPO_CACHE_TTL_MS + }) + pruneOriginRepoCache(Date.now()) + } + return resolveGitHubApiRepositoryProbe(slug, requireVerifiedSshProbe) + })() + originRepoInFlight.set(cacheKey, probe) + try { + return await probe + } finally { + if (originRepoInFlight.get(cacheKey) === probe) { + originRepoInFlight.delete(cacheKey) + } + } +} + +export async function getOriginGitHubApiRepository( + repoPath: string, + connectionId?: string | null, + localGitOptions: LocalGitExecOptions = {} +): Promise { + return getGitHubApiRepositoryForRemote(repoPath, 'origin', connectionId, localGitOptions) +} diff --git a/src/main/github/github-api-repository.test.ts b/src/main/github/github-api-repository.test.ts index fb6512dab30..ad09e2d38ec 100644 --- a/src/main/github/github-api-repository.test.ts +++ b/src/main/github/github-api-repository.test.ts @@ -8,13 +8,15 @@ const { getOwnerRepoMock, getOwnerRepoForRemoteMock, getSshGitProviderGenerationMock, - isGitHubHostAuthenticatedMock + isGitHubHostAuthenticatedMock, + shouldProbeGitRemoteMock } = vi.hoisted(() => ({ getEnterpriseGitHubRepoSlugMock: vi.fn(), getOwnerRepoMock: vi.fn(), getOwnerRepoForRemoteMock: vi.fn(), getSshGitProviderGenerationMock: vi.fn(() => 0), - isGitHubHostAuthenticatedMock: vi.fn() + isGitHubHostAuthenticatedMock: vi.fn(), + shouldProbeGitRemoteMock: vi.fn(async () => true) })) vi.mock('../providers/ssh-git-dispatch', async (importOriginal) => ({ @@ -35,12 +37,18 @@ vi.mock('./github-enterprise-repository', async (importOriginal) => ({ isGitHubHostAuthenticated: isGitHubHostAuthenticatedMock })) +vi.mock('../git/remote-name-listing', () => ({ + shouldProbeGitRemote: shouldProbeGitRemoteMock +})) + import { _resetOriginGitHubApiRepositoryCache, getGitHubApiRepositoryForRemote, + getIssueGitHubApiRepository, getOriginGitHubApiRepository, githubHostExecOptions, resolveGitHubApiRepository, + resolveGitHubApiRepositoryCandidates, resolveGitHubRepoExecution } from './github-api-repository' @@ -51,6 +59,7 @@ beforeEach(() => { getOwnerRepoForRemoteMock.mockReset().mockResolvedValue(null) getSshGitProviderGenerationMock.mockReset().mockReturnValue(0) isGitHubHostAuthenticatedMock.mockReset().mockResolvedValue(false) + shouldProbeGitRemoteMock.mockReset().mockResolvedValue(true) }) describe('githubHostExecOptions', () => { @@ -346,3 +355,146 @@ describe('origin repository cache', () => { expect(getEnterpriseGitHubRepoSlugMock).toHaveBeenCalledTimes(2) }) }) + +describe('skip missing upstream remote probes', () => { + it('starts the issue origin probe before checking whether upstream exists', async () => { + let releaseRemoteProbe: (value: boolean) => void = () => undefined + shouldProbeGitRemoteMock.mockReturnValue( + new Promise((resolve) => { + releaseRemoteProbe = resolve + }) + ) + let originStarted = false + getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => { + if (remote === 'origin') { + originStarted = true + return { owner: 'fork', repo: 'orca' } + } + return { owner: 'stablyai', repo: 'orca' } + }) + + const resultPromise = getIssueGitHubApiRepository('/repo') + expect(originStarted).toBe(true) + + releaseRemoteProbe(true) + await expect(resultPromise).resolves.toEqual({ + owner: 'stablyai', + repo: 'orca', + host: 'github.com' + }) + }) + + it('does not probe upstream for issue identity when that remote is absent', async () => { + shouldProbeGitRemoteMock.mockResolvedValue(false) + getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => + remote === 'origin' ? { owner: 'acme', repo: 'widgets' } : null + ) + + await expect(getIssueGitHubApiRepository('/repo')).resolves.toEqual({ + owner: 'acme', + repo: 'widgets', + host: 'github.com' + }) + expect(getOwnerRepoForRemoteMock.mock.calls.map(([, remote]) => remote)).toEqual(['origin']) + }) + + it('still probes upstream for issue identity when that remote is present', async () => { + getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => + remote === 'upstream' ? { owner: 'stablyai', repo: 'orca' } : { owner: 'fork', repo: 'orca' } + ) + + await expect(getIssueGitHubApiRepository('/repo')).resolves.toEqual({ + owner: 'stablyai', + repo: 'orca', + host: 'github.com' + }) + expect(getOwnerRepoForRemoteMock).toHaveBeenCalledWith('/repo', 'upstream', undefined, {}) + }) + + it('observes a rejected origin probe when upstream resolves the issue repository', async () => { + const originError = new Error('origin probe failed') + getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => { + if (remote === 'origin') { + throw originError + } + return { owner: 'stablyai', repo: 'orca' } + }) + + await expect(getIssueGitHubApiRepository('/repo')).resolves.toEqual({ + owner: 'stablyai', + repo: 'orca', + host: 'github.com' + }) + }) + + it('preserves a rejected origin probe when upstream cannot resolve the issue repository', async () => { + const originError = new Error('origin probe failed') + getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => { + if (remote === 'origin') { + throw originError + } + return null + }) + + await expect(getIssueGitHubApiRepository('/repo')).rejects.toBe(originError) + }) + + it('does not probe upstream for PR candidates when that remote is absent', async () => { + shouldProbeGitRemoteMock.mockResolvedValue(false) + getOwnerRepoForRemoteMock.mockResolvedValue({ owner: 'fork', repo: 'orca' }) + + await expect(resolveGitHubApiRepositoryCandidates('/repo')).resolves.toEqual({ + candidates: [{ owner: 'fork', repo: 'orca', host: 'github.com' }], + headRepo: { owner: 'fork', repo: 'orca', host: 'github.com' } + }) + expect(getOwnerRepoForRemoteMock.mock.calls.map(([, remote]) => remote)).toEqual(['origin']) + }) + + it('observes and propagates a verified origin probe failure while listing remotes', async () => { + let releaseRemoteProbe: (value: boolean) => void = () => undefined + shouldProbeGitRemoteMock.mockReturnValue( + new Promise((resolve) => { + releaseRemoteProbe = resolve + }) + ) + const originError = new Error('origin probe failed') + getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => { + if (remote === 'origin') { + throw originError + } + return { owner: 'stablyai', repo: 'orca' } + }) + + const resultPromise = resolveGitHubApiRepositoryCandidates('/repo') + await vi.waitFor(() => + expect(getOwnerRepoForRemoteMock).toHaveBeenCalledWith( + '/repo', + 'origin', + undefined, + {}, + { requireVerifiedSshProbe: true } + ) + ) + releaseRemoteProbe(true) + + await expect(resultPromise).rejects.toBe(originError) + }) + + it('still probes upstream for PR candidates when that remote is present', async () => { + getOwnerRepoForRemoteMock.mockImplementation(async (_path, remote) => + remote === 'upstream' ? { owner: 'Acme', repo: 'Orca' } : { owner: 'acme', repo: 'orca' } + ) + + await expect(resolveGitHubApiRepositoryCandidates('/repo')).resolves.toEqual({ + candidates: [{ owner: 'Acme', repo: 'Orca', host: 'github.com' }], + headRepo: { owner: 'acme', repo: 'orca', host: 'github.com' } + }) + expect(getOwnerRepoForRemoteMock).toHaveBeenCalledWith( + '/repo', + 'upstream', + undefined, + {}, + { requireVerifiedSshProbe: true } + ) + }) +}) diff --git a/src/main/github/github-api-repository.ts b/src/main/github/github-api-repository.ts index 7e394789714..db3eccbc106 100644 --- a/src/main/github/github-api-repository.ts +++ b/src/main/github/github-api-repository.ts @@ -4,27 +4,19 @@ import { githubRepoIdentityKey, isDefaultGitHubHost } from '../../shared/github/repository-identity-key' -import { - getOwnerRepoForRemote, - ghRepoExecOptions, - githubRepoContext, - type GitHubRemoteIdentityProbeOptions, - type LocalGitExecOptions -} from './gh-utils' -import { - getEnterpriseGitHubRepoSlug, - getEnterpriseGitHubRepoSlugForRemote, - isGitHubHostAuthenticated -} from './github-enterprise-repository' +import { shouldProbeGitRemote } from '../git/remote-name-listing' +import { ghRepoExecOptions, githubRepoContext, type LocalGitExecOptions } from './gh-utils' +import { isGitHubHostAuthenticated } from './github-enterprise-repository' import { githubHostExecOptions } from './github-repository-host' import { isValidGitHubApiRepository, type GitHubApiRepositoryResolution } from './github-api-repository-validation' import { - githubApiRepositoryProbeCacheKey, - resolveGitHubApiRepositoryProbe -} from './github-api-repository-probe' + _resetOriginGitHubApiRepositoryCache, + getGitHubApiRepositoryForRemote, + getOriginGitHubApiRepository +} from './github-api-repository-remote-probe' export { githubHostExecOptions, @@ -32,128 +24,18 @@ export { githubRepositoryWebHost } from './github-repository-host' export type GitHubApiRepository = GitHubOwnerRepo -export type GitHubRepoExecOptions = ReturnType & { host?: string } +export type GitHubRepoExecOptions = ReturnType & { + host?: string + env?: NodeJS.ProcessEnv +} export type GitHubRepoExecution = { ownerRepo: GitHubApiRepository | null ghOptions: GitHubRepoExecOptions } - -// Why: cache the uncached Enterprise remote probe used by hot paths. -const ORIGIN_REPO_CACHE_TTL_MS = 30_000 -const ORIGIN_REPO_CACHE_MAX_ENTRIES = 512 -const originRepoCache = new Map() -const originRepoInFlight = new Map>() - -/** @internal - exposed for tests only */ -export function _resetOriginGitHubApiRepositoryCache(): void { - originRepoCache.clear() - originRepoInFlight.clear() -} - -function pruneOriginRepoCache(now: number): void { - for (const [key, entry] of originRepoCache) { - if (entry.expiresAt <= now) { - originRepoCache.delete(key) - } - } - while (originRepoCache.size > ORIGIN_REPO_CACHE_MAX_ENTRIES) { - const oldestKey = originRepoCache.keys().next().value - if (oldestKey === undefined) { - return - } - originRepoCache.delete(oldestKey) - } -} - -/** - * Host-qualified repository identity for one remote: github.com remotes come - * from the cached slug parser; any other GitHub-shaped host is auth-gated so a - * non-GitHub forge never routes to the GitHub provider. - */ -export async function getGitHubApiRepositoryForRemote( - repoPath: string, - remoteName: string, - connectionId?: string | null, - localGitOptions: LocalGitExecOptions = {}, - probeOptions: GitHubRemoteIdentityProbeOptions = {} -): Promise { - // Why: generic PR resolution prefers upstream, but this API represents the - // caller-selected remote exactly (#7331). - const requireVerifiedSshProbe = probeOptions.requireVerifiedSshProbe === true - const verifiedIdentityArgs = requireVerifiedSshProbe ? ([probeOptions] as const) : [] - const ownerRepo = await getOwnerRepoForRemote( - repoPath, - remoteName, - connectionId, - localGitOptions, - ...verifiedIdentityArgs - ) - if (ownerRepo) { - return { ...ownerRepo, host: 'github.com' } - } - const cacheKey = githubApiRepositoryProbeCacheKey( - repoPath, - remoteName, - connectionId, - localGitOptions, - requireVerifiedSshProbe - ) - const now = Date.now() - pruneOriginRepoCache(now) - const cached = originRepoCache.get(cacheKey) - if (cached && cached.expiresAt > now) { - return cached.value - } - const inFlight = originRepoInFlight.get(cacheKey) - if (inFlight) { - return inFlight - } - const probe = (async () => { - const enterpriseOptions = - Object.keys(localGitOptions).length > 0 ? { localGitExecOptions: localGitOptions } : {} - const verifiedEnterpriseArgs = requireVerifiedSshProbe ? ([true] as const) : [] - const slug = - remoteName === 'origin' - ? await getEnterpriseGitHubRepoSlug( - repoPath, - connectionId, - enterpriseOptions, - ...verifiedEnterpriseArgs - ) - : await getEnterpriseGitHubRepoSlugForRemote( - repoPath, - remoteName, - connectionId, - enterpriseOptions, - ...verifiedEnterpriseArgs - ) - // Why: undefined means the gh auth inventory could not be read. Caching it - // as a negative would turn a transient spawn failure into a 30-second miss. - if (slug !== undefined) { - originRepoCache.set(cacheKey, { - value: slug, - expiresAt: Date.now() + ORIGIN_REPO_CACHE_TTL_MS - }) - pruneOriginRepoCache(Date.now()) - } - return resolveGitHubApiRepositoryProbe(slug, requireVerifiedSshProbe) - })() - originRepoInFlight.set(cacheKey, probe) - try { - return await probe - } finally { - if (originRepoInFlight.get(cacheKey) === probe) { - originRepoInFlight.delete(cacheKey) - } - } -} - -export async function getOriginGitHubApiRepository( - repoPath: string, - connectionId?: string | null, - localGitOptions: LocalGitExecOptions = {} -): Promise { - return getGitHubApiRepositoryForRemote(repoPath, 'origin', connectionId, localGitOptions) +export { + _resetOriginGitHubApiRepositoryCache, + getGitHubApiRepositoryForRemote, + getOriginGitHubApiRepository } /** Hosted mirror of getIssueOwnerRepo: issues prefer `upstream` over `origin`. */ @@ -162,16 +44,26 @@ export async function getIssueGitHubApiRepository( connectionId?: string | null, localGitOptions: LocalGitExecOptions = {} ): Promise { - const upstream = await getGitHubApiRepositoryForRemote( + const originPromise = getGitHubApiRepositoryForRemote( repoPath, - 'upstream', + 'origin', connectionId, localGitOptions + ).then( + (value) => ({ status: 'fulfilled' as const, value }), + (reason: unknown) => ({ status: 'rejected' as const, reason }) ) + const upstream = (await shouldProbeGitRemote(repoPath, 'upstream', connectionId, localGitOptions)) + ? await getGitHubApiRepositoryForRemote(repoPath, 'upstream', connectionId, localGitOptions) + : null if (upstream) { return upstream } - return getGitHubApiRepositoryForRemote(repoPath, 'origin', connectionId, localGitOptions) + const origin = await originPromise + if (origin.status === 'rejected') { + throw origin.reason + } + return origin.value } export type GitHubApiRepositoryCandidates = { @@ -185,14 +77,36 @@ export async function resolveGitHubApiRepositoryCandidates( connectionId?: string | null, localGitOptions: LocalGitExecOptions = {} ): Promise { - const [upstream, origin] = await Promise.all([ - getGitHubApiRepositoryForRemote(repoPath, 'upstream', connectionId, localGitOptions, { + const originPromise = getGitHubApiRepositoryForRemote( + repoPath, + 'origin', + connectionId, + localGitOptions, + { requireVerifiedSshProbe: true - }), - getGitHubApiRepositoryForRemote(repoPath, 'origin', connectionId, localGitOptions, { - requireVerifiedSshProbe: true - }) + } + ).then( + (value) => ({ status: 'fulfilled' as const, value }), + (reason: unknown) => ({ status: 'rejected' as const, reason }) + ) + const probeUpstream = await shouldProbeGitRemote( + repoPath, + 'upstream', + connectionId, + localGitOptions + ) + const [upstream, originResult] = await Promise.all([ + probeUpstream + ? getGitHubApiRepositoryForRemote(repoPath, 'upstream', connectionId, localGitOptions, { + requireVerifiedSshProbe: true + }) + : null, + originPromise ]) + if (originResult.status === 'rejected') { + throw originResult.reason + } + const origin = originResult.value const seen = new Set() const candidates: GitHubApiRepository[] = [] for (const candidate of [upstream, origin]) { diff --git a/src/main/github/github-owner-repo-selection.ts b/src/main/github/github-owner-repo-selection.ts index 39cd0d2da0e..2e05613d0b8 100644 --- a/src/main/github/github-owner-repo-selection.ts +++ b/src/main/github/github-owner-repo-selection.ts @@ -1,5 +1,6 @@ import type { IssueSourcePreference } from '../../shared/repo-types' import { githubRepoIdentityKey } from '../../shared/github/repository-identity-key' +import { shouldProbeGitRemote } from '../git/remote-name-listing' import { getOwnerRepoForRemote, type LocalGitExecOptions, @@ -12,11 +13,19 @@ export async function getOwnerRepo( localGitOptions: LocalGitExecOptions = {} ): Promise { // Why: on a fork checkout PRs live on the upstream parent, not origin (#7331). - const upstream = await getOwnerRepoForRemote(repoPath, 'upstream', connectionId, localGitOptions) - if (upstream) { - return upstream + const originPromise = getOwnerRepoForRemote(repoPath, 'origin', connectionId, localGitOptions) + if (await shouldProbeGitRemote(repoPath, 'upstream', connectionId, localGitOptions)) { + const upstream = await getOwnerRepoForRemote( + repoPath, + 'upstream', + connectionId, + localGitOptions + ) + if (upstream) { + return upstream + } } - return getOwnerRepoForRemote(repoPath, 'origin', connectionId, localGitOptions) + return originPromise } export const getIssueOwnerRepo = getOwnerRepo @@ -31,9 +40,18 @@ export async function resolvePRRepositoryCandidates( connectionId?: string | null, localGitOptions: LocalGitExecOptions = {} ): Promise { + const originPromise = getOwnerRepoForRemote(repoPath, 'origin', connectionId, localGitOptions) + const probeUpstream = await shouldProbeGitRemote( + repoPath, + 'upstream', + connectionId, + localGitOptions + ) const [upstream, origin] = await Promise.all([ - getOwnerRepoForRemote(repoPath, 'upstream', connectionId, localGitOptions), - getOwnerRepoForRemote(repoPath, 'origin', connectionId, localGitOptions) + probeUpstream + ? getOwnerRepoForRemote(repoPath, 'upstream', connectionId, localGitOptions) + : null, + originPromise ]) const seen = new Set() const candidates: OwnerRepo[] = [] diff --git a/src/main/github/github-repository-identity.fork-owner-repo.test.ts b/src/main/github/github-repository-identity.fork-owner-repo.test.ts index 5461b838877..e0cd7de6ca4 100644 --- a/src/main/github/github-repository-identity.fork-owner-repo.test.ts +++ b/src/main/github/github-repository-identity.fork-owner-repo.test.ts @@ -28,6 +28,7 @@ vi.mock('./local-git-config-signature', () => ({ readLocalGitConfigSignature: readLocalGitConfigSignatureMock })) +import { _resetRemoteNameListingCache } from '../git/remote-name-listing' import { getOwnerRepoForRemote, _resetOwnerRepoCache } from './github-repository-identity' import { getOwnerRepo, getIssueOwnerRepo } from './github-owner-repo-selection' import { getRepoUpstream } from './client' @@ -53,13 +54,17 @@ const REMOTE_URLS_BY_REPO: Record> = { beforeEach(() => { _resetOwnerRepoCache() + _resetRemoteNameListingCache() gitExecFileAsyncMock.mockReset() ghExecFileAsyncMock.mockReset() gitExecFileAsyncMock.mockImplementation( async (args: string[], options: { cwd?: string } = {}) => { - // getRemoteUrlForRepo calls: ['remote', 'get-url', ] + const configured = REMOTE_URLS_BY_REPO[options.cwd ?? ''] ?? {} + if (args[0] === 'remote' && args[1] !== 'get-url') { + return { stdout: `${Object.keys(configured).join('\n')}\n` } + } const remoteName = args[2] - const url = REMOTE_URLS_BY_REPO[options.cwd ?? '']?.[remoteName] + const url = configured[remoteName] if (!url) { const err = new Error(`fatal: No such remote '${remoteName}'`) as Error & { code?: number } err.code = 128 @@ -92,16 +97,22 @@ describe('issue #7331: fork PR owner/repo resolution', () => { expect(prRepo).toEqual({ owner: 'stablyai', repo: 'orca' }) }) - it('caches the missing-upstream probe so repeat lookups skip the git spawn', async () => { + it('skips git remote get-url upstream on origin-only clones and caches the listing', async () => { await getOwnerRepo(NON_FORK_PATH) - const upstreamProbes = (): number => - gitExecFileAsyncMock.mock.calls.filter(([args]) => args[2] === 'upstream').length - expect(upstreamProbes()).toBe(1) + const upstreamGetUrl = (): number => + gitExecFileAsyncMock.mock.calls.filter( + ([args]) => args[1] === 'get-url' && args[2] === 'upstream' + ).length + const listCalls = (): number => + gitExecFileAsyncMock.mock.calls.filter( + ([args]) => args[0] === 'remote' && args[1] !== 'get-url' + ).length + expect(upstreamGetUrl()).toBe(0) + expect(listCalls()).toBe(1) await getOwnerRepo(NON_FORK_PATH) - // Second lookup within the negative-cache TTL must not respawn git for - // the missing upstream remote. - expect(upstreamProbes()).toBe(1) + expect(upstreamGetUrl()).toBe(0) + expect(listCalls()).toBe(1) }) it('resolves the upstream parent for SSH-style remote URLs', async () => { diff --git a/src/main/github/work-item-search-fallback-environment.test.ts b/src/main/github/work-item-search-fallback-environment.test.ts new file mode 100644 index 00000000000..9f57048d9f6 --- /dev/null +++ b/src/main/github/work-item-search-fallback-environment.test.ts @@ -0,0 +1,86 @@ +import { expect, it, vi } from 'vitest' +import { api, capture } from './work-item-search-test-harness' +import { listWorkItems } from './client/list/list-work-items' +import { countWorkItems } from './client/list/count-work-items' +import metadata from './__fixtures__/work-item-search-metadata.json' + +it('preserves the Search budget floor when the preferred count fails', async () => { + api.restSearches = 29 + api.aliasErrorRepo = 'fixture/repo' + + expect(await countWorkItems('fixture/repo', 'is:issue')).toBe(0) + expect(api.calls.some((call) => call.args.includes('graphql'))).toBe(true) + expect(api.calls.some((call) => call.args.some((arg) => arg.startsWith('search/issues?')))).toBe( + false + ) + expect(api.restSearches).toBe(29) +}) + +it('still counts through GraphQL when the REST Search budget is below its floor', async () => { + api.restSearches = 29 + + expect(await countWorkItems('fixture/repo', 'is:issue')).toBe(120) + expect(api.restSearches).toBe(29) +}) + +it('keeps REST fallback on the credential captured for the failed preferred search', async () => { + vi.stubEnv('GH_TOKEN', 'fixture-original-credential') + api.aliasErrorRepo = 'fixture/repo' + capture.mockImplementation(async (binary, args, options) => { + if (args.includes('graphql')) { + vi.stubEnv('GH_TOKEN', 'fixture-later-credential') + } + return api.capture(binary, args, options) + }) + expect((await listWorkItems('fixture/repo', 24, 'is:issue')).items).toHaveLength(24) + const queries = api.calls.filter( + (call) => + call.args.includes('graphql') || call.args.some((arg) => arg.startsWith('search/issues?')) + ) + expect(queries.map((call) => call.fixtureCredential)).toEqual([ + 'fixture-original-credential', + 'fixture-original-credential' + ]) +}) + +it('keeps count fallback on its captured credential', async () => { + vi.stubEnv('GH_TOKEN', 'fixture-original-credential') + api.aliasErrorRepo = 'fixture/repo' + capture.mockImplementation(async (binary, args, options) => { + if (args.includes('graphql')) { + vi.stubEnv('GH_TOKEN', 'fixture-later-credential') + } + return api.capture(binary, args, options) + }) + expect(await countWorkItems('fixture/repo', 'is:issue')).toBe(120) + const queries = api.calls.filter( + (call) => + call.args.includes('graphql') || call.args.some((arg) => arg.startsWith('search/issues?')) + ) + expect(queries.map((call) => call.fixtureCredential)).toEqual([ + 'fixture-original-credential', + 'fixture-original-credential' + ]) +}) + +it('hydrates oversized associations with the preferred page credential', async () => { + vi.stubEnv('GH_TOKEN', 'fixture-original-credential') + const row = structuredClone(metadata[0].graphql) + api.specialNodes = [{ ...row, labels: { ...row.labels, pageInfo: { hasNextPage: true } } }] + capture.mockImplementation(async (binary, args, options) => { + if (args.includes('graphql')) { + vi.stubEnv('GH_TOKEN', 'fixture-later-credential') + } + return api.capture(binary, args, options) + }) + const result = await listWorkItems('fixture/repo', 24, 'is:issue') + expect(result.items[0].labels).toHaveLength(125) + const queries = api.calls.filter( + (call) => + call.args.includes('graphql') || call.args.some((arg) => /^repos\/.+\/issues\/\d+$/.test(arg)) + ) + expect(queries.map((call) => call.fixtureCredential)).toEqual([ + 'fixture-original-credential', + 'fixture-original-credential' + ]) +}) diff --git a/src/main/github/work-item-search-freshness.test.ts b/src/main/github/work-item-search-freshness.test.ts new file mode 100644 index 00000000000..bbc59bc471e --- /dev/null +++ b/src/main/github/work-item-search-freshness.test.ts @@ -0,0 +1,32 @@ +import { expect, it, vi } from 'vitest' +import { api, capture } from './work-item-search-test-harness' +import { searchWorkItemCount } from './client/list/work-item-search-page' + +it('does not renew a gh-cached response after bounded response-cache eviction', async () => { + const ghCache = new Map< + string, + { expires: number; response: { stdout: string; stderr: string } } + >() + capture.mockImplementation(async (binary, args, options) => { + const key = JSON.stringify([options.cwd, options.env?.GH_TOKEN, args]) + const cached = args.includes('--cache') ? ghCache.get(key) : undefined + if (cached && cached.expires > Date.now()) { + return cached.response + } + const response = await api.capture(binary, args, options) + if (args.includes('--cache')) { + ghCache.set(key, { expires: Date.now() + 120000, response }) + } + return response + }) + const search = 'repo:fixture/first is:issue' + expect(await searchWorkItemCount(search, {})).toBe(120) + for (let index = 0; index < 512; index++) { + await searchWorkItemCount(`repo:fixture/evict-${index} is:issue`, {}) + } + api.reportedCount = 121 + vi.setSystemTime(119000) + await searchWorkItemCount(search, {}) + vi.setSystemTime(120001) + expect(await searchWorkItemCount(search, {})).toBe(121) +}) diff --git a/src/main/github/work-item-search-isolation.test.ts b/src/main/github/work-item-search-isolation.test.ts new file mode 100644 index 00000000000..de11bdacc2e --- /dev/null +++ b/src/main/github/work-item-search-isolation.test.ts @@ -0,0 +1,140 @@ +import { expect, it, vi } from 'vitest' +import { api, sourceContext } from './work-item-search-test-harness' +import { listWorkItems } from './client/list/list-work-items' +import { countWorkItems } from './client/list/count-work-items' +import { searchWorkItemCount, usesGraphqlWorkItemSearch } from './client/list/work-item-search-page' +import { recordGhPrimaryRateLimit, ghRateLimitScopeKey } from '../git/gh-rate-limit-breaker' + +it('coalesces matching searches and batches independent queries in one execution context', async () => { + const queries = Array.from({ length: 25 }, (_, i) => `repo:fixture/repo-${i} is:issue`) + const counts = await Promise.all( + queries.flatMap((search) => [searchWorkItemCount(search, {}), searchWorkItemCount(search, {})]) + ) + expect(counts).toEqual(Array(50).fill(120)) + expect(api.graphqlCalls).toBe(3) + expect(api.graphqlFields).toBe(25) + expect(api.calls.every((call) => call.cwd === undefined)).toBe(true) +}) + +it('isolates native cwd, WSL distro, host, admission context and inherited credentials', async () => { + const search = 'repo:fixture/repo is:issue' + const options = [ + { cwd: 'folder-a' }, + { cwd: 'folder-b' }, + { wslDistro: 'Ubuntu' }, + { wslDistro: 'Debian' }, + { host: 'github.example.com' }, + { admissionTier: 'interactive' as const } + ] + await Promise.all(options.map((option) => searchWorkItemCount(search, option))) + expect(api.graphqlCalls).toBe(options.length) + await searchWorkItemCount(search, { cwd: 'folder-a' }) + expect(api.graphqlCalls).toBe(options.length) + vi.stubEnv('GH_TOKEN', 'fixture-rotated-credential') + await searchWorkItemCount(search, { cwd: 'folder-a' }) + expect(api.graphqlCalls).toBe(options.length + 1) + expect(api.calls.some((call) => call.args.includes('github.example.com'))).toBe(true) +}) + +it('keeps SSH GitHub execution client-side without passing remote cwd', async () => { + const results = await Promise.all( + Array.from({ length: 8 }, (_, i) => + listWorkItems(`/remote/repo-${i}`, 24, 'is:issue', 1, undefined, `ssh-${i}`) + ) + ) + expect(results.every((result) => result.items.length === 24)).toBe(true) + expect(api.graphqlCalls).toBe(2) + expect(api.calls.every((call) => call.cwd === undefined)).toBe(true) +}) + +it('leaves GHES on REST and unresolved/non-GitHub sources empty', async () => { + sourceContext.host = 'github.example.com' + expect((await listWorkItems('fixture/repo', 24, 'is:issue')).items).toHaveLength(24) + expect(await countWorkItems('fixture/repo', 'is:issue')).toBe(120) + expect(api.graphqlCalls).toBe(0) + expect(api.restSearches).toBe(2) + expect( + api.calls + .filter((call) => !call.args.includes('rate_limit')) + .every((call) => call.args.includes('github.example.com')) + ).toBe(true) + expect( + usesGraphqlWorkItemSearch({ owner: 'fixture', repo: 'repo', host: 'gitlab.com' }, {}) + ).toBe(false) + sourceContext.available = false + expect((await listWorkItems('folder/without-git', 24, 'is:issue')).items).toEqual([]) + expect(await countWorkItems('folder/without-git')).toBe(0) + await expect( + listWorkItems('/remote/unresolved', 24, 'is:issue', 1, undefined, 'ssh') + ).rejects.toThrow() + expect(api.restSearches).toBe(2) +}) + +it('preserves successful aliases when one repository needs REST fallback', async () => { + api.aliasErrorRepo = 'fixture/repo-1' + const results = await Promise.all( + Array.from({ length: 4 }, (_, i) => + listWorkItems(`/remote/repo-${i}`, 24, 'is:issue', 1, undefined, 'ssh') + ) + ) + expect(results.every((result) => result.items.length === 24 && !result.errors)).toBe(true) + expect(api.graphqlCalls).toBe(1) + expect(api.restSearches).toBe(1) + expect( + api.calls + .find((call) => call.args.some((arg) => arg.startsWith('search/issues?'))) + ?.args.join(' ') + ).toContain('repo%3Afixture%2Frepo-1') +}) + +it('falls back on GraphQL quota exhaustion and respects independent runner breaker scopes', async () => { + recordGhPrimaryRateLimit('graphql', 3600000, ghRateLimitScopeKey('native', 'github.com')) + expect((await listWorkItems('fixture/repo', 24, 'is:issue')).items).toHaveLength(24) + expect(api.graphqlCalls).toBe(0) + expect(api.restSearches).toBe(1) + expect( + ( + await listWorkItems('fixture/repo', 24, 'is:issue', 1, undefined, undefined, false, { + wslDistro: 'Ubuntu' + }) + ).items + ).toHaveLength(24) + expect(api.graphqlCalls).toBe(1) + expect(api.restSearches).toBe(1) +}) + +it('keeps count/list search usable when REST Search is exhausted and reports both-bucket failures', async () => { + api.searchAvailable = false + expect(await countWorkItems('fixture/repo', 'is:issue')).toBe(120) + expect((await listWorkItems('fixture/repo', 24, 'is:issue')).items).toHaveLength(24) + expect(api.restSearches).toBe(0) + api.graphqlAvailable = false + await expect( + listWorkItems('fixture/repo', 24, 'is:issue', 1, undefined, undefined, true) + ).rejects.toThrow(/rate limit exceeded/) +}) + +it('splits long search predicates within Windows command-line headroom', async () => { + const queries = Array.from( + { length: 4 }, + (_, index) => `repo:fixture/repo-${index} is:issue ${'word '.repeat(1400)}` + ) + expect(await Promise.all(queries.map((query) => searchWorkItemCount(query, {})))).toEqual([ + 120, 120, 120, 120 + ]) + expect(api.graphqlCalls).toBe(4) + expect(api.calls.every((call) => call.args.join(' ').length < 12000)).toBe(true) +}) + +it('executes queued requests with the credential environment captured at enqueue time', async () => { + vi.stubEnv('GH_TOKEN', 'fixture-first-credential') + const first = searchWorkItemCount('repo:fixture/repo is:issue', {}) + vi.stubEnv('GH_TOKEN', 'fixture-second-credential') + const second = searchWorkItemCount('repo:fixture/repo is:issue', {}) + expect(await Promise.all([first, second])).toEqual([120, 120]) + expect(api.graphqlCalls).toBe(2) + expect(api.calls.map((call) => call.fixtureCredential)).toEqual([ + 'fixture-first-credential', + 'fixture-second-credential' + ]) +}) diff --git a/src/main/github/work-item-search-pagination.test.ts b/src/main/github/work-item-search-pagination.test.ts new file mode 100644 index 00000000000..5e07878e5e6 --- /dev/null +++ b/src/main/github/work-item-search-pagination.test.ts @@ -0,0 +1,71 @@ +import { expect, it, vi } from 'vitest' +import { api } from './work-item-search-test-harness' +import { listWorkItems } from './client/list/list-work-items' +import { countWorkItems } from './client/list/count-work-items' + +function issuePage(page: number, noCache = false, limit = 24) { + return listWorkItems( + 'fixture/repo', + limit, + 'is:issue is:open', + page, + undefined, + undefined, + noCache + ) +} + +it('restores a cold numbered page using only API-issued opaque cursors', async () => { + const third = await issuePage(3) + expect(third.items.map((item) => item.number)).toEqual( + Array.from({ length: 24 }, (_, i) => 9952 - i) + ) + expect(api.graphqlCalls).toBe(2) + expect(api.calls[0].args.join(' ')).not.toContain(' nodes {') + expect(api.calls[1].args.join(' ')).toContain('after: "opaque:1:cursor"') + expect((await issuePage(4)).items[0].number).toBe(9928) + expect(api.graphqlCalls).toBe(3) + expect((await issuePage(6)).items).toEqual([]) + expect(api.restSearches).toBe(0) +}) + +it('walks long jumps without node hydration and retains the authoritative 1000-result window', async () => { + api.rowsPerRepo = 1400 + const last = await issuePage(10, false, 100) + expect(last.items).toHaveLength(100) + expect(last.items[0].number).toBe(9100) + expect(api.graphqlCalls).toBe(10) + expect(api.calls.filter((call) => call.args.join(' ').includes(' nodes {'))).toHaveLength(1) + expect(await countWorkItems('fixture/repo', 'is:issue is:open')).toBe(1400) + const outside = await issuePage(11, false, 100) + expect(outside.items).toEqual([]) + expect(outside.errors?.issues).toMatchObject({ + type: 'validation_error', + message: 'Invalid request — Only the first 1000 search results are available (HTTP 422)' + }) + expect(api.restSearches).toBe(1) +}) + +it('bypasses both page and cursor caches on refresh and expires retained entries', async () => { + await issuePage(3) + expect(api.graphqlCalls).toBe(2) + await issuePage(3) + expect(api.graphqlCalls).toBe(2) + await issuePage(3, true) + expect(api.graphqlCalls).toBe(4) + expect(api.calls.slice(-2).every((call) => !call.args.includes('--cache'))).toBe(true) + vi.setSystemTime(120001) + await issuePage(3) + expect(api.graphqlCalls).toBe(6) + expect(api.restSearches).toBe(0) +}) + +it('does not renew cursor freshness when re-reading a cached page', async () => { + await issuePage(1) + vi.setSystemTime(119000) + await issuePage(1) + vi.setSystemTime(120001) + await issuePage(2) + expect(api.graphqlCalls).toBe(3) + expect(api.calls[1].args.join(' ')).not.toContain('after:') +}) diff --git a/src/main/github/work-item-search-semantics.test.ts b/src/main/github/work-item-search-semantics.test.ts new file mode 100644 index 00000000000..e5df22cddd3 --- /dev/null +++ b/src/main/github/work-item-search-semantics.test.ts @@ -0,0 +1,114 @@ +import { expect, it } from 'vitest' +import { api } from './work-item-search-test-harness' +import { listWorkItems } from './client/list/list-work-items' +import { countWorkItems } from './client/list/count-work-items' +import { mapIssueWorkItem } from './client/map/work-item' +import metadata from './__fixtures__/work-item-search-metadata.json' + +it('matches the saved REST projection for users, bots, avatars, assignees and labels', async () => { + api.specialNodes = metadata.map((pair) => pair.graphql) + api.reportedCount = 2748 + const result = await listWorkItems('fixture/repo', 5, 'is:issue') + expect(result.items).toEqual(metadata.map((pair) => mapIssueWorkItem(pair.rest))) + expect(await countWorkItems('fixture/repo', 'is:issue')).toBe(2748) + expect(api.restSearches).toBe(0) +}) + +it('preserves deleted authors and hydrates associations beyond GraphQL connection limits', async () => { + const row = structuredClone(metadata[0].graphql) + api.specialNodes = [ + { ...row, author: null, labels: { ...row.labels, pageInfo: { hasNextPage: true } } } + ] + const result = await listWorkItems('fixture/repo', 24, 'is:issue') + expect(result.items).toHaveLength(1) + expect(result.items[0].author).toBeNull() + expect(result.items[0].labels).toEqual( + Array.from({ length: 125 }, (_, index) => `label-${index}`) + ) + expect(api.restDetails).toBe(1) + expect(api.restSearches).toBe(0) +}) + +it('passes every issue predicate to the server for both results and full counts', async () => { + api.expectedSearch = + 'repo:fixture/repo is:issue is:closed assignee:"some user" author:"some author" label:"needs review" label:bug in:"title,body" "needle phrase"' + api.specialNodes = [ + { ...metadata[0].graphql, number: 7, state: 'CLOSED', title: 'old needle phrase' } + ] + const query = + 'is:issue is:closed assignee:"some user" author:"some author" label:"needs review" label:bug in:"title,body" "needle phrase"' + expect((await listWorkItems('fixture/repo', 24, query)).items).toMatchObject([ + { number: 7, state: 'closed', title: 'old needle phrase' } + ]) + expect(await countWorkItems('fixture/repo', query)).toBe(1) + expect(api.restSearches).toBe(0) +}) + +it.each([ + ['is:issue state:all', 'repo:fixture/repo is:issue'], + ['is:issue is:open label:bug', 'repo:fixture/repo is:issue is:open label:bug'] +])('retains state/scope semantics for %s', async (query, expected) => { + api.expectedSearch = expected + expect((await listWorkItems('fixture/repo', 24, query)).items).toHaveLength(24) + expect(await countWorkItems('fixture/repo', query)).toBe(120) + expect(api.restSearches).toBe(0) +}) + +it.each([ + [ + 'is:draft', + 'is:pr is:open draft:true sort:created-desc', + 'repo:fixture/repo is:pull-request is:open draft:true' + ], + [ + 'is:pr is:closed', + 'is:pr is:closed -is:merged sort:created-desc', + 'repo:fixture/repo is:pull-request is:closed -is:merged' + ], + ['is:merged', 'is:pr is:merged sort:created-desc', 'repo:fixture/repo is:pull-request is:merged'], + [ + 'review-requested:"some user" reviewed-by:someone', + 'is:pr review-requested:"some user" reviewed-by:someone sort:created-desc', + 'repo:fixture/repo is:pull-request review-requested:"some user" reviewed-by:someone' + ] +])('keeps rich PR lists and full count predicates for %s', async (query, prSearch, countSearch) => { + expect((await listWorkItems('fixture/repo', 24, query)).items).toEqual([]) + expect(api.graphqlCalls).toBe(0) + expect(api.restSearches).toBe(0) + expect(api.calls[0].args).toContain(prSearch) + expect(api.calls[0].args).toContain('--json') + api.expectedSearch = countSearch + expect(await countWorkItems('fixture/repo', query)).toBe(120) + expect(api.graphqlCalls).toBe(1) +}) + +it('falls back with the original numbered query when GraphQL is unavailable', async () => { + api.graphqlAvailable = false + api.expectedSearch = 'repo:fixture/repo is:issue is:closed label:"needs review" "exact phrase"' + const result = await listWorkItems( + 'fixture/repo', + 24, + 'is:issue is:closed label:"needs review" "exact phrase"', + 3, + undefined, + undefined, + true + ) + expect(result.items[0].number).toBe(9952) + const call = api.calls.find((call) => call.args.some((arg) => arg.startsWith('search/issues?'))) + expect(call?.args).toEqual([ + 'api', + '--hostname', + 'github.com', + `search/issues?q=${encodeURIComponent(api.expectedSearch)}&sort=created&order=desc&per_page=24&page=3`, + '--jq', + '.items' + ]) +}) + +it('falls back for malformed GraphQL rows instead of presenting a truncated result', async () => { + api.specialNodes = [{ ...metadata[0].graphql, __typename: 'PullRequest' }] + const result = await listWorkItems('fixture/repo', 24, 'is:issue') + expect(result.items).toHaveLength(1) + expect(api.restSearches).toBe(1) +}) diff --git a/src/main/github/work-item-search-test-harness.ts b/src/main/github/work-item-search-test-harness.ts new file mode 100644 index 00000000000..d3783f0afe1 --- /dev/null +++ b/src/main/github/work-item-search-test-harness.ts @@ -0,0 +1,78 @@ +import { afterEach, beforeEach, vi } from 'vitest' +import type { Mock } from 'vitest' +import { randomUUID } from 'node:crypto' +import { basename } from 'node:path' +import type * as GithubApiRepositoryModule from './github-api-repository' +import { WorkItemSearchApi } from './__fixtures__/work-item-search-api' + +const { + capture, + sourceContext +}: { + capture: Mock + sourceContext: { host: string; available: boolean } +} = vi.hoisted(() => ({ + capture: vi.fn(), + sourceContext: { host: 'github.com', available: true } +})) +vi.mock('../git/command-runner/exec-file-capture', () => ({ + execFileCaptureToTermination: capture +})) +vi.mock('../git/command-runner/wsl-command-resolution', () => ({ + resolveCommand: (binary: string, args: string[], cwd?: string, distro?: string) => ({ + binary, + args, + cwd, + wsl: distro ? { distro } : null, + wslMode: null + }), + resolveDefaultWslCli: () => null +})) +vi.mock('../git/runner', async () => ({ + ghExecFileAsync: (await import('../git/command-runner/gh-exec-file')).ghExecFileAsync, + gitExecFileAsync: vi.fn() +})) +vi.mock('./github-api-repository', async (importOriginal) => { + const actual = await importOriginal() + const source = (repoPath: string) => + sourceContext.available + ? { owner: 'fixture', repo: basename(repoPath), host: sourceContext.host } + : null + return { + ...actual, + resolveIssueGitHubApiRepositorySource: async (repoPath: string) => ({ + source: source(repoPath), + fellBack: false + }), + getOriginGitHubApiRepository: async (repoPath: string) => source(repoPath), + getGitHubApiRepositoryForRemote: async () => null + } +}) + +import { _resetRateLimitCache } from './rate-limit' +import { clearGhRateLimitBlock, ghRateLimitScopeKey } from '../git/gh-rate-limit-breaker' +export let api: WorkItemSearchApi +beforeEach(() => { + vi.useFakeTimers({ toFake: ['Date'] }) + vi.setSystemTime(0) + vi.stubEnv('GH_HOST', 'github.com') + vi.stubEnv('ORCA_WORK_ITEM_SEARCH_FIXTURE', randomUUID()) + _resetRateLimitCache() + for (const runtime of ['native', 'wsl:ubuntu', 'wsl:debian']) { + for (const host of ['github.com', 'github.example.com']) { + for (const bucket of ['core', 'graphql', 'search'] as const) { + clearGhRateLimitBlock(bucket, ghRateLimitScopeKey(runtime, host)) + } + } + } + sourceContext.host = 'github.com' + sourceContext.available = true + api = new WorkItemSearchApi() + capture.mockReset().mockImplementation(api.capture.bind(api)) +}) +afterEach(() => { + vi.useRealTimers() + vi.unstubAllEnvs() +}) + +export { capture, sourceContext } diff --git a/src/main/gitlab/gitlab-project-ref-resolution.ts b/src/main/gitlab/gitlab-project-ref-resolution.ts index b64e8c3f44c..c337c01ae89 100644 --- a/src/main/gitlab/gitlab-project-ref-resolution.ts +++ b/src/main/gitlab/gitlab-project-ref-resolution.ts @@ -1,5 +1,6 @@ import { glabExecFileAsync } from '../git/runner' import type { GitAdmissionTier } from '../git/command-runner/git-exec-options' +import { shouldProbeGitRemote } from '../git/remote-name-listing' import { isTransientGitProbeError, readRemoteUrl } from '../git/remote-url-probe' import { NEGATIVE_ENTRY_TTL_MS } from '../git/remote-ref-probe-cache' import { getSshGitProviderGeneration } from '../providers/ssh-git-dispatch' @@ -180,17 +181,26 @@ export async function getIssueProjectRef( connectionId?: string | null, localGitOptions: LocalGitExecOptions = {} ): Promise { - const upstream = await getProjectRefForRemote( + const originPromise = getProjectRefForRemote( repoPath, - 'upstream', + 'origin', knownHosts, connectionId, localGitOptions ) - return ( - upstream ?? - getProjectRefForRemote(repoPath, 'origin', knownHosts, connectionId, localGitOptions) - ) + if (await shouldProbeGitRemote(repoPath, 'upstream', connectionId, localGitOptions)) { + const upstream = await getProjectRefForRemote( + repoPath, + 'upstream', + knownHosts, + connectionId, + localGitOptions + ) + if (upstream) { + return upstream + } + } + return originPromise } export type ResolvedIssueSource = { diff --git a/src/main/gitlab/gl-utils.test.ts b/src/main/gitlab/gl-utils.test.ts index 9e69b9e75cf..8222a1f919e 100644 --- a/src/main/gitlab/gl-utils.test.ts +++ b/src/main/gitlab/gl-utils.test.ts @@ -33,9 +33,39 @@ import { } from './gl-utils' import { GlabNonListResponseError } from './glab-api-response' import { registerSshGitProvider, unregisterSshGitProvider } from '../providers/ssh-git-dispatch' +import { _resetRemoteNameListingCache } from '../git/remote-name-listing' import { REMOTE_URL_PROBE_TIMEOUT_MS } from '../git/remote-url-probe' import { NEGATIVE_ENTRY_TTL_MS } from '../git/remote-ref-probe-cache' +function mockGitRemoteCommands(remotes: Record): void { + gitExecFileAsyncMock.mockImplementation(async (args: string[]) => { + if (args[0] === 'remote' && args[1] !== 'get-url') { + return { stdout: `${Object.keys(remotes).join('\n')}\n` } + } + if (args[0] === 'remote' && args[1] === 'get-url') { + const url = remotes[args[2] ?? ''] + if (!url) { + throw new Error(`fatal: No such remote '${args[2]}'`) + } + return { stdout: url } + } + throw new Error(`unexpected git ${args.join(' ')}`) + }) +} + +function gitRemoteGetUrlCalls(remoteName: string): unknown[][] { + return gitExecFileAsyncMock.mock.calls.filter( + ([args]) => + Array.isArray(args) && args[0] === 'remote' && args[1] === 'get-url' && args[2] === remoteName + ) +} + +function gitRemoteListCalls(): unknown[][] { + return gitExecFileAsyncMock.mock.calls.filter( + ([args]) => Array.isArray(args) && args[0] === 'remote' && args[1] !== 'get-url' + ) +} + describe('gitlab project ref resolution', () => { beforeEach(() => { gitExecFileAsyncMock.mockReset() @@ -43,6 +73,7 @@ describe('gitlab project ref resolution', () => { sshExecMock.mockReset() unregisterSshGitProvider('conn-1') _resetProjectRefCache() + _resetRemoteNameListingCache() }) afterEach(() => { @@ -66,35 +97,53 @@ describe('gitlab project ref resolution', () => { }) it('prefers upstream for issue project ref resolution', async () => { - gitExecFileAsyncMock.mockResolvedValueOnce({ - stdout: 'git@gitlab.com:stablyai/orca.git\n' + mockGitRemoteCommands({ + origin: 'git@gitlab.com:fork/orca.git\n', + upstream: 'git@gitlab.com:stablyai/orca.git\n' }) await expect(getIssueProjectRef('/repo')).resolves.toEqual({ host: 'gitlab.com', path: 'stablyai/orca' }) - expect(gitExecFileAsyncMock).toHaveBeenCalledWith(['remote', 'get-url', 'upstream'], { - cwd: '/repo', - timeout: REMOTE_URL_PROBE_TIMEOUT_MS - }) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(1) }) - it('falls back to origin when upstream is missing or non-GitLab', async () => { - gitExecFileAsyncMock - .mockResolvedValueOnce({ stdout: 'git@example.com:stablyai/orca.git\n' }) - .mockResolvedValueOnce({ stdout: 'git@gitlab.com:fork/orca.git\n' }) + it('does not spawn git remote get-url upstream on an origin-only clone', async () => { + mockGitRemoteCommands({ origin: 'git@gitlab.com:fork/orca.git\n' }) await expect(getIssueProjectRef('/repo')).resolves.toEqual({ host: 'gitlab.com', path: 'fork/orca' }) + await expect(getIssueProjectRef('/repo')).resolves.toEqual({ + host: 'gitlab.com', + path: 'fork/orca' + }) + expect(gitRemoteListCalls()).toHaveLength(1) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(0) + expect(gitRemoteGetUrlCalls('origin')).toHaveLength(1) + }) + + it('falls back to origin when upstream is present but non-GitLab', async () => { + mockGitRemoteCommands({ + origin: 'git@gitlab.com:fork/orca.git\n', + upstream: 'git@example.com:stablyai/orca.git\n' + }) + + await expect(getIssueProjectRef('/repo')).resolves.toEqual({ + host: 'gitlab.com', + path: 'fork/orca' + }) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(1) + expect(gitRemoteGetUrlCalls('origin')).toHaveLength(1) }) it('does not mix origin and upstream cache entries for the same repo path', async () => { - gitExecFileAsyncMock - .mockResolvedValueOnce({ stdout: 'git@gitlab.com:fork/orca.git\n' }) - .mockResolvedValueOnce({ stdout: 'git@gitlab.com:stablyai/orca.git\n' }) + mockGitRemoteCommands({ + origin: 'git@gitlab.com:fork/orca.git\n', + upstream: 'git@gitlab.com:stablyai/orca.git\n' + }) await expect(getProjectRef('/repo')).resolves.toEqual({ host: 'gitlab.com', @@ -355,23 +404,27 @@ describe('resolveIssueSource', () => { beforeEach(() => { gitExecFileAsyncMock.mockReset() _resetProjectRefCache() + _resetRemoteNameListingCache() }) it("'auto' + upstream exists → upstream, fellBack=false", async () => { - gitExecFileAsyncMock.mockResolvedValueOnce({ - stdout: 'git@gitlab.com:stablyai/orca.git\n' + mockGitRemoteCommands({ + origin: 'git@gitlab.com:fork/orca.git\n', + upstream: 'git@gitlab.com:stablyai/orca.git\n' }) await expect(resolveIssueSource('/repo', 'auto')).resolves.toEqual({ source: { host: 'gitlab.com', path: 'stablyai/orca' }, fellBack: false }) + expect(gitRemoteGetUrlCalls('upstream')).toHaveLength(1) }) - it("'auto' + no upstream → origin, fellBack=false", async () => { - gitExecFileAsyncMock - .mockResolvedValueOnce({ stdout: 'git@example.com:stablyai/orca.git\n' }) - .mockResolvedValueOnce({ stdout: 'git@gitlab.com:solo/orca.git\n' }) + it("'auto' + no gitlab upstream → origin, fellBack=false", async () => { + mockGitRemoteCommands({ + origin: 'git@gitlab.com:solo/orca.git\n', + upstream: 'git@example.com:stablyai/orca.git\n' + }) await expect(resolveIssueSource('/repo', 'auto')).resolves.toEqual({ source: { host: 'gitlab.com', path: 'solo/orca' }, @@ -407,8 +460,9 @@ describe('resolveIssueSource', () => { }) it('undefined preference is treated identically to auto', async () => { - gitExecFileAsyncMock.mockResolvedValueOnce({ - stdout: 'git@gitlab.com:stablyai/orca.git\n' + mockGitRemoteCommands({ + origin: 'git@gitlab.com:fork/orca.git\n', + upstream: 'git@gitlab.com:stablyai/orca.git\n' }) await expect(resolveIssueSource('/repo', undefined)).resolves.toEqual({ diff --git a/src/main/grok/grok-hook-config.ts b/src/main/grok/grok-hook-config.ts index 52ee2ecfdb2..5482ba0accd 100644 --- a/src/main/grok/grok-hook-config.ts +++ b/src/main/grok/grok-hook-config.ts @@ -12,6 +12,7 @@ export const GROK_EVENTS = [ { eventName: 'SessionStart', definition: { hooks: [{ type: 'command', command: '' }] } }, { eventName: 'UserPromptSubmit', definition: { hooks: [{ type: 'command', command: '' }] } }, { eventName: 'Stop', definition: { hooks: [{ type: 'command', command: '' }] } }, + { eventName: 'StopCancelled', definition: { hooks: [{ type: 'command', command: '' }] } }, { eventName: 'StopFailure', definition: { hooks: [{ type: 'command', command: '' }] } }, { eventName: 'SessionEnd', definition: { hooks: [{ type: 'command', command: '' }] } }, { diff --git a/src/main/grok/hook-service.test.ts b/src/main/grok/hook-service.test.ts index 251ae64fa33..620966bd6ae 100644 --- a/src/main/grok/hook-service.test.ts +++ b/src/main/grok/hook-service.test.ts @@ -251,6 +251,7 @@ describe('GrokHookService', () => { 'SessionEnd', 'SessionStart', 'Stop', + 'StopCancelled', 'StopFailure', 'UserPromptSubmit' ].sort() @@ -262,7 +263,8 @@ describe('GrokHookService', () => { // Why: Grok matchers are real regexes; bare `*` does not match-all. expect(config.hooks.PostToolUseFailure[0].matcher).toBe('.*') expect(config.hooks.PostToolUse[0].matcher).toBe('.*') - // Why: StopFailure must not carry a tool matcher — lifecycle-only event. + // Why: cancellation/failure are lifecycle-only events and must not inherit a tool matcher. + expect(config.hooks.StopCancelled[0].matcher).toBeUndefined() expect(config.hooks.StopFailure[0].matcher).toBeUndefined() expect(config.hooks.Notification[0].matcher).toBeUndefined() // Why: assert the shipped helper still matches what install wrote (regression @@ -279,7 +281,7 @@ describe('GrokHookService', () => { expect(command).toContain(join(homeDir, '.orca')) // Why: with no Orca pane in the environment the guard short-circuits, so a standalone Grok // session never spawns a shell for the managed script at all. - expect(command).toMatch(/^if \[ -n "\$ORCA_PANE_KEY" \] && /) + expect(command).toMatch(/^if \[ -n "\$\{ORCA_PANE_KEY-\}" \] && /) } const script = readFileSync( diff --git a/src/main/grok/windows-hook-launcher-chain.test.ts b/src/main/grok/windows-hook-launcher-chain.test.ts index ee503bd27a7..5ea5582af78 100644 --- a/src/main/grok/windows-hook-launcher-chain.test.ts +++ b/src/main/grok/windows-hook-launcher-chain.test.ts @@ -28,6 +28,7 @@ const GROK_EVENT_NAMES = [ 'SessionStart', 'UserPromptSubmit', 'Stop', + 'StopCancelled', 'StopFailure', 'SessionEnd', 'PreToolUse', diff --git a/src/main/hook-archive-termination-safety.test.ts b/src/main/hook-archive-termination-safety.test.ts new file mode 100644 index 00000000000..7627c7e84fc --- /dev/null +++ b/src/main/hook-archive-termination-safety.test.ts @@ -0,0 +1,103 @@ +import { describe, expect, it, vi } from 'vitest' +import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import type { Repo } from '../shared/repo-types' + +vi.mock('./effective-hook-config', () => ({ + getEffectiveHooksFromConfig: (_repo: unknown, hooks: unknown) => hooks +})) + +const REPO: Repo = { id: 'r', path: '/repo', displayName: 'r', badgeColor: '#000', addedAt: 0 } + +/** + * Run a hook past its deadline with `process.kill` intercepted, so the escalation's decisions are + * observed directly instead of raced against the kernel. `groupAlive` answers the signal-0 probe. + */ +async function signalsFromTimedOutHook(groupAlive: boolean): Promise { + const { runHook } = await import('./hooks') + const dir = mkdtempSync(join(tmpdir(), 'orca-hook-signals-')) + writeFileSync(join(dir, 'orca.yaml'), 'scripts:\n archive: |\n sleep 30\n') + const sent: string[] = [] + const fakeKill = (pid: number, signal?: string | number): true => { + if (signal === 0) { + if (!groupAlive) { + throw Object.assign(new Error('ESRCH'), { code: 'ESRCH' }) + } + return true + } + sent.push(`${pid < 0 ? 'group' : 'child'}:${String(signal)}`) + return true + } + const spy = vi.spyOn(process, 'kill').mockImplementation(fakeKill) + try { + await runHook('archive', dir, REPO, dir, undefined, 100) + await new Promise((resolve) => setTimeout(resolve, 2_400)) + return sent + } finally { + spy.mockRestore() + rmSync(dir, { recursive: true, force: true }) + } +} + +// Why (#19334): the escalation exists for descendants that outlive the shell — a setup hook that +// backgrounds a server typically loses its leader to the first SIGTERM while the server keeps +// running. Keying the skip on the CHILD's exit would miss exactly that case; the probe asks the +// GROUP instead. The residual hazard, stated in hooks.ts: a recycled pid answers the probe too. +describe.skipIf(process.platform === 'win32')('archive hook termination', () => { + it('escalates to the group when members survive the first signal', async () => { + await expect(signalsFromTimedOutHook(true)).resolves.toEqual(['group:SIGTERM', 'group:SIGKILL']) + }, 20_000) + + it('sends nothing once the group is provably empty', async () => { + // A group that answers ESRCH has no members left to kill, and its pid may since belong to + // someone else — so neither the SIGTERM nor the escalation is delivered. + await expect(signalsFromTimedOutHook(false)).resolves.toEqual([]) + }, 20_000) +}) + +// The regression the group probe exists for, pinned directly because it cannot be reproduced +// through `runHook` with signals intercepted: with `process.kill` mocked nothing actually dies, so +// the child never reaches the exited state that a child-liveness skip would key on. +describe.skipIf(process.platform === 'win32')('terminateHookTree', () => { + const fakeChild = (exited: boolean) => ({ + pid: 4242, + exitCode: exited ? 0 : null, + signalCode: null, + kill: vi.fn() + }) + + it('signals a surviving group even though the shell leader already exited', async () => { + const { terminateHookTree } = await import('./hooks') + const sent: (string | number | undefined)[][] = [] + const recordKill = (pid: number, signal?: string | number): true => { + if (signal !== 0) { + sent.push([pid, signal]) + } + return true + } + const spy = vi.spyOn(process, 'kill').mockImplementation(recordKill) + try { + // A hook that backgrounds a server loses its leader to the first SIGTERM; the server lives on. + terminateHookTree(fakeChild(true), 'SIGKILL') + expect(sent).toEqual([[-4242, 'SIGKILL']]) + } finally { + spy.mockRestore() + } + }) + + it('sends nothing when the group answers ESRCH', async () => { + const { terminateHookTree } = await import('./hooks') + const child = fakeChild(true) + const emptyGroup = (): true => { + throw Object.assign(new Error('ESRCH'), { code: 'ESRCH' }) + } + const spy = vi.spyOn(process, 'kill').mockImplementation(emptyGroup) + try { + terminateHookTree(child, 'SIGKILL') + expect(child.kill).not.toHaveBeenCalled() + } finally { + spy.mockRestore() + } + }) +}) diff --git a/src/main/hook-archive-timeout-observation.test.ts b/src/main/hook-archive-timeout-observation.test.ts new file mode 100644 index 00000000000..62f4b17a386 --- /dev/null +++ b/src/main/hook-archive-timeout-observation.test.ts @@ -0,0 +1,52 @@ +import { describe, expect, it, vi } from 'vitest' +import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import type { Repo } from '../shared/repo-types' + +vi.mock('./effective-hook-config', () => ({ + getEffectiveHooksFromConfig: (_repo: unknown, hooks: unknown) => hooks +})) + +const REPO: Repo = { id: 'r', path: '/repo', displayName: 'r', badgeColor: '#000', addedAt: 0 } + +/** Run a real archive script in a real shell, under a deadline short enough to test. */ +async function runArchive(script: string, timeoutMs = 400) { + const { runHook } = await import('./hooks') + const dir = mkdtempSync(join(tmpdir(), 'orca-hook-deadline-')) + writeFileSync(join(dir, 'orca.yaml'), `scripts:\n archive: |\n ${script}\n`) + try { + return await runHook('archive', dir, REPO, dir, undefined, timeoutMs) + } finally { + rmSync(dir, { recursive: true, force: true }) + } +} + +// Why a real shell (#19334): this bug is invisible to a mock. Node's `exec({ timeout })` SIGTERMs +// the child and reports whatever it chose to do, so a hook that traps SIGTERM and exits 0 came +// back as a PASS — a hook cut off mid-archive, indistinguishable from one that finished its work. +describe.skipIf(process.platform === 'win32')('archive hook deadline', () => { + it('fails a hook that traps SIGTERM and exits zero, despite its zero exit', async () => { + const result = await runArchive("trap 'exit 0' TERM; sleep 30") + expect(result.success).toBe(false) + // Withheld, so the removal gate reads `unverifiable` rather than a pass. + expect(result.exitCode).toBeUndefined() + expect(result.output).toContain('timed out') + }, 20_000) + + it('settles at the deadline even when the hook refuses to die', async () => { + const started = Date.now() + const result = await runArchive("trap '' TERM; sleep 30") + expect(result.success).toBe(false) + // A hook that ignores the signal must not hold a removal open until it finishes. + expect(Date.now() - started).toBeLessThan(10_000) + }, 20_000) + + it('passes a hook that finishes inside its deadline', async () => { + await expect(runArchive('echo archived')).resolves.toMatchObject({ success: true }) + }) + + it('reports an observed non-zero exit as the exit it is', async () => { + await expect(runArchive('exit 23')).resolves.toMatchObject({ success: false, exitCode: 23 }) + }) +}) diff --git a/src/main/hooks-archive-exit-observation.test.ts b/src/main/hooks-archive-exit-observation.test.ts new file mode 100644 index 00000000000..7773894c4c4 --- /dev/null +++ b/src/main/hooks-archive-exit-observation.test.ts @@ -0,0 +1,63 @@ +import { describe, expect, it, vi } from 'vitest' +import type { Repo } from '../shared/repo-types' + +const { execMock } = vi.hoisted(() => ({ execMock: vi.fn() })) +vi.mock('child_process', () => ({ + exec: execMock, + execFileSync: vi.fn(), + execFile: vi.fn(), + spawn: vi.fn() +})) +vi.mock('./effective-hook-config', () => ({ + getEffectiveHooksFromConfig: () => ({ scripts: { archive: 'do-the-archive' } }) +})) + +const REPO: Repo = { id: 'r', path: '/repo', displayName: 'r', badgeColor: '#000', addedAt: 0 } + +const execFailure = (code: unknown): Error => Object.assign(new Error('Command failed'), { code }) + +/** Drive runHook once with the error object `exec` hands back for a given failure mode. */ +async function runArchiveWith( + error: Error | null +): Promise<{ success: boolean; exitCode?: number }> { + const { runHook } = await import('./hooks') + execMock.mockImplementationOnce((_script, _opts, cb) => { + cb(error, '', '') + return { pid: 1234, kill: vi.fn() } + }) + const outcome = await runHook('archive', '/repo/wt', REPO) + // Guard against a vacuous pass: if the mock ever stops intercepting, a real shell would run and + // this, rather than the subtle assertions below, is what fails. + expect(execMock).toHaveBeenCalled() + return outcome +} + +// Why (#19334): an ABSENT exitCode is what the removal gate reads as `unverifiable`. The guard is +// `typeof code === 'number'`, because `exec` reports a spawn failure with a *string* code — a +// looser null-check would file ENOENT as `exited "ENOENT"`, reading a hook that never ran as one +// that reported an exit. The timeout arm of the same contract is covered against a real shell in +// hook-archive-timeout-observation.test.ts. +describe('archive hook exit observation', () => { + it('passes a clean run through without an exit code', async () => { + await expect(runArchiveWith(null)).resolves.toEqual({ success: true, output: '' }) + }) + + it.each([ + ['a non-zero exit', 23], + ['a shell command-not-found', 127] + ])('reports %s as the observed exit it is', async (_label, code) => { + await expect(runArchiveWith(execFailure(code))).resolves.toMatchObject({ + success: false, + exitCode: code + }) + }) + + it.each([ + ['was killed by a signal', null], + ['never started, so the code is a string', 'ENOENT'] + ])('withholds the exit code when the hook %s', async (_label, code) => { + const result = await runArchiveWith(execFailure(code)) + expect(result.success).toBe(false) + expect(result.exitCode).toBeUndefined() + }) +}) diff --git a/src/main/hooks.ts b/src/main/hooks.ts index ef65fc28cf0..f9d91f38423 100644 --- a/src/main/hooks.ts +++ b/src/main/hooks.ts @@ -1,6 +1,5 @@ import { readFileSync, existsSync } from 'node:fs' import { join } from 'node:path' -import { exec } from 'node:child_process' import { parseOrcaYaml } from '../shared/orca-yaml' import { resolveHookCommandSourcePolicy } from '../shared/hook-command-source-policy' import { getEffectiveHooksFromConfig } from './effective-hook-config' @@ -15,9 +14,114 @@ import type { HookRuntimeTarget } from './hook-runtime-target' import type { OrcaHooks } from '../shared/orca-yaml-hook-types' import type { Repo } from '../shared/repo-types' import type { ProjectExecutionRuntimeResolution } from '../shared/project-execution-runtime' +import { exec } from 'node:child_process' const HOOK_TIMEOUT = 120_000 // 2 minutes +type HookProcessOutcome = { success: boolean; output: string; exitCode?: number } + +/** + * Turn a finished process into a hook verdict. + * + * Why `timedOut` decides before `code` (#19334): a hook that traps SIGTERM and exits 0 reports a + * zero exit for a run we cut off mid-archive. The exit code of something we stopped is not + * evidence it finished, so a timeout withholds the code and the removal gate reads that as + * `unverifiable` rather than as a pass. + */ +function classifyHookProcessResult( + result: { code: number | null; stdout: string; stderr: string; timedOut: boolean }, + context: { hookName: string; cwd: string; timeoutMs: number } +): HookProcessOutcome { + const streams = `${result.stdout}\n${result.stderr}` + if (result.timedOut) { + const message = `Hook timed out after ${context.timeoutMs}ms.` + console.error(`[hooks] ${context.hookName} hook failed in ${context.cwd}:`, message) + return { success: false, output: `${streams}\n${message}`.trim() } + } + if (result.code !== 0) { + const message = `Command failed with exit code ${result.code}.` + console.error(`[hooks] ${context.hookName} hook failed in ${context.cwd}:`, message) + return { + success: false, + output: `${streams}\n${message}`.trim(), + ...(typeof result.code === 'number' ? { exitCode: result.code } : {}) + } + } + console.log(`[hooks] ${context.hookName} hook completed in ${context.cwd}`) + return { success: true, output: streams.trim() } +} + +const SIGTERM_GRACE_MS = 2_000 + +/** Signal the hook's whole process group where the platform has one, else just the child. */ +export type TerminableChild = { + pid?: number + exitCode: number | null + signalCode: NodeJS.Signals | null + kill: (signal: NodeJS.Signals) => boolean +} + +export function terminateHookTree(child: TerminableChild, signal: NodeJS.Signals): void { + // Why probe the GROUP and not the child: the escalation exists for descendants that outlive the + // shell. A hook that backgrounds a server typically loses its leader to the first SIGTERM while + // the server keeps running, so keying this on `child.exitCode` would skip the SIGKILL in exactly + // the case it was added for. + // + // The trade-off it does not solve: signalling by negative pid names whatever group owns that pid + // now. Once the leader is reaped its pid can be recycled, and a probe cannot tell a surviving + // descendant from a stranger that inherited the number. Killing a runaway hook is the likelier + // event and the one the deadline promises, so the group is signalled whenever it answers; the + // residual window is pid wraparound inside the two-second grace. + if (process.platform !== 'win32' && child.pid) { + try { + // Signal 0 tests for members without delivering anything: ESRCH means the group is empty. + process.kill(-child.pid, 0) + } catch { + return + } + try { + process.kill(-child.pid, signal) + return + } catch { + // Raced with the last member exiting; fall through to the direct kill. + } + } + if (child.exitCode !== null || child.signalCode !== null) { + return + } + try { + child.kill(signal) + } catch { + // Already dead. + } +} + +/** An `exec` failure: a string `code` (ENOENT) means it never started, so no exit was observed. */ +function hookProcessError( + error: Error, + stdout: string, + stderr: string, + context: { hookName: string; cwd: string } +): HookProcessOutcome { + const code = 'code' in error ? error.code : undefined + console.error(`[hooks] ${context.hookName} hook failed in ${context.cwd}:`, error.message) + return { + success: false, + output: `${stdout}\n${stderr}\n${error.message}`.trim(), + ...(typeof code === 'number' ? { exitCode: code } : {}) + } +} + +/** A hook that never started reported no exit, so the code stays withheld. */ +function hookSpawnFailure( + error: unknown, + context: { hookName: string; cwd: string } +): HookProcessOutcome { + const message = error instanceof Error ? error.message : String(error) + console.error(`[hooks] ${context.hookName} hook failed in ${context.cwd}:`, message) + return { success: false, output: message } +} + function getHookShell(): string | undefined { if (process.platform === 'win32') { return process.env.ComSpec || 'cmd.exe' @@ -120,8 +224,12 @@ export function runHook( cwd: string, repo: Repo, hooksPath?: string, - projectRuntime?: ProjectExecutionRuntimeResolution | HookRuntimeTarget -): Promise<{ success: boolean; output: string }> { + projectRuntime?: ProjectExecutionRuntimeResolution | HookRuntimeTarget, + /** Deadline override. Production uses HOOK_TIMEOUT; tests use it to exercise the timeout path. */ + timeoutMs: number = HOOK_TIMEOUT + // Why (#19334): an absent exitCode means no exit was ever observed. The archive-hook removal + // gate reads that as `unverifiable` rather than folding it into a zero. +): Promise<{ success: boolean; output: string; exitCode?: number }> { const hooks = getEffectiveHooks(repo, hooksPath) const script = hooks?.scripts[hookName] @@ -165,57 +273,71 @@ export function runHook( shell: 'bash', cwd: wslInfo.linuxPath, env: guestEnv, - timeoutMs: HOOK_TIMEOUT + timeoutMs }) - .then((result) => { - if (result.timedOut) { - const message = `Hook timed out after ${HOOK_TIMEOUT}ms.` - console.error(`[hooks] ${hookName} hook failed in ${cwd}:`, message) - return { success: false, output: `${result.stdout}\n${result.stderr}\n${message}`.trim() } - } - if (result.code !== 0) { - const message = `Command failed with exit code ${result.code}.` - console.error(`[hooks] ${hookName} hook failed in ${cwd}:`, message) - return { success: false, output: `${result.stdout}\n${result.stderr}\n${message}`.trim() } - } - console.log(`[hooks] ${hookName} hook completed in ${cwd}`) - return { success: true, output: `${result.stdout}\n${result.stderr}`.trim() } - }) - .catch((error: unknown) => { - const message = error instanceof Error ? error.message : String(error) - console.error(`[hooks] ${hookName} hook failed in ${cwd}:`, message) - return { success: false, output: message } - }) + .then((result) => classifyHookProcessResult(result, { hookName, cwd, timeoutMs })) + .catch((error: unknown) => hookSpawnFailure(error, { hookName, cwd })) } const shellHookEnv: NodeJS.ProcessEnv = { ...process.env, ...getSetupEnvVars(repo, cwd) } dropIncoherentCondaActivationEnv(shellHookEnv) - return new Promise((resolve) => { - exec( + return new Promise((resolve) => { + // Why we own the deadline (#19334): Node's `exec({ timeout })` SIGTERMs the child and then + // reports whatever it chose to do, so a hook that traps SIGTERM and exits 0 came back as a + // PASS — a hook cut off mid-archive, indistinguishable from one that finished. Settle on the + // deadline instead, and settle AT it, so a hook that traps and keeps running cannot hold a + // removal open. `exec` stays because it owns the per-platform shell invocation (`cmd.exe` + // wants `/d /s /c`, not `-c`), which is not this change's to re-derive. + let settled = false + let deadline: NodeJS.Timeout | undefined + const settle = (result: HookProcessOutcome): void => { + if (settled) { + return + } + settled = true + if (deadline) { + clearTimeout(deadline) + } + resolve(result) + } + const child = exec( script, { cwd, - timeout: HOOK_TIMEOUT, shell: getHookShell(), // Why: hooks run unattended; block Git Credential Manager's interactive prompt while keeping cached auth (issue #7652). - env: promptGuardShellEnv(shellHookEnv) + env: promptGuardShellEnv(shellHookEnv), + // Signal the whole group on POSIX: the script is a shell, and the work is its children. + ...(process.platform === 'win32' ? {} : { detached: true }) }, (error, stdout, stderr) => { if (error) { - console.error(`[hooks] ${hookName} hook failed in ${cwd}:`, error.message) - resolve({ - success: false, - output: `${stdout}\n${stderr}\n${error.message}`.trim() - }) - } else { - console.log(`[hooks] ${hookName} hook completed in ${cwd}`) - resolve({ - success: true, - output: `${stdout}\n${stderr}`.trim() - }) + settle(hookProcessError(error, stdout, stderr, { hookName, cwd })) + return } + settle( + classifyHookProcessResult( + { code: 0, stdout, stderr, timedOut: false }, + { hookName, cwd, timeoutMs } + ) + ) } ) + // Why guarded: `exec`'s callback can fire synchronously (the unit test's mock does), and arming + // a deadline on an already-settled run would later signal a process group whose pid is long + // gone — and may by then belong to something else. + if (!settled) { + deadline = setTimeout(() => { + settle( + classifyHookProcessResult( + { code: null, stdout: '', stderr: '', timedOut: true }, + { hookName, cwd, timeoutMs } + ) + ) + terminateHookTree(child, 'SIGTERM') + setTimeout(() => terminateHookTree(child, 'SIGKILL'), SIGTERM_GRACE_MS).unref?.() + }, timeoutMs) + } }) } diff --git a/src/main/ipc/filesystem/filesystem-read-handlers.ts b/src/main/ipc/filesystem/filesystem-read-handlers.ts index 938370a2816..2850ba659b4 100644 --- a/src/main/ipc/filesystem/filesystem-read-handlers.ts +++ b/src/main/ipc/filesystem/filesystem-read-handlers.ts @@ -1,3 +1,8 @@ +import { + capturePathExistence, + validatePathExistenceBatch, + type PathExistenceResult +} from '../../../shared/path-existence-batch' import { ipcMain } from 'electron' import { readdir, readFile, stat } from 'node:fs/promises' import { extname } from 'node:path' @@ -147,6 +152,37 @@ export function registerFilesystemReadHandlers(context: FilesystemHandlerContext } ) + ipcMain.handle( + 'fs:pathsExist', + async ( + _event, + args: { filePaths: string[]; connectionId?: string } + ): Promise => { + validatePathExistenceBatch(args.filePaths) + const provider = args.connectionId ? requireSshFilesystemProvider(args.connectionId) : null + if (provider?.pathsExist) { + return provider.pathsExist(args.filePaths) + } + return Promise.all( + args.filePaths.map((filePath) => + capturePathExistence(async () => { + try { + await (provider + ? provider.stat(filePath) + : stat(await resolveAuthorizedPath(filePath, store))) + return true + } catch (error) { + if (isENOENT(error)) { + return false + } + throw error + } + }) + ) + ) + } + ) + ipcMain.handle( 'fs:pathExists', async (_event, args: { filePath: string; connectionId?: string }): Promise => { diff --git a/src/main/ipc/notifications.ts b/src/main/ipc/notifications.ts index 274ab2719d8..d4b859f4d93 100644 --- a/src/main/ipc/notifications.ts +++ b/src/main/ipc/notifications.ts @@ -9,13 +9,12 @@ import type { NotificationPermissionStatusResult } from '../../shared/notification-settings-types' import type { OrcaRuntimeService } from '../runtime/orca-runtime' -import { buildNotificationOptions } from './notification-options' import { readNotificationAuthorizationStatus } from './notification-authorization-status' import { setTrayAttention } from '../tray/system-tray' import { isMainWindowVisible } from '../window/main-window-visibility' import { activeNotificationsById } from './native-notification-lifecycle' import { deliverNativeNotification } from './native-notification-delivery' -import { reserveNotificationCooldown } from './notification-burst-cooldown' +import { createNotificationDeliveryService } from '../notifications/notification-delivery-service' import { registerNotificationSoundHandlers } from './notification-sound-ipc' import { openNotificationSystemSettings } from './notification-system-settings-link' import { @@ -29,8 +28,6 @@ import { export function registerNotificationHandlers(store: Store, runtime?: OrcaRuntimeService): void { ipcMain.removeHandler('notifications:getDesktopAwayState') ipcMain.handle('notifications:getDesktopAwayState', () => readDesktopAwayState(powerMonitor)) - const recentDesktopNotifications = new Map() - const recentMobileNotifications = new Map() resetNotificationPermissionEvidence() ipcMain.removeHandler('notifications:openSystemSettings') @@ -106,95 +103,31 @@ export function registerNotificationHandlers(store: Store, runtime?: OrcaRuntime return { dismissed } }) + const deliveryService = createNotificationDeliveryService({ + readNotificationSettings: () => store.getSettings().notifications, + findActiveWindow: () => + BrowserWindow.getAllWindows().find((window) => !window.isDestroyed()) ?? null, + isWindowVisible: isMainWindowVisible, + setTrayAttention, + isNotificationSupported: () => Notification.isSupported(), + dispatchMobileNotification: runtime + ? (payload) => runtime.dispatchMobileNotification(payload) + : null, + readAuthorizationStatus: readNotificationAuthorizationStatus, + recordDeliveryOutcome: recordNotificationDeliveryOutcome, + deliverNative: deliverNativeNotification, + platform: process.platform, + now: () => Date.now() + }) + ipcMain.removeHandler('notifications:dispatch') ipcMain.handle( 'notifications:dispatch', ( _event, args: NotificationDispatchRequest - ): NotificationDispatchResult | Promise => { - // Why: light the tray attention dot before the cooldown/focus/enabled gates so they can't hold it back (clears on window show/restore; see index.ts). - if (args.source === 'agent-task-complete' || args.source === 'terminal-bell') { - const activeWindow = BrowserWindow.getAllWindows().find((win) => !win.isDestroyed()) ?? null - if (!isMainWindowVisible(activeWindow)) { - setTrayAttention(true) - } - } - - const settings = store.getSettings().notifications - const desktopAllowed = - settings.enabled && - (args.source !== 'agent-task-complete' || settings.agentTaskComplete) && - (args.source !== 'terminal-bell' || settings.terminalBell) - - const notificationOptions = buildNotificationOptions(args) - - // Why: desktop focus only means this computer sees the worktree; the paired phone may still need the alert. - if (runtime && args.source !== 'test') { - const dedupeKey = args.worktreeId ?? args.worktreeLabel ?? 'global' - if ( - reserveNotificationCooldown( - recentMobileNotifications, - JSON.stringify([desktopAllowed, args.source, args.agentState, dedupeKey]), - Date.now() - ) - ) { - runtime.dispatchMobileNotification({ - type: 'notification', - emittedAt: Date.now(), - source: args.source, - ...(!desktopAllowed ? { desktopAllowed: false } : {}), - title: notificationOptions.title, - body: notificationOptions.body, - worktreeId: args.worktreeId, - ...(args.notificationId ? { notificationId: args.notificationId } : {}), - // Why: background push needs the agent's real state to pick "needs input" - // vs "finished" — and to stay silent while the agent is still working. - ...(args.agentState ? { agentState: args.agentState } : {}) - }) - } - } - - if (!desktopAllowed) { - return { delivered: false, reason: settings.enabled ? 'source-disabled' : 'disabled' } - } - - const browserWindow = - BrowserWindow.getAllWindows().find((window) => !window.isDestroyed()) ?? null - if ( - settings.suppressWhenFocused && - args.isActiveWorktree && - browserWindow && - browserWindow.isFocused() - ) { - return { delivered: false, reason: 'suppressed-focus' } - } - - // Why: the Settings test button is an explicit, often-repeated user action, so it bypasses burst dedupe. - if (args.source !== 'test') { - // Dedupe by worktree, not source — agent-finish and terminal-bell often fire in one chunk; surface only the first. - const dedupeKey = args.worktreeId ?? args.worktreeLabel ?? 'global' - if (!reserveNotificationCooldown(recentDesktopNotifications, dedupeKey, Date.now())) { - return { delivered: false, reason: 'cooldown' } - } - } - - if (!Notification.isSupported()) { - return { delivered: false, reason: 'not-supported' } - } - - if (process.platform !== 'darwin') { - return deliverNativeNotification(args, notificationOptions, settings) - } - // Why: macOS silently swallows notifications while permission is denied/undecided (verified macOS 26); skip so the renderer can show a fallback. - return readNotificationAuthorizationStatus().then((authorization) => { - if (authorization === 'denied' || authorization === 'not-determined') { - recordNotificationDeliveryOutcome('failed') - return { delivered: false, reason: 'blocked-by-system' } - } - return deliverNativeNotification(args, notificationOptions, settings) - }) - } + ): NotificationDispatchResult | Promise => + deliveryService.dispatch(args) ) registerNotificationSoundHandlers(store) diff --git a/src/main/ipc/pty-daemon-spawn-session-identity.test.ts b/src/main/ipc/pty-daemon-spawn-session-identity.test.ts index b1ead181530..766decf1c9c 100644 --- a/src/main/ipc/pty-daemon-spawn-session-identity.test.ts +++ b/src/main/ipc/pty-daemon-spawn-session-identity.test.ts @@ -435,7 +435,8 @@ describe('registerPtyHandlers', () => { worktreeId: 'wt-1', tabId: 'tab-1', leafId, - ptyId: 'ssh-pty' + ptyId: 'ssh-pty', + origin: 'spawn' }, 'ssh:ssh-1' ) diff --git a/src/main/ipc/pty-pane-claim-arbitration.test.ts b/src/main/ipc/pty-pane-claim-arbitration.test.ts index f4f57fc6b0b..86fe3381f2b 100644 --- a/src/main/ipc/pty-pane-claim-arbitration.test.ts +++ b/src/main/ipc/pty-pane-claim-arbitration.test.ts @@ -159,7 +159,8 @@ describe('registerPtyHandlers', () => { leafId, ptyId: expect.any(String), incarnationId: expect.any(String), - hostAdmittedMembership: true + hostAdmittedMembership: true, + origin: 'spawn' }) }) it('shuts down a split PTY when its expected source binding was retired', async () => { @@ -518,7 +519,8 @@ describe('registerPtyHandlers', () => { leafId, ptyId: 'pty-shared', startupCwd: '/tmp', - hostAdmittedMembership: true + hostAdmittedMembership: true, + origin: 'spawn' }) }) }) diff --git a/src/main/ipc/pty-pane-materialization-race.test.ts b/src/main/ipc/pty-pane-materialization-race.test.ts index ee1bc16c75b..bdfd4118182 100644 --- a/src/main/ipc/pty-pane-materialization-race.test.ts +++ b/src/main/ipc/pty-pane-materialization-race.test.ts @@ -387,7 +387,8 @@ describe('registerPtyHandlers', () => { tabId: 'tab-race', leafId, ptyId: 'pty-renderer', - startupCwd: '/tmp' + startupCwd: '/tmp', + origin: 'spawn' }) }) it.each([ diff --git a/src/main/ipc/pty-pane-reservation-settlement.test.ts b/src/main/ipc/pty-pane-reservation-settlement.test.ts index 06e8679ace4..b6aba0855e6 100644 --- a/src/main/ipc/pty-pane-reservation-settlement.test.ts +++ b/src/main/ipc/pty-pane-reservation-settlement.test.ts @@ -541,7 +541,8 @@ describe('registerPtyHandlers', () => { tabId: 'tab-remote', leafId, ptyId: 'ssh:ssh-1@@relay-pty', - hostAdmittedMembership: true + hostAdmittedMembership: true, + origin: 'spawn' }, 'ssh:ssh-1' ) diff --git a/src/main/ipc/pty-runtime-ssh-binding-persistence.test.ts b/src/main/ipc/pty-runtime-ssh-binding-persistence.test.ts index d1078477d12..b66cd30e71f 100644 --- a/src/main/ipc/pty-runtime-ssh-binding-persistence.test.ts +++ b/src/main/ipc/pty-runtime-ssh-binding-persistence.test.ts @@ -202,7 +202,8 @@ describe('registerPtyHandlers', () => { tabId: 'tab-remote', leafId, ptyId: 'ssh:ssh-reattach-ok@@relay-pty', - hostAdmittedMembership: true + hostAdmittedMembership: true, + origin: 'reattach' }, 'ssh:ssh-reattach-ok' ) diff --git a/src/main/ipc/pty/ipc/spawn-commit-persist.ts b/src/main/ipc/pty/ipc/spawn-commit-persist.ts index d9bee3e6934..7aaa90bf9b8 100644 --- a/src/main/ipc/pty/ipc/spawn-commit-persist.ts +++ b/src/main/ipc/pty/ipc/spawn-commit-persist.ts @@ -13,6 +13,7 @@ import { ptyOwnership, ptyIncarnationById, deletePtyOwnership } from '../provide import { ptySizes } from '../delivery/visibility-state' import { resolveCommittedPtySize, type PtyGrid } from '../delivery/attached-pty-size' import { clearProviderPtyState } from '../provider/state-cleanup' +import { spawnCommitBindingOrigin } from '../../../persistence/loading-store/pty-binding-span' import type { PtyIpcSpawnState } from './spawn-state' export async function persistPtyIpcSpawnCommit(ctx: PtyIpcSpawnState): Promise<{ @@ -115,7 +116,8 @@ export async function persistPtyIpcSpawnCommit(ctx: PtyIpcSpawnState): Promise<{ leafId: ctx.validatedLeafId, ptyId: ctx.result.id, ...(ctx.result.incarnationId ? { incarnationId: ctx.result.incarnationId } : {}), - ...(ctx.cwd ? { startupCwd: ctx.cwd } : {}) + ...(ctx.cwd ? { startupCwd: ctx.cwd } : {}), + origin: spawnCommitBindingOrigin(ctx.result) } if (args.connectionId) { ctx.deps.store.persistPtyBinding(binding, toSshExecutionHostId(args.connectionId)) diff --git a/src/main/ipc/pty/pane/stable-owner.ts b/src/main/ipc/pty/pane/stable-owner.ts index 731065e59ab..5d25e11f57c 100644 --- a/src/main/ipc/pty/pane/stable-owner.ts +++ b/src/main/ipc/pty/pane/stable-owner.ts @@ -14,6 +14,7 @@ import { import { ptyIncarnationById, ptyOwnership } from '../provider/ownership-state' import { isHostReportedPtyAbsenceError, isObservedPtyExitEvidence } from '../provider/liveness' import { clearProviderPtyState } from '../provider/state-cleanup' +import { spawnCommitBindingOrigin } from '../../../persistence/loading-store/pty-binding-span' export type StablePaneOwner = { handle?: string @@ -200,7 +201,8 @@ export function persistAdmittedStablePaneBinding(args: { ptyId: args.result.id, ...(args.result.incarnationId ? { incarnationId: args.result.incarnationId } : {}), ...(args.startupCwd ? { startupCwd: args.startupCwd } : {}), - expectedBinding + expectedBinding, + origin: spawnCommitBindingOrigin(args.result) }, args.connectionId ? toSshExecutionHostId(args.connectionId) : undefined ) diff --git a/src/main/ipc/pty/runtime/spawn-commit.ts b/src/main/ipc/pty/runtime/spawn-commit.ts index 7f8a9e38267..09d41460263 100644 --- a/src/main/ipc/pty/runtime/spawn-commit.ts +++ b/src/main/ipc/pty/runtime/spawn-commit.ts @@ -34,6 +34,7 @@ import { createTerminalSessionStateSaveFailureMessage } from '../../../../shared import { clearProviderPtyState } from '../provider/state-cleanup' import { resolvePaneSpawnReservation } from '../pane/spawn-reservation' import { admitProviderReattachLaunchIdentity } from '../pane/launch-authority' +import { spawnCommitBindingOrigin } from '../../../persistence/loading-store/pty-binding-span' import type { RuntimePtySpawnState } from './spawn-state' export async function commitRuntimePtySpawn(ctx: RuntimePtySpawnState) { @@ -159,7 +160,8 @@ export async function commitRuntimePtySpawn(ctx: RuntimePtySpawnState) { ...(ctx.cwd ? { startupCwd: ctx.cwd } : {}), ...(ctx.hostSessionBinding.expectedSourceBinding ? { expectedSourceBinding: ctx.hostSessionBinding.expectedSourceBinding } - : {}) + : {}), + origin: spawnCommitBindingOrigin(ctx.result, ctx.hostSessionBinding.expectedSourceBinding) } const persisted = args.connectionId ? ctx.hostSessionBinding.store.persistPtyBinding( diff --git a/src/main/ipc/runtime-environment-connectivity-handlers.ts b/src/main/ipc/runtime-environment-connectivity-handlers.ts index bfbc63847c4..d461b1d080a 100644 --- a/src/main/ipc/runtime-environment-connectivity-handlers.ts +++ b/src/main/ipc/runtime-environment-connectivity-handlers.ts @@ -226,6 +226,7 @@ function registerPassiveCallHandler(getUserDataPath: () => string): void { params?: unknown timeoutMs?: number expectedEnvironmentPairingRevision?: number + expectedEnvironmentRuntimeId?: string } ): Promise> => { const environment = resolveEnvironment(getUserDataPath(), args.selector) @@ -240,7 +241,9 @@ function registerPassiveCallHandler(getUserDataPath: () => string): void { args.method, args.params, args.timeoutMs, - args.expectedEnvironmentPairingRevision + args.expectedEnvironmentPairingRevision, + undefined, + { expectedEnvironmentRuntimeId: args.expectedEnvironmentRuntimeId } ) } catch (error) { const failure = runtimeEnvironmentCallFailure(environment, args.method, error) diff --git a/src/main/ipc/runtime-environment-revision-guard.test.ts b/src/main/ipc/runtime-environment-revision-guard.test.ts index 09870ab770a..2ffd3739515 100644 --- a/src/main/ipc/runtime-environment-revision-guard.test.ts +++ b/src/main/ipc/runtime-environment-revision-guard.test.ts @@ -26,4 +26,24 @@ describe('runtimeEnvironmentRevisionFailure', () => { expect(runtimeEnvironmentRevisionFailure(environment, undefined, 'repo.list')).toBeNull() expect(runtimeEnvironmentRevisionFailure(environment, 20, 'repo.list')).toBeNull() }) + + it('fails a queued call when the saved runtime identity changed', () => { + expect( + runtimeEnvironmentRevisionFailure(environment, 20, 'files.writeBase64', 'runtime-a') + ).toEqual({ + id: 'files.writeBase64', + ok: false, + error: { + code: 'runtime_environment_changed', + message: 'Runtime environment identity changed; refresh and try again' + }, + _meta: { runtimeId: 'runtime-b' } + }) + }) + + it('accepts a queued call when both pairing and runtime identity still match', () => { + expect( + runtimeEnvironmentRevisionFailure(environment, 20, 'files.writeBase64', 'runtime-b') + ).toBeNull() + }) }) diff --git a/src/main/ipc/runtime-environment-revision-guard.ts b/src/main/ipc/runtime-environment-revision-guard.ts index 2ef7cb06ac3..af70d556356 100644 --- a/src/main/ipc/runtime-environment-revision-guard.ts +++ b/src/main/ipc/runtime-environment-revision-guard.ts @@ -4,12 +4,15 @@ import type { RuntimeRpcResponse } from '../../shared/runtime-rpc-envelope' export function runtimeEnvironmentRevisionFailure( environment: KnownRuntimeEnvironment, expectedPairingRevision: number | undefined, - method: string + method: string, + expectedRuntimeId?: string ): RuntimeRpcResponse | null { - if ( - expectedPairingRevision === undefined || - (environment.pairingRevision ?? environment.createdAt) === expectedPairingRevision - ) { + const pairingChanged = + expectedPairingRevision !== undefined && + (environment.pairingRevision ?? environment.createdAt) !== expectedPairingRevision + const runtimeChanged = + expectedRuntimeId !== undefined && environment.runtimeId !== expectedRuntimeId + if (!pairingChanged && !runtimeChanged) { return null } return { @@ -17,7 +20,9 @@ export function runtimeEnvironmentRevisionFailure( ok: false, error: { code: 'runtime_environment_changed', - message: 'Runtime environment pairing changed; refresh and try again' + message: pairingChanged + ? 'Runtime environment pairing changed; refresh and try again' + : 'Runtime environment identity changed; refresh and try again' }, _meta: { runtimeId: environment.runtimeId } } diff --git a/src/main/ipc/runtime-environment-transport-routing.ts b/src/main/ipc/runtime-environment-transport-routing.ts index b19b0d9e376..f39962c20cb 100644 --- a/src/main/ipc/runtime-environment-transport-routing.ts +++ b/src/main/ipc/runtime-environment-transport-routing.ts @@ -70,7 +70,7 @@ export async function callRuntimeEnvironment( timeoutMs?: number, expectedEnvironmentPairingRevision?: number, envelope?: RuntimeOrchestrationEnvelope, - options?: { signal?: AbortSignal } + options?: { signal?: AbortSignal; expectedEnvironmentRuntimeId?: string } ): Promise> { if (method === 'status.get') { const environment = resolveEnvironment(userDataPath, selector) @@ -97,7 +97,8 @@ export async function callRuntimeEnvironment( const revisionFailure = runtimeEnvironmentRevisionFailure( currentEnvironment, expectedEnvironmentPairingRevision, - method + method, + options?.expectedEnvironmentRuntimeId ) if (revisionFailure) { return revisionFailure diff --git a/src/main/ipc/runtime-environments-call-routing.test.ts b/src/main/ipc/runtime-environments-call-routing.test.ts index e6f8946527d..0e8472625d5 100644 --- a/src/main/ipc/runtime-environments-call-routing.test.ts +++ b/src/main/ipc/runtime-environments-call-routing.test.ts @@ -416,6 +416,42 @@ describe('registerRuntimeEnvironmentHandlers', () => { expect(sendRemoteRuntimeSharedControlRequestMock).toHaveBeenCalledTimes(1) }) + it('rejects an import mutation when its capability-proven runtime was replaced before routing', async () => { + registerRuntimeEnvironmentHandlers(store as never) + const add = handler< + { name: string; pairingCode: string }, + { environment: { id: string; name: string } } + >('runtimeEnvironments:addFromPairingCode') + const added = await add(null, { name: 'desk', pairingCode: pairingCode() }) + environmentStore.markEnvironmentUsed(userDataPath, added.environment.id, { + runtimeId: 'runtime-replacement' + }) + + const call = handler< + { + selector: string + method: string + expectedEnvironmentRuntimeId?: string + }, + RuntimeRpcResponse + >('runtimeEnvironments:call') + await expect( + call(null, { + selector: 'desk', + method: 'files.writeBase64', + expectedEnvironmentRuntimeId: 'runtime-capability-proven' + }) + ).resolves.toMatchObject({ + ok: false, + error: { + code: 'runtime_environment_changed', + message: 'Runtime environment identity changed; refresh and try again' + } + }) + expect(sendRemoteRuntimeRequestMock).not.toHaveBeenCalled() + expect(sendRemoteRuntimeSharedControlRequestMock).not.toHaveBeenCalled() + }) + it.each([ [ new RemoteRuntimeClientError( diff --git a/src/main/ipc/runtime-environments.ts b/src/main/ipc/runtime-environments.ts index ac7a4107bc8..6d16315b3a7 100644 --- a/src/main/ipc/runtime-environments.ts +++ b/src/main/ipc/runtime-environments.ts @@ -114,6 +114,7 @@ export function registerRuntimeEnvironmentHandlers(store: Store): void { timeoutMs?: number subscriptionId?: string expectedEnvironmentPairingRevision?: number + expectedEnvironmentRuntimeId?: string } ): Promise<{ subscriptionId: string; requestId: string }> => { const subscriptionId = @@ -134,6 +135,12 @@ export function registerRuntimeEnvironmentHandlers(store: Store): void { ) { throw new Error('Runtime environment pairing changed; refresh and try again') } + if ( + args.expectedEnvironmentRuntimeId !== undefined && + environment.runtimeId !== args.expectedEnvironmentRuntimeId + ) { + throw new Error('Runtime environment identity changed; refresh and try again') + } const transportGeneration = getRuntimeEnvironmentTransportGeneration(environment.id) const transportIsCurrent = (): boolean => getRuntimeEnvironmentTransportGeneration(environment.id) === transportGeneration diff --git a/src/main/ipc/shell.ts b/src/main/ipc/shell.ts index 80f02552f18..7ed49c4af7c 100644 --- a/src/main/ipc/shell.ts +++ b/src/main/ipc/shell.ts @@ -1,3 +1,4 @@ +import { validatePathExistenceBatch } from '../../shared/path-existence-batch' import { ipcMain, shell, dialog } from 'electron' import { constants, copyFile, readFile, stat } from 'node:fs/promises' import { basename, extname, isAbsolute, normalize, posix, win32 } from 'node:path' @@ -204,6 +205,11 @@ export function registerShellHandlers(store: Store): void { await openWithSystemDefault(target.path) }) + ipcMain.handle('shell:pathsExist', async (_event, paths: string[]): Promise => { + validatePathExistenceBatch(paths) + return Promise.all(paths.map(pathExists)) + }) + ipcMain.handle('shell:pathExists', async (_event, filePath: string): Promise => { return pathExists(filePath) }) diff --git a/src/main/ipc/skills.test.ts b/src/main/ipc/skills.test.ts index e14c716f9cc..98cd54c384f 100644 --- a/src/main/ipc/skills.test.ts +++ b/src/main/ipc/skills.test.ts @@ -3,7 +3,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' const { handleMock, discoverSkillsMock, - discoverSkillsInWslMock, + discoverSkillObservationInWslMock, inventorySkillFreshnessMock, getDefaultWslDistroMock, getWslHomeMock, @@ -11,7 +11,7 @@ const { } = vi.hoisted(() => ({ handleMock: vi.fn(), discoverSkillsMock: vi.fn(), - discoverSkillsInWslMock: vi.fn(), + discoverSkillObservationInWslMock: vi.fn(), inventorySkillFreshnessMock: vi.fn(), getDefaultWslDistroMock: vi.fn(), getWslHomeMock: vi.fn(), @@ -37,7 +37,7 @@ vi.mock('../skills/discovery', () => ({ })) vi.mock('../skills/skill-discovery-wsl', () => ({ - discoverSkillsInWsl: discoverSkillsInWslMock + discoverSkillObservationInWsl: discoverSkillObservationInWslMock })) vi.mock('../skills/skill-freshness-inventory', () => ({ @@ -60,6 +60,7 @@ vi.mock('../wsl', () => ({ })) import { registerSkillsHandlers } from './skills' +import { clearSkillDiscoveryCaches } from '../skills/skill-discovery-target' describe('registerSkillsHandlers', () => { const originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform') @@ -69,15 +70,16 @@ describe('registerSkillsHandlers', () => { } beforeEach(() => { + clearSkillDiscoveryCaches() handleMock.mockReset() discoverSkillsMock.mockReset() - discoverSkillsInWslMock.mockReset() + discoverSkillObservationInWslMock.mockReset() getDefaultWslDistroMock.mockReset() getWslHomeMock.mockReset() parseWslPathMock.mockReset() parseWslPathMock.mockReturnValue(null) discoverSkillsMock.mockResolvedValue({ skills: [], sources: [], scannedAt: 1 }) - discoverSkillsInWslMock.mockResolvedValue({ skills: [], sources: [], scannedAt: 1 }) + discoverSkillObservationInWslMock.mockResolvedValue({ rows: [], sources: [], scannedAt: 1 }) inventorySkillFreshnessMock.mockResolvedValue({ schemaVersion: 1, installations: [], @@ -171,10 +173,30 @@ describe('registerSkillsHandlers', () => { expect(getDefaultWslDistroMock).not.toHaveBeenCalled() expect(getWslHomeMock).toHaveBeenCalledWith('Ubuntu') - expect(discoverSkillsInWslMock).toHaveBeenCalledWith({ + expect(discoverSkillObservationInWslMock).toHaveBeenCalledWith({ distro: 'Ubuntu', homeDir: '/home/alice', - cwd: '/home/alice' + sourceKinds: undefined + }) + }) + + it('shares the home and bundled WSL scan across name-filtered requests', async () => { + const handler = getDiscoverHandler() + + for (const name of ['orchestration', 'linear-tickets']) { + await handler(null, { + runtime: 'wsl', + wslDistro: 'Ubuntu', + names: [name], + sourceKinds: ['home'] + }) + } + + expect(discoverSkillObservationInWslMock).toHaveBeenCalledOnce() + expect(discoverSkillObservationInWslMock).toHaveBeenCalledWith({ + distro: 'Ubuntu', + homeDir: '/home/alice', + sourceKinds: ['bundled', 'home'] }) }) @@ -196,10 +218,11 @@ describe('registerSkillsHandlers', () => { } }) - expect(discoverSkillsInWslMock).toHaveBeenCalledWith({ + expect(discoverSkillObservationInWslMock).toHaveBeenCalledWith({ distro: 'Ubuntu', homeDir: '/home/alice', - cwd: '/mnt/c/repo/worktree' + cwd: '/mnt/c/repo/worktree', + sourceKinds: undefined }) }) diff --git a/src/main/native-chat/agent-session-wire/agent-session-retired-provider-exit-copy-ratchet.test.ts b/src/main/native-chat/agent-session-wire/agent-session-retired-provider-exit-copy-ratchet.test.ts new file mode 100644 index 00000000000..1145c30aa2d --- /dev/null +++ b/src/main/native-chat/agent-session-wire/agent-session-retired-provider-exit-copy-ratchet.test.ts @@ -0,0 +1,79 @@ +import { join, resolve } from 'node:path' +import { describe, expect, it } from 'vitest' +import { scanSourceTree, stripComments } from '../../../shared/source-scan/source-tree-scan' + +/** + * The retired copy has to stay retired. + * + * A bare `Provider exited: ` status row is the reported symptom: a chat the user could + * not act on, settled by a restart rather than by observed death. Both production writers of that + * copy are gone, replaced by outcome copy the death evidence decides. Nothing filters this string + * at read time, so a producer that resurrects it reaches the transcript directly — which is why + * the guard sits on the writing side. + * + * Deliberately narrow: only a literal that OPENS with the prefix. Prose about the retirement, and + * copy that merely mentions a provider exiting, are not producers. + */ + +const RETIRED_COPY_PREFIX = 'Provider exited' + +/** Line numbers of string literals whose first character begins the retired copy. */ +export function findRetiredProviderExitCopyLines(source: string): number[] { + const code = stripComments(source) + const pattern = new RegExp(`['"\`]${RETIRED_COPY_PREFIX}`, 'g') + return [...code.matchAll(pattern)].map((match) => code.slice(0, match.index).split('\n').length) +} + +describe('retired provider-exit copy ratchet', () => { + it('flags a literal that opens with the retired copy', () => { + const flagged = [ + `const text = 'Provider exited: recorded pid absent on host'`, + `appendStatus("Provider exited")`, + 'appendStatus(`Provider exited: ${reason}`)' + ] + for (const source of flagged) { + expect(findRetiredProviderExitCopyLines(source), source).toHaveLength(1) + } + }) + + it('reports the line the literal sits on', () => { + expect(findRetiredProviderExitCopyLines(`const a = 1\n\nconst b = 'Provider exited'`)).toEqual([ + 3 + ]) + }) + + it('leaves prose and unrelated copy alone', () => { + const allowed = [ + `// the old bare 'Provider exited: ' row`, + `/* wrote \`Provider exited\` once */`, + `const text = 'provider exited'`, + `const text = 'The provider exited unexpectedly'`, + `const text = 'Provider exit was not proven'`, + `if (text.startsWith(prefix)) {}` + ] + for (const source of allowed) { + expect(findRetiredProviderExitCopyLines(source), source).toEqual([]) + } + }) + + const repoRoot = resolve(__dirname, '..', '..', '..', '..') + // Tests assert on the retired copy on purpose; the walk skips them. + const files = scanSourceTree(join(repoRoot, 'src')) + + it('scans a plausible number of files', () => { + // A broken root or extension list would make the guard silently vacuous. + expect(files.length).toBeGreaterThan(500) + }) + + it('has no production writer of the retired copy', () => { + const offenders = files.flatMap(({ relativePath, source }) => + findRetiredProviderExitCopyLines(source).map((line) => `src/${relativePath}:${line}`) + ) + expect( + offenders, + `A status row whose copy opens with "${RETIRED_COPY_PREFIX}" lands in the user's transcript ` + + 'unfiltered, which is the symptom this chat surface was reported for. Write the outcome ' + + 'copy the death evidence decides instead of resurrecting the retired prefix.' + ).toEqual([]) + }) +}) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-acquisition-options.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-acquisition-options.test.ts index 0c89914669c..78bf7cf2808 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-acquisition-options.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-acquisition-options.test.ts @@ -72,6 +72,7 @@ function attachParams( function adapter(input: { origin: 'created' | 'resumed' options?: AgentSessionOptionsResult + restoreFailures?: readonly string[] }): StructuredAgentSessionAdapter { return { acquire: vi @@ -92,6 +93,9 @@ function adapter(input: { } })), ...(input.options ? { readOptions: vi.fn(async () => input.options!) } : {}), + ...(input.restoreFailures + ? { readOptionRestoreFailures: vi.fn(() => input.restoreFailures!) } + : {}), dispatch: vi.fn(), cancelTurn: vi.fn(), answerPrompt: vi.fn(), @@ -217,7 +221,7 @@ describe('structured session acquisition options', () => { hostId: 'local' }) const sessionAdapter = adapter({ origin: 'created' }) - const options = { model: 'gpt-5.6-sol', effort: 'medium' } + const options = { model: 'gpt-5.6-sol', effort: 'medium', fastMode: 'false' } const recordPhase = vi.fn() const created = await performAttach({ @@ -303,7 +307,7 @@ describe('structured session acquisition options', () => { await store.replaceSessionOptions({ sessionId: SESSION, fence: store.getRecord(SESSION)?.lease.runtimeFence ?? 0, - options: { approvalPolicy: 'on-request', personality: 'concise' }, + options: { approvalPolicy: 'on-request', personality: 'concise', fastMode: 'true' }, now: NOW }) @@ -321,7 +325,7 @@ describe('structured session acquisition options', () => { adapter: adapter({ origin: 'resumed', options: { - current: { model: 'gpt-5.6-terra', effort: 'medium' }, + current: { model: 'gpt-5.6-terra', effort: 'medium', fastMode: false }, models: [] } }), @@ -344,10 +348,46 @@ describe('structured session acquisition options', () => { approvalPolicy: 'on-request', personality: 'concise', model: 'gpt-5.6-terra', - effort: 'medium' + effort: 'medium', + fastMode: 'false' }) }) + it('clears a rejected Fast restore instead of retaining the prior encoded value', async () => { + root = await mkdtemp(join(tmpdir(), 'orca-acquisition-fast-restore-')) + const store = await AgentSessionRecordStore.open({ + directory: join(root, 'store'), + hostId: 'local' + }) + const sessionAdapter = adapter({ + origin: 'created', + options: { current: { model: 'gpt-standard' }, models: [] }, + restoreFailures: ['fastMode'] + }) + + const created = await performAttach({ + store, + adapter: sessionAdapter, + journalRoot: root, + authority: { + spawnToken: 'spawn-a', + claimKeyId: 'key-1', + handoffOperationId: CREATE_OPERATION, + probe: { outcome: 'reservation-unused' } + }, + callerKey: 'client-1', + params: attachParams(CREATE_OPERATION, null, { + model: 'gpt-standard', + fastMode: 'true' + }), + now: () => NOW, + onAttached: () => {} + }) + + expect(created).toMatchObject({ ok: true }) + expect(store.getRecord(SESSION)?.options).toEqual({ model: 'gpt-standard' }) + }) + it('releases an acquisition when provider options cannot be read', async () => { root = await mkdtemp(join(tmpdir(), 'orca-acquisition-options-failure-')) const store = await AgentSessionRecordStore.open({ diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.test.ts index c6566083eac..e08c289c87a 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.test.ts @@ -1,18 +1,45 @@ import { describe, expect, it, vi } from 'vitest' -import type { StructuredAgentSessionAdapter } from './structured-agent-session-adapter' +import type { AgentSessionJournalIdentity } from '../../../shared/agent-session-journal-types' +import type { + AgentSessionAcquisition, + StructuredAgentSessionAdapter +} from './structured-agent-session-adapter' import { StructuredAgentSessionAdapterRouter } from './structured-agent-session-adapter-router' +function claudeIdentity(sessionId: string): AgentSessionJournalIdentity { + return { + sessionId, + workspaceId: 'workspace-1', + hostId: 'local', + agent: 'claude', + providerHandle: { kind: 'claude', sessionId: 'provider-session-1', leafUuid: null } + } +} + +function acquisition(fence: number, spawnToken: string): AgentSessionAcquisition { + return { + process: { hostId: 'local', pid: 1, processStartTimeMs: 1, spawnToken }, + link: { + linkId: `link-${fence}`, + handle: { provider: 'claude', sessionId: 'provider-session-1', leafUuid: null }, + origin: 'created', + mintedAtFence: fence, + observedAt: 1 + } + } +} + function adapterOf( releaseAcquisition: StructuredAgentSessionAdapter['releaseAcquisition'] ): StructuredAgentSessionAdapter { return { - acquire: vi.fn(async () => ({ process: { pid: 1 } }) as never), + acquire: vi.fn(async ({ fence, spawnToken }) => acquisition(fence, spawnToken)), releaseAcquisition, dispatch: vi.fn(), cancelTurn: vi.fn(), answerPrompt: vi.fn(), setOption: vi.fn() - } as unknown as StructuredAgentSessionAdapter + } } describe('StructuredAgentSessionAdapterRouter.releaseAcquisition', () => { @@ -21,7 +48,7 @@ describe('StructuredAgentSessionAdapterRouter.releaseAcquisition', () => { const claude = adapterOf(vi.fn().mockRejectedValueOnce(failure).mockResolvedValue(false)) const codex = adapterOf(vi.fn(async () => false)) const router = new StructuredAgentSessionAdapterRouter({ claude, codex }, async () => {}) - const identity = { sessionId: 'session-1', agent: 'claude' } as never + const identity = claudeIdentity('session-1') await router.acquire({ identity, fence: 1, spawnToken: 'spawn-1' }) await expect(router.releaseAcquisition({ sessionId: 'session-1' })).rejects.toBe(failure) @@ -41,7 +68,7 @@ describe('StructuredAgentSessionAdapterRouter.closeSession', () => { claude.dispatch = dispatch const codex = adapterOf(vi.fn(async () => false)) const router = new StructuredAgentSessionAdapterRouter({ claude, codex }, async () => {}) - const identity = { sessionId: 'session-1', agent: 'claude' } as never + const identity = claudeIdentity('session-1') await router.acquire({ identity, fence: 1, spawnToken: 'spawn-1' }) await expect(router.closeSession('session-1')).resolves.toBe(false) @@ -49,7 +76,7 @@ describe('StructuredAgentSessionAdapterRouter.closeSession', () => { router.dispatch({ sessionId: 'session-1', clientMessageId: 'client-1', - body: {} as never, + body: { kind: 'message', role: 'user', blocks: [] }, fence: 1 }) ).resolves.toMatchObject({ state: 'unknown' }) @@ -57,6 +84,32 @@ describe('StructuredAgentSessionAdapterRouter.closeSession', () => { expect(closeSession).toHaveBeenCalledTimes(2) expect(dispatch).toHaveBeenCalledTimes(1) }) + + it('retains a stop proof across journal-close failure until the host acknowledges release', async () => { + const closeSession = vi.fn(async () => true) + const closeJournal = vi.fn(async () => { + throw new Error('journal close failed') + }) + const claude = adapterOf(vi.fn(async () => true)) + claude.closeSession = closeSession + const router = new StructuredAgentSessionAdapterRouter( + { claude, codex: adapterOf(vi.fn(async () => false)) }, + async () => {} + ) + const identity = claudeIdentity('session-1') + await router.acquire({ identity, fence: 1, spawnToken: 'spawn-1' }) + + await expect(router.closeSession('session-1')).resolves.toBe(true) + await expect(closeJournal()).rejects.toThrow('journal close failed') + await expect(router.closeSession('session-1')).resolves.toBe(true) + expect(closeSession).toHaveBeenCalledOnce() + router.acknowledgeSessionRelease('session-1') + await expect(router.closeSession('session-1')).resolves.toBe(false) + + await router.acquire({ identity, fence: 2, spawnToken: 'spawn-2' }) + await expect(router.closeSession('session-1')).resolves.toBe(true) + expect(closeSession).toHaveBeenCalledTimes(2) + }) }) describe('StructuredAgentSessionAdapterRouter optional lifecycle methods', () => { @@ -73,7 +126,7 @@ describe('StructuredAgentSessionAdapterRouter optional lifecycle methods', () => claude.dispatch = dispatch const codex = adapterOf(vi.fn(async () => false)) const router = new StructuredAgentSessionAdapterRouter({ claude, codex }, async () => {}) - const identity = { sessionId: 'session-1', agent: 'claude' } as never + const identity = claudeIdentity('session-1') await router.acquire({ identity, fence: 1, spawnToken: 'spawn-1' }) const stopSession = router[method] @@ -82,7 +135,7 @@ describe('StructuredAgentSessionAdapterRouter optional lifecycle methods', () => router.dispatch({ sessionId: 'session-1', clientMessageId: 'client-1', - body: {} as never, + body: { kind: 'message', role: 'user', blocks: [] }, fence: 1 }) ).resolves.toMatchObject({ state: 'unknown' }) @@ -101,7 +154,7 @@ describe('StructuredAgentSessionAdapterRouter optional lifecycle methods', () => const codex = adapterOf(vi.fn(async () => false)) const router = new StructuredAgentSessionAdapterRouter({ claude, codex }, async () => {}) await router.acquire({ - identity: { sessionId: 'session-1', agent: 'claude' } as never, + identity: claudeIdentity('session-1'), fence: 1, spawnToken: 'spawn-1' }) @@ -112,3 +165,129 @@ describe('StructuredAgentSessionAdapterRouter optional lifecycle methods', () => } ) }) + +describe('StructuredAgentSessionAdapterRouter.closeAll', () => { + it('refuses to acquire once the global close proof is published', async () => { + const acquire = vi.fn(async ({ fence, spawnToken }) => acquisition(fence, spawnToken)) + const claude = adapterOf(vi.fn(async () => true)) + claude.acquire = acquire + const router = new StructuredAgentSessionAdapterRouter( + { claude, codex: adapterOf(vi.fn(async () => false)) }, + async () => undefined + ) + await router.closeAll() + + await expect( + router.acquire({ + identity: claudeIdentity('session-1'), + fence: 1, + spawnToken: 'spawn-1' + }) + ).rejects.toThrow('router is closed') + expect(acquire).not.toHaveBeenCalled() + }) + + it('keeps a per-session stop proof and reports no stop for a session it never routed', async () => { + const claude = adapterOf(vi.fn(async () => true)) + const closeAdapters = vi.fn(async () => undefined) + const router = new StructuredAgentSessionAdapterRouter( + { claude, codex: adapterOf(vi.fn(async () => false)) }, + closeAdapters + ) + await router.acquire({ + identity: claudeIdentity('session-1'), + fence: 1, + spawnToken: 'spawn-1' + }) + + await router.closeAll() + + // The routed session carries the shutdown's own exit proof; the other two are sessions this + // router has no record of, and an absent record is not a stop it can report. + await expect(router.closeSession('session-1')).resolves.toBe(true) + await expect(router.closeSession('never-routed')).resolves.toBe(false) + router.acknowledgeSessionRelease('session-1') + await expect(router.closeSession('session-1')).resolves.toBe(false) + await router.closeAll() + expect(closeAdapters).toHaveBeenCalledOnce() + }) + + it('asks the adapters to release an unrouted session rather than answering from the close proof', async () => { + const claudeRelease = vi.fn(async () => true) + const codexRelease = vi.fn(async () => false) + const router = new StructuredAgentSessionAdapterRouter( + { claude: adapterOf(claudeRelease), codex: adapterOf(codexRelease) }, + async () => undefined + ) + await router.closeAll() + + await expect(router.releaseAcquisition({ sessionId: 'never-routed' })).resolves.toBe(true) + expect(claudeRelease).toHaveBeenCalledWith({ sessionId: 'never-routed' }) + expect(codexRelease).toHaveBeenCalledWith({ sessionId: 'never-routed' }) + }) + + it('retains live routes and publishes no global proof when closeAll fails', async () => { + const failure = new Error('adapter shutdown failed') + const claude = adapterOf(vi.fn(async () => true)) + const dispatch = vi.fn().mockResolvedValue({ state: 'unknown', reason: 'test' }) + const closeSession = vi.fn(async () => true) + claude.dispatch = dispatch + claude.closeSession = closeSession + const router = new StructuredAgentSessionAdapterRouter( + { claude, codex: adapterOf(vi.fn(async () => false)) }, + vi.fn(async () => { + throw failure + }) + ) + await router.acquire({ + identity: claudeIdentity('session-1'), + fence: 1, + spawnToken: 'spawn-1' + }) + + await expect(router.closeAll()).rejects.toBe(failure) + + await expect(router.closeSession('never-routed')).resolves.toBe(false) + await expect( + router.dispatch({ + sessionId: 'session-1', + clientMessageId: 'client-1', + body: { kind: 'message', role: 'user', blocks: [] }, + fence: 1 + }) + ).resolves.toMatchObject({ state: 'unknown' }) + await expect(router.closeSession('session-1')).resolves.toBe(true) + expect(closeSession).toHaveBeenCalledOnce() + }) + + it('keeps the global proof when an acquisition lands mid-close', async () => { + let resolveAcquire!: (value: AgentSessionAcquisition) => void + const closeSession = vi.fn(async () => true) + const claude = adapterOf(vi.fn(async () => true)) + claude.closeSession = closeSession + claude.acquire = vi.fn( + () => + new Promise((resolve) => { + resolveAcquire = resolve + }) + ) + const router = new StructuredAgentSessionAdapterRouter( + { claude, codex: adapterOf(vi.fn(async () => false)) }, + async () => undefined + ) + const acquiring = router.acquire({ + identity: claudeIdentity('session-1'), + fence: 2, + spawnToken: 'spawn-2' + }) + + await router.closeAll() + resolveAcquire(acquisition(2, 'spawn-2')) + + // The route is NOT published behind a closed adapter, so nothing routes back out to it — and + // with no route the router has nothing to stop and no stop to report. + await expect(acquiring).rejects.toThrow('router is closed') + await expect(router.closeSession('session-1')).resolves.toBe(false) + expect(closeSession).not.toHaveBeenCalled() + }) +}) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.ts index e0f89a72afd..1cc571d39aa 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-adapter-router.ts @@ -6,9 +6,12 @@ import type { import type { StructuredAgentSessionAdapter } from './structured-agent-session-adapter' type RoutedAgent = 'claude' | 'codex' +type SessionRoute = { adapter: StructuredAgentSessionAdapter; state: 'live' | 'stopped' } export class StructuredAgentSessionAdapterRouter implements StructuredAgentSessionAdapter { - private readonly owners = new Map() + private readonly routes = new Map() + private allAdaptersClosed = false + private closePromise: Promise | null = null constructor( private readonly adapters: Record, @@ -23,20 +26,29 @@ export class StructuredAgentSessionAdapterRouter implements StructuredAgentSessi supportsLocation = (location: AgentSessionExecutionLocation): boolean => Object.values(this.adapters).some((adapter) => adapter.supportsLocation?.(location) ?? false) + /** Both adapters already gate their own shutdown, so the router only has to stop UNDOING that: + * a late acquire must not clear `allAdaptersClosed` and fan a session back out to closed + * adapters. Once closed, the router stays closed. */ async acquire(input: Parameters[0]) { + if (this.allAdaptersClosed) { + throw new Error('structured session adapter router is closed') + } const adapter = this.requireAgent(input.identity) const acquired = await adapter.acquire(input) - this.owners.set(input.identity.sessionId, adapter) + if (this.allAdaptersClosed) { + throw new Error('structured session adapter router is closed') + } + this.routes.set(input.identity.sessionId, { adapter, state: 'live' }) return acquired } async releaseAcquisition(input: { sessionId: string }): Promise { - const adapter = this.owners.get(input.sessionId) - if (adapter) { + const route = this.routes.get(input.sessionId) + if (route) { try { - return (await adapter.releaseAcquisition?.(input)) === true + return (await route.adapter.releaseAcquisition?.(input)) === true } finally { - this.owners.delete(input.sessionId) + this.routes.delete(input.sessionId) } } let released = false @@ -50,7 +62,7 @@ export class StructuredAgentSessionAdapterRouter implements StructuredAgentSessi this.owner(input.sessionId).dispatch(input) rewindSupport: NonNullable = (sessionId) => - this.owners.get(sessionId)?.rewindSupport?.(sessionId) ?? { + this.liveOwnerOrNull(sessionId)?.rewindSupport?.(sessionId) ?? { supported: false, reason: 'unsupported' } @@ -83,10 +95,10 @@ export class StructuredAgentSessionAdapterRouter implements StructuredAgentSessi backgroundTaskState: NonNullable = ( sessionId - ) => this.owners.get(sessionId)?.backgroundTaskState?.(sessionId) + ) => this.liveOwnerOrNull(sessionId)?.backgroundTaskState?.(sessionId) readCommands: NonNullable = (sessionId) => - this.owners.get(sessionId)?.readCommands?.(sessionId) + this.liveOwnerOrNull(sessionId)?.readCommands?.(sessionId) answerPrompt: StructuredAgentSessionAdapter['answerPrompt'] = (input) => this.owner(input.sessionId).answerPrompt(input) @@ -128,32 +140,68 @@ export class StructuredAgentSessionAdapterRouter implements StructuredAgentSessi adapter: StructuredAgentSessionAdapter ) => NonNullable | undefined ): Promise { - const adapter = this.owners.get(sessionId) - if (!adapter) { + const route = this.routes.get(sessionId) + if (!route) { + // No route is loss of contact, never proof of a stop. Answering `true` here would hand a + // caller a receipt for a session this router never acted on — and the caller spends that + // receipt by releasing the durable lease. return false } - const stop = selectStop(adapter) - const stopped = await stop?.call(adapter, sessionId) + if (route.state === 'stopped') { + return true + } + const stop = selectStop(route.adapter) + const stopped = await stop?.call(route.adapter, sessionId) if (stopped === true) { - this.owners.delete(sessionId) + route.state = 'stopped' return true } return false } async closeAll(): Promise { - this.owners.clear() - await this.closeAdapters() + if (this.allAdaptersClosed) { + return + } + if (this.closePromise) { + return this.closePromise + } + this.closePromise = (async () => { + try { + await this.closeAdapters() + // Adapter shutdown only resolves once every child is PROVEN stopped, so each routed + // session inherits that proof and keeps it per session. Clearing the map instead would + // leave one boolean as the only surviving evidence, and an empty map cannot tell a + // session this router stopped from one it never saw. + for (const route of this.routes.values()) { + route.state = 'stopped' + } + this.allAdaptersClosed = true + } finally { + this.closePromise = null + } + })() + return this.closePromise + } + + /** Drops a per-session stop receipt after the host releases its durable owner. */ + acknowledgeSessionRelease = (sessionId: string): void => { + this.routes.delete(sessionId) } private owner(sessionId: string): StructuredAgentSessionAdapter { - const adapter = this.owners.get(sessionId) + const adapter = this.liveOwnerOrNull(sessionId) if (!adapter) { throw new Error(`no live structured adapter owns ${sessionId}`) } return adapter } + private liveOwnerOrNull(sessionId: string): StructuredAgentSessionAdapter | null { + const route = this.routes.get(sessionId) + return route?.state === 'live' ? route.adapter : null + } + private requireAgent(identity: AgentSessionJournalIdentity): StructuredAgentSessionAdapter { const adapter = this.adapterForAgent(identity.agent) if (!adapter) { diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-adapter.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-adapter.ts index 8c1568e0af8..75e539b5641 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-adapter.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-adapter.ts @@ -240,6 +240,8 @@ export type StructuredAgentSessionAdapter = { forceCloseSession?(sessionId: string): Promise /** Stops a provider child for teardown without requiring a future-resume cursor. */ disposeSession?(sessionId: string): Promise + /** Host acknowledgement that the proven-dead child, lease and journal owner are released. */ + acknowledgeSessionRelease?(sessionId: string): void } export async function rethrowAfterAgentSessionAcquisitionCleanup( diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-dead-generation-settlement.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-dead-generation-settlement.test.ts new file mode 100644 index 00000000000..af51a9967d6 --- /dev/null +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-dead-generation-settlement.test.ts @@ -0,0 +1,315 @@ +import { mkdtemp, rm } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { openAgentSessionJournal } from '../agent-session-journal/journal-store-factory' +import type { AgentJournalRenderItem } from '../../../shared/agent-session-journal-types' +import type { AgentSessionJournal } from '../agent-session-journal/journal-store' +import { + captureUnfinishedStructuredAgentSessionWork, + MAX_UNEXPECTED_EXIT_REASON_CHARS, + settleStructuredAgentSessionDeadGeneration, + UNEXPECTED_PROVIDER_EXIT_OUTCOME, + unfinishedStructuredAgentSessionWorkWasInterrupted +} from './structured-agent-session-dead-generation-settlement' + +const SESSION = 'session-dead-generation' +const THREAD = 'thread-1' +let root: string +let journal: AgentSessionJournal + +beforeEach(async () => { + root = await mkdtemp(join(tmpdir(), 'orca-dead-generation-')) + journal = await openAgentSessionJournal({ + identity: { + sessionId: SESSION, + workspaceId: 'workspace-1', + hostId: 'local', + agent: 'codex', + providerHandle: { kind: 'codex', threadId: THREAD } + }, + journalDir: root, + now: () => 1_000 + }) +}) + +afterEach(async () => { + await journal.close() + await rm(root, { recursive: true, force: true }) +}) + +async function seedUnfinishedWork(): Promise { + await journal.appendSubmission({ + clientMessageId: 'client-1', + payloadFingerprint: 'fingerprint', + body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'keep going' }] }, + fence: 7 + }) + await journal.appendItem( + { provider: 'codex', threadId: THREAD, turnId: 'turn-1', ordinal: 1 }, + { kind: 'tool-call', name: 'shell', input: { command: 'pnpm test' }, state: 'running' }, + { fence: 7 } + ) + await journal.appendItem( + { provider: 'codex', threadId: THREAD, turnId: 'turn-1', ordinal: 2 }, + { + kind: 'approval', + title: 'Run command?', + detail: null, + options: [{ id: 'yes', label: 'Allow' }], + resolution: { state: 'pending', selectedOptionId: null, resolvedBy: null, resolvedAt: null } + }, + { fence: 7 } + ) + await journal.appendItem( + { provider: 'codex', threadId: THREAD, turnId: 'turn-1', ordinal: 3 }, + { + kind: 'question', + question: 'Which target?', + options: [{ id: 'web', label: 'Web' }], + resolution: { state: 'pending', selectedOptionId: null, resolvedBy: null, resolvedAt: null } + }, + { fence: 7 } + ) + await journal.appendItem( + { provider: 'codex', threadId: THREAD, turnId: 'turn-1', ordinal: 4 }, + { kind: 'turn', turnId: 'turn-1', state: 'running', startedAt: 900 }, + { fence: 7 } + ) +} + +describe('dead structured-session generation settlement', () => { + it('settles probe-proven work as unverifiable without a technical chat row or fake end time', async () => { + await seedUnfinishedWork() + + await expect( + settleStructuredAgentSessionDeadGeneration({ + journal, + sessionId: SESSION, + fence: 8, + settlementId: `restart-eviction:${SESSION}:8`, + pendingSubmissionReason: 'provider_exited_before_acknowledgement', + verdict: { state: 'unverifiable' }, + showUnexpectedExitOutcome: false + }) + ).resolves.toBe(true) + + const snapshot = journal.snapshot() + expect(snapshot.submissions).toEqual([ + expect.objectContaining({ clientMessageId: 'client-1', dispatchState: 'unknown' }) + ]) + expect(snapshot.items.map((item) => item.body)).toEqual( + expect.arrayContaining([ + expect.objectContaining({ kind: 'tool-call', state: 'failed' }), + expect.objectContaining({ + kind: 'approval', + resolution: expect.objectContaining({ state: 'cancelled' }) + }), + expect.objectContaining({ + kind: 'question', + resolution: expect.objectContaining({ state: 'cancelled' }) + }), + { kind: 'turn', turnId: 'turn-1', state: 'unverifiable', startedAt: 900 } + ]) + ) + expect(snapshot.items.some((item) => item.body.kind === 'status')).toBe(false) + }) + + it('adds one actionable outcome for observed active-work failure and is idempotent', async () => { + await seedUnfinishedWork() + const input = { + journal, + sessionId: SESSION, + fence: 7, + settlementId: `provider-exit:${SESSION}:7:generation-1`, + pendingSubmissionReason: 'provider_exited_before_acknowledgement', + verdict: { state: 'interrupted' as const, completedAt: 1_000 }, + showUnexpectedExitOutcome: true + } + + await expect(settleStructuredAgentSessionDeadGeneration(input)).resolves.toBe(true) + const settledCursor = journal.cursor() + await expect(settleStructuredAgentSessionDeadGeneration(input)).resolves.toBe(true) + + expect(journal.cursor()).toEqual(settledCursor) + expect( + journal + .snapshot() + .items.filter( + (item) => + item.body.kind === 'status' && item.body.text === UNEXPECTED_PROVIDER_EXIT_OUTCOME + ) + ).toHaveLength(1) + }) + + it('keeps the actionable tail when the provider dumps a stderr wall into its exit reason', async () => { + await seedUnfinishedWork() + + await expect( + settleStructuredAgentSessionDeadGeneration({ + journal, + sessionId: SESSION, + fence: 7, + settlementId: `provider-exit:${SESSION}:7:generation-1`, + pendingSubmissionReason: 'provider_exited_before_acknowledgement', + verdict: { state: 'interrupted', completedAt: 1_000 }, + showUnexpectedExitOutcome: true, + unexpectedExitReason: 'stack frame '.repeat(4_000) + }) + ).resolves.toBe(true) + + const statuses = journal + .snapshot() + .items.flatMap((item) => (item.body.kind === 'status' ? [item.body.text] : [])) + expect(statuses).toHaveLength(1) + // The cause is bounded before composing, so the row never reaches the byte cap that would + // truncate the sentence telling the user the conversation is still usable. + expect(statuses[0]).toContain('stack frame') + expect(statuses[0]).toMatch(/You can continue in this conversation\.$/) + expect(statuses[0]?.length).toBeLessThan(MAX_UNEXPECTED_EXIT_REASON_CHARS * 2) + }) + + it('retries an already settled expected close without writing through a closed journal gate', async () => { + const settledItem: AgentJournalRenderItem = { + itemId: 'codex:thread-1:turn-1:0', + revision: 2, + sequence: 2, + observedAt: 1_000, + body: { + kind: 'turn', + turnId: 'turn-1', + state: 'interrupted', + completedAt: 1_000 + } + } + const settledSnapshot = journal.snapshot() + const closedJournal: Pick< + AgentSessionJournal, + 'snapshot' | 'submissions' | 'markPendingSubmissionsUnknown' | 'appendLifecycleBatch' + > = { + snapshot: () => ({ + ...settledSnapshot, + items: [settledItem] + }), + submissions: () => [], + markPendingSubmissionsUnknown: async () => { + throw new Error('journal_closed') + }, + appendLifecycleBatch: async () => { + throw new Error('journal_closed') + } + } + + await expect( + settleStructuredAgentSessionDeadGeneration({ + journal: closedJournal, + sessionId: SESSION, + fence: 7, + settlementId: `expected-close:${SESSION}:7:generation-1`, + pendingSubmissionReason: 'provider_closed_before_acknowledgement', + verdict: { state: 'interrupted', completedAt: 1_000 }, + showUnexpectedExitOutcome: false + }) + ).resolves.toBe(true) + }) + + it('settles a live unknown submission even when no unfinished item remains', async () => { + await journal.appendSubmission({ + clientMessageId: 'client-unknown', + payloadFingerprint: 'fingerprint', + body: { kind: 'message', role: 'user', blocks: [{ type: 'text', text: 'did this land?' }] }, + fence: 7 + }) + await journal.resolveDispatch({ + clientMessageId: 'client-unknown', + state: 'unknown', + reason: 'provider write outcome unknown', + fence: 7 + }) + + await expect( + settleStructuredAgentSessionDeadGeneration({ + journal, + sessionId: SESSION, + fence: 7, + settlementId: `expected-close:${SESSION}:7:generation-1`, + pendingSubmissionReason: 'provider_closed_before_acknowledgement', + verdict: { state: 'interrupted', completedAt: 1_000 }, + showUnexpectedExitOutcome: false + }) + ).resolves.toBe(true) + + expect(journal.submissions()).toEqual([ + expect.objectContaining({ + clientMessageId: 'client-unknown', + dispatchState: 'unknown', + recovered: true, + reason: 'provider write outcome unknown' + }) + ]) + }) +}) + +describe('whether a dead generation interrupted anything', () => { + async function seedIdlePendingApproval(): Promise { + await journal.appendItem( + { provider: 'codex', threadId: THREAD, turnId: 'turn-1', ordinal: 1 }, + { + kind: 'approval', + title: 'Run command?', + detail: null, + options: [{ id: 'yes', label: 'Allow' }], + resolution: { state: 'pending', selectedOptionId: null, resolvedBy: null, resolvedAt: null } + }, + { fence: 7 } + ) + await journal.appendItem( + { provider: 'codex', threadId: THREAD, turnId: 'turn-1', ordinal: 2 }, + { kind: 'turn', turnId: 'turn-1', state: 'completed', startedAt: 900, completedAt: 950 }, + { fence: 7 } + ) + } + + it('says nothing was interrupted when the provider died waiting on an approval', async () => { + await seedIdlePendingApproval() + const before = captureUnfinishedStructuredAgentSessionWork(journal) + + expect(unfinishedStructuredAgentSessionWorkWasInterrupted(before, journal, 1_000)).toBe(false) + }) + + it('still reports an interruption when a turn was running', async () => { + await seedUnfinishedWork() + const before = captureUnfinishedStructuredAgentSessionWork(journal) + + expect(unfinishedStructuredAgentSessionWorkWasInterrupted(before, journal, 1_000)).toBe(true) + }) + + it('cancels the idle prompt without claiming a response was in progress', async () => { + await seedIdlePendingApproval() + + await expect( + settleStructuredAgentSessionDeadGeneration({ + journal, + sessionId: SESSION, + fence: 7, + settlementId: `provider-exit:${SESSION}:7:generation-1`, + pendingSubmissionReason: 'provider_exited_before_acknowledgement', + verdict: { state: 'interrupted', completedAt: 1_000 }, + showUnexpectedExitOutcome: unfinishedStructuredAgentSessionWorkWasInterrupted( + captureUnfinishedStructuredAgentSessionWork(journal), + journal, + 1_000 + ) + }) + ).resolves.toBe(true) + + const snapshot = journal.snapshot() + expect(snapshot.items.some((item) => item.body.kind === 'status')).toBe(false) + expect(snapshot.items.map((item) => item.body)).toContainEqual( + expect.objectContaining({ + kind: 'approval', + resolution: expect.objectContaining({ state: 'cancelled' }) + }) + ) + }) +}) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-dead-generation-settlement.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-dead-generation-settlement.ts new file mode 100644 index 00000000000..9a3f3a7c091 --- /dev/null +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-dead-generation-settlement.ts @@ -0,0 +1,204 @@ +import { parseAgentJournalItemKey } from '../../../shared/agent-session-journal-item-key' +import type { + AgentJournalItemBody, + AgentJournalRenderItem +} from '../../../shared/agent-session-journal-types' +import { readAgentJournalTurn } from '../../../shared/agent-session-turn-record' +import { partitionJournalLifecycleMutations } from '../agent-session-journal/journal-lifecycle-batch-partition' +import type { JournalLifecycleMutationInput } from '../agent-session-journal/journal-row-builders' +import { + boundJournalStatusText, + cancelledJournalPromptBody +} from '../agent-session-journal/journal-prompt-body-bounds' +import type { AgentSessionJournal } from '../agent-session-journal/journal-store' +import { + runningTurnLifecycleRevisions, + type StructuredAgentSessionTurnVerdict +} from './structured-agent-session-stale-turn-verdict' + +export const UNEXPECTED_PROVIDER_EXIT_OUTCOME = + 'The provider stopped while this response was in progress. You can continue in this conversation.' + +/** A provider may put a whole stderr dump in its exit reason; unbounded it would push the + * actionable tail past the row's byte cap and lose it to truncation. */ +export const MAX_UNEXPECTED_EXIT_REASON_CHARS = 512 + +/** The cause is the only thing separating an auth failure from an OOM kill, so it is carried + * into the copy rather than left in the durable record nothing renders. */ +export function unexpectedProviderExitOutcome(reason?: string): string { + const detail = reason + ?.slice(0, MAX_UNEXPECTED_EXIT_REASON_CHARS) + .trim() + .replace(/[.\s]+$/, '') + return detail + ? `The provider stopped while this response was in progress: ${detail}. You can continue in this conversation.` + : UNEXPECTED_PROVIDER_EXIT_OUTCOME +} + +type DeadGenerationSubmission = Pick< + ReturnType[number], + 'clientMessageId' | 'dispatchState' | 'recovered' +> + +export type DeadGenerationJournal = { + appendLifecycleBatch: AgentSessionJournal['appendLifecycleBatch'] + markPendingSubmissionsUnknown: AgentSessionJournal['markPendingSubmissionsUnknown'] + snapshot: () => Pick, 'items'> + pendingSubmissions?: AgentSessionJournal['pendingSubmissions'] + submissions?: () => DeadGenerationSubmission[] +} + +export type StructuredAgentSessionUnfinishedWork = { + items: AgentJournalRenderItem[] + hadUnsettledSubmissions: boolean +} + +export function captureUnfinishedStructuredAgentSessionWork( + journal: DeadGenerationJournal +): StructuredAgentSessionUnfinishedWork { + return { + items: journal.snapshot().items.filter(isUnfinishedItem), + hadUnsettledSubmissions: hasUnsettledSubmission(journal) + } +} + +function hasUnfinishedStructuredAgentSessionWork(journal: DeadGenerationJournal): boolean { + const work = captureUnfinishedStructuredAgentSessionWork(journal) + return work.hadUnsettledSubmissions || work.items.length > 0 +} + +export function unfinishedStructuredAgentSessionWorkWasInterrupted( + before: StructuredAgentSessionUnfinishedWork, + journal: DeadGenerationJournal, + observedExitAt: number +): boolean { + const currentSnapshot = journal.snapshot() + if (hasUnsettledSubmission(journal) || currentSnapshot.items.some(isInProgressItem)) { + return true + } + if ( + currentSnapshot.items.some((item) => { + const turn = readAgentJournalTurn(item.body) + return turn?.state === 'interrupted' && turn.completedAt === observedExitAt + }) + ) { + return true + } + const inProgressBefore = before.items.filter(isInProgressItem) + if (inProgressBefore.length === 0) { + return false + } + const currentItems = new Map(currentSnapshot.items.map((item) => [item.itemId, item])) + const runningTurns = inProgressBefore.filter( + (item) => readAgentJournalTurn(item.body)?.state === 'running' + ) + const outcomeItems = runningTurns.length > 0 ? runningTurns : inProgressBefore + return outcomeItems.some((item) => !isCleanlySettled(currentItems.get(item.itemId))) +} + +export async function settleStructuredAgentSessionDeadGeneration(input: { + journal: DeadGenerationJournal + sessionId: string + fence: number + settlementId: string + verdict: StructuredAgentSessionTurnVerdict + pendingSubmissionReason: string + showUnexpectedExitOutcome?: boolean + /** Why the provider stopped, when the host has it. Rendered with the outcome copy. */ + unexpectedExitReason?: string + onError?: (sessionId: string, error: unknown) => void +}): Promise { + try { + const hasUnfinishedWork = hasUnfinishedStructuredAgentSessionWork(input.journal) + const showUnexpectedExitOutcome = input.showUnexpectedExitOutcome ?? hasUnfinishedWork + if (!showUnexpectedExitOutcome && !hasUnfinishedWork) { + return true + } + await input.journal.markPendingSubmissionsUnknown(input.fence, input.pendingSubmissionReason) + const items = input.journal.snapshot().items + const mutations: JournalLifecycleMutationInput[] = [] + if (showUnexpectedExitOutcome) { + mutations.push({ + kind: 'item', + identity: { provider: 'orca', clientMessageId: input.settlementId }, + body: { + kind: 'status', + text: boundJournalStatusText(unexpectedProviderExitOutcome(input.unexpectedExitReason)) + } + }) + } + for (const item of items) { + const identity = parseAgentJournalItemKey(item.itemId) + const body = terminalDeadGenerationBody(item) + if (identity && body) { + mutations.push({ kind: 'item', identity, body }) + } + } + mutations.push(...runningTurnLifecycleRevisions(items, input.verdict)) + const batchId = `dead-generation:${input.settlementId}` + for (const chunk of partitionJournalLifecycleMutations(batchId, mutations)) { + await input.journal.appendLifecycleBatch({ + settlementId: chunk.settlementId, + fence: input.fence, + recovered: true, + mutations: chunk.mutations + }) + } + return true + } catch (error) { + input.onError?.(input.sessionId, error) + return false + } +} + +function terminalDeadGenerationBody(item: AgentJournalRenderItem): AgentJournalItemBody | null { + if (item.body.kind === 'tool-call' && item.body.state === 'running') { + return { ...item.body, state: 'failed' } + } + if (item.body.kind === 'approval' || item.body.kind === 'question') { + return item.body.resolution.state === 'pending' ? cancelledJournalPromptBody(item.body) : null + } + return null +} + +function isUnfinishedItem(item: AgentJournalRenderItem): boolean { + return ( + readAgentJournalTurn(item.body)?.state === 'running' || + terminalDeadGenerationBody(item) !== null + ) +} + +/** Work that means the provider was MID-RESPONSE. A pending approval or question is the provider + * waiting on the user, so dying while one sits there interrupted nothing — it still needs + * cancelling, but it must not claim a response was in progress. */ +function isInProgressItem(item: AgentJournalRenderItem): boolean { + return ( + readAgentJournalTurn(item.body)?.state === 'running' || + (item.body.kind === 'tool-call' && item.body.state === 'running') + ) +} + +function isCleanlySettled(item: AgentJournalRenderItem | undefined): boolean { + const turn = readAgentJournalTurn(item?.body) + if (turn) { + return turn.state === 'completed' + } + if (item?.body.kind === 'tool-call') { + return item.body.state === 'completed' + } + if (item?.body.kind === 'approval' || item?.body.kind === 'question') { + return item.body.resolution.state === 'resolved' + } + return false +} + +function hasUnsettledSubmission(journal: DeadGenerationJournal): boolean { + const submissions = journal.submissions?.() + return submissions + ? submissions.some( + (submission) => + submission.dispatchState === 'pending' || + (submission.dispatchState === 'unknown' && submission.recovered !== true) + ) + : (journal.pendingSubmissions?.().length ?? 0) > 0 +} diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-eviction.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-eviction.test.ts index 5d3de400b7a..36cecd44807 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-eviction.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-eviction.test.ts @@ -34,6 +34,9 @@ function context(): StructuredAgentSessionEvictionContext & { order: string[] } order.push('forget') }), discardSink: vi.fn(() => order.push('discardSink')), + settleWork: vi.fn(async () => { + order.push('settleWork') + }), releaseLease: vi.fn(async () => { order.push('releaseLease') }) @@ -54,6 +57,7 @@ describe('structured agent session eviction', () => { expect(ctx.order).toEqual([ 'closeSession', 'drained', + 'settleWork', 'unbind', 'close', 'discardSink', @@ -80,6 +84,7 @@ describe('structured agent session eviction', () => { expect(STRUCTURED_AGENT_SESSION_EVICTION_STEPS.map((step) => step.name)).toEqual([ 'stop-provider-child', 'drain-published', + 'settle-dead-generation', 'stop-publishing', 'close-sink', 'discard-sink', @@ -153,6 +158,7 @@ describe('a child that will not stop', () => { expect(ctx.order).toEqual([ 'drained', + 'settleWork', 'unbind', 'close', 'discardSink', diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-eviction.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-eviction.ts index 892e8695842..04840c18d5f 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-eviction.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-eviction.ts @@ -35,6 +35,13 @@ export type StructuredAgentSessionEvictionContext = { forget: () => Promise /** Drops the cached sink so a later attach mints a fresh one. */ discardSink: () => void + /** Fires once the adapter has PROVEN the child gone, so host bookkeeping stops claiming one. */ + onProviderChildStopped?: () => void + /** Whether this host still owes the child's wind-down. Distinct from `hasProviderChild`, which a + * proven exit retires mid-run: the two disagree for exactly the steps a retry has to repeat. */ + owesProviderChildWindDown?: boolean + /** Settles work owned by the child after its final callbacks have drained. */ + settleWork?: () => Promise /** Hands the lease back now that this host's child is proven gone. No-ops when the record is * not this host's to release. */ releaseLease: () => Promise @@ -71,6 +78,7 @@ export const STRUCTURED_AGENT_SESSION_EVICTION_STEPS: readonly StructuredAgentSe } } } + context.onProviderChildStopped?.() } }, { @@ -82,6 +90,11 @@ export const STRUCTURED_AGENT_SESSION_EVICTION_STEPS: readonly StructuredAgentSe } } }, + { + name: 'settle-dead-generation', + run: (context) => + context.owesProviderChildWindDown === false ? undefined : context.settleWork?.() + }, { name: 'stop-publishing', run: (context) => context.eventSink.unbind() }, { name: 'close-sink', run: (context) => context.eventSink.close() }, // Why: the runtime caches one sink per session id and hands the SAME instance to the next diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-forward.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-forward.ts index 53c5903197c..a73e8b21116 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-forward.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-forward.ts @@ -55,6 +55,7 @@ export async function handoffStructuredSessionToTui( operationId, now: deps.now() }) + deps.acknowledgeNativeRelease?.(sessionId) context.publishStage(record, 'to-tui') if (nativeSuspend.state === 'stopped-cleanup-failed') { await markStructuredHandoffManualRecovery(context, sessionId, operationId) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-options.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-options.test.ts index e5ee4f7ca9b..210defed0c5 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-options.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-options.test.ts @@ -30,6 +30,7 @@ const CALLER = { callerKey: 'client-1' } const DEFAULT_MODEL = 'gpt-default' const PICKED_MODEL = 'gpt-picked' const PICKED_EFFORT = 'medium' +const PICKED_FAST_MODE = true let root: string let store: AgentSessionRecordStore @@ -37,6 +38,7 @@ let host: StructuredAgentSessionHost let acquire: Mock let activeModel: string let activeEffort: string | null +let activeFastMode: boolean | null let transcriptPath: string let optionFailure: Error | null const dispatchedModels: string[] = [] @@ -109,6 +111,7 @@ function adapter(): StructuredAgentSessionAdapter { acquire = vi.fn(async ({ fence, spawnToken, options }) => { activeModel = options?.model ?? DEFAULT_MODEL activeEffort = options?.effort ?? null + activeFastMode = options?.fastMode === undefined ? null : options.fastMode === 'true' return { process: { hostId: 'local', @@ -146,14 +149,21 @@ function adapter(): StructuredAgentSessionAdapter { activeModel = value } else if (key === 'effort') { activeEffort = value + } else if (key === 'fastMode') { + activeFastMode = value === 'true' } return { model: activeModel, - ...(activeEffort ? { effort: activeEffort } : {}) + ...(activeEffort ? { effort: activeEffort } : {}), + ...(activeFastMode !== null ? { fastMode: String(activeFastMode) } : {}) } }), readOptions: vi.fn(async () => ({ - current: { model: activeModel, ...(activeEffort ? { effort: activeEffort } : {}) }, + current: { + model: activeModel, + ...(activeEffort ? { effort: activeEffort } : {}), + ...(activeFastMode !== null ? { fastMode: activeFastMode } : {}) + }, models: [] })), closeSession: vi.fn(async () => { @@ -168,6 +178,7 @@ beforeEach(async () => { resetHostTestOperationIds() activeModel = DEFAULT_MODEL activeEffort = null + activeFastMode = null optionFailure = null dispatchedModels.length = 0 launchedOptions.length = 0 @@ -255,6 +266,19 @@ describe('structured session handoff options', () => { effort: PICKED_EFFORT }) + const fastModeFields = { key: 'fastMode', value: String(PICKED_FAST_MODE) } + expect( + await host.setOption(CALLER, { + envelope: envelope('agentSession.setOption', fastModeFields), + ...fastModeFields + }) + ).toMatchObject({ ok: true }) + expect(store.getRecord(SESSION)?.options).toEqual({ + model: PICKED_MODEL, + effort: PICKED_EFFORT, + fastMode: 'true' + }) + expect(await host.requestHandoff(CALLER, handoff('to-tui'))).toMatchObject({ ok: true }) await vi.waitFor(async () => expect(await host.handoffStatus(SESSION)).toMatchObject({ owner: 'tui' }) @@ -264,15 +288,19 @@ describe('structured session handoff options', () => { expect(await host.handoffStatus(SESSION)).toMatchObject({ owner: 'native' }) ) - expect(launchedOptions).toEqual([{ model: PICKED_MODEL, effort: PICKED_EFFORT }]) + expect(launchedOptions).toEqual([ + { model: PICKED_MODEL, effort: PICKED_EFFORT, fastMode: 'true' } + ]) expect(closedTuiOwners).toHaveLength(1) expect(acquire.mock.calls[1]?.[0].options).toEqual({ model: PICKED_MODEL, - effort: PICKED_EFFORT + effort: PICKED_EFFORT, + fastMode: 'true' }) expect(store.getRecord(SESSION)?.options).toEqual({ model: PICKED_MODEL, - effort: PICKED_EFFORT + effort: PICKED_EFFORT, + fastMode: 'true' }) const body = hostTestMessage('use the selected model') expect( diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-options.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-options.ts index a5afd9891a1..567b4b7c256 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-options.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-options.ts @@ -1,4 +1,5 @@ import type { StructuredAgentSessionAdapter } from './structured-agent-session-adapter' +import { encodeStructuredAgentSessionOptionValue } from '../../../shared/structured-agent-session-option-codec' export async function readNativeHandoffSessionOptions(input: { adapter: Pick @@ -14,10 +15,15 @@ export async function readNativeHandoffSessionOptions(input: { if (!reported) { return undefined } - const { model: _model, effort: _effort, ...restored } = priorOptions ?? {} + const { model: _model, effort: _effort, fastMode: _fastMode, ...restored } = priorOptions ?? {} + const fastMode = + reported.current.fastMode === undefined + ? undefined + : encodeStructuredAgentSessionOptionValue('fastMode', reported.current.fastMode) return { ...restored, model: reported.current.model, - ...(reported.current.effort ? { effort: reported.current.effort } : {}) + ...(reported.current.effort ? { effort: reported.current.effort } : {}), + ...(fastMode !== undefined && fastMode !== null ? { fastMode } : {}) } } diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-types.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-types.ts index 218db8c539c..5a36c691098 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-types.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff-types.ts @@ -70,6 +70,8 @@ export type StructuredAgentSessionHandoffDeps = { transport?: StructuredAgentSessionHandoffTransport session: (sessionId: string) => { journal: AgentSessionJournal; fence: number } suspendNative: (sessionId: string) => Promise + /** Consumes the router's stop proof after `old-owner-stopped` is durable. */ + acknowledgeNativeRelease?: (sessionId: string) => void acquireNative: (input: { sessionId: string fence: number diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff.test.ts index beca21cb63a..d92bdcd7957 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-handoff.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-handoff.test.ts @@ -244,6 +244,9 @@ describe('structured session handoff failure handling', () => { it('parks a stopped native cleanup failure in manual recovery without launching TUI', async () => { const operation = operationId() const cleanupError = new Error('journal drain failed') + const acknowledgeNativeRelease = vi.fn((sessionId: string) => { + expect(store.getRecord(sessionId)?.lease.handoffStage).toBe('old-owner-stopped') + }) const retainOwner = vi.fn() const releaseOwner = vi.fn() const context = createStructuredHandoffFlowContext({ @@ -270,6 +273,7 @@ describe('structured session handoff failure handling', () => { state: 'stopped-cleanup-failed' as const, error: cleanupError })), + acknowledgeNativeRelease, acquireNative: vi.fn(async () => { throw new Error('native acquisition should not run') }), @@ -304,6 +308,7 @@ describe('structured session handoff failure handling', () => { expect(launchTui).not.toHaveBeenCalled() expect(retainOwner).not.toHaveBeenCalled() expect(releaseOwner).not.toHaveBeenCalled() + expect(acknowledgeNativeRelease).toHaveBeenCalledExactlyOnceWith(SESSION) expect(store.getRecord(SESSION)?.lease).toMatchObject({ runtimeKind: 'native', claimStatus: 'released', diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-host-handoff.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-host-handoff.ts index 113940ff0f4..9a3266541be 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-host-handoff.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-host-handoff.ts @@ -99,6 +99,7 @@ export function createStructuredAgentSessionHostHandoff( return { state: 'stopped-cleanup-failed', error } } }, + acknowledgeNativeRelease: (sessionId) => deps.adapter.acknowledgeSessionRelease?.(sessionId), acquireNative: (input) => acquireNativeHandoffOwner(deps, host, input), acquireNativeStop: async (sessionId, turnId, fence) => (await deps.adapter.cancelTurn({ sessionId, turnId, fence })).cancelled, diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-host-lifetime.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-host-lifetime.ts index e2f75297a5a..0cff20c831b 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-host-lifetime.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-host-lifetime.ts @@ -21,6 +21,7 @@ import type { import { releaseStoredStructuredAgentSessionOwner } from './structured-agent-session-lease-release' import { resumeHeldStructuredAgentSession } from './structured-agent-session-hold-resume' import type { AgentSessionWireRefusal } from '../../../shared/agent-session-wire' +import { settleStructuredAgentSessionDeadGeneration } from './structured-agent-session-dead-generation-settlement' export type StructuredAgentSessionLifetimeContext = { deps: StructuredAgentSessionHostDeps @@ -49,29 +50,75 @@ function hasProviderChild( return context.sessions.get(sessionId)?.hasProviderChild === true } +/** The wind-down this host owes for the session's child. A live child always owes one, whatever a + * previous childless eviction recorded — the same session object is re-acquired in place on a + * handoff back to native, so a remembered `false` must never outrank the child in front of it. */ +function owesProviderChildWindDown(session: StructuredAgentSessionHostSession): boolean { + return session.hasProviderChild || session.owesProviderChildWindDown === true +} + /** Runs the eviction steps under a deadline. A step that fails — or runs out of time — aborts the * rest, which leaves the session indexed and the child loaded so the next close is a real retry. */ export async function evictHeldStructuredAgentSession( context: StructuredAgentSessionLifetimeContext, sessionId: string ): Promise { - if (!context.sessions.has(sessionId)) { + const session = context.sessions.get(sessionId) + if (!session) { return } + // The obligation OUTLIVES the child. `hasProviderChild` is retired the instant the adapter + // proves the exit, so a step that aborts after that point would otherwise leave the retry + // reading "no child here" and skipping the settlement and the lease release it still owes. + const owesWindDown = owesProviderChildWindDown(session) + session.owesProviderChildWindDown = owesWindDown + let settlementError: unknown const eviction: StructuredAgentSessionEvictionContext = { sessionId, - hasProviderChild: hasProviderChild(context, sessionId), + // The retry must not re-stop a child the adapter already proved gone, so this stays honest. + hasProviderChild: session.hasProviderChild, + owesProviderChildWindDown: owesWindDown, eventSink: context.runtimeState.eventSinkFor(sessionId), adapter: context.deps.adapter, - forget: () => forgetStructuredAgentSession(context, sessionId), + // Host state must not disagree with the adapter for the seven steps in between. + onProviderChildStopped: () => { + session.hasProviderChild = false + }, + forget: async () => { + await forgetStructuredAgentSession(context, sessionId) + context.deps.adapter.acknowledgeSessionRelease?.(sessionId) + }, discardSink: () => context.runtimeState.discardEventSink(sessionId), - releaseLease: () => - releaseStoredStructuredAgentSessionOwner({ + settleWork: async () => { + const settled = await settleStructuredAgentSessionDeadGeneration({ + journal: session.journal, + sessionId, + fence: session.fence, + settlementId: `expected-close:${sessionId}:${session.fence}:${session.acquisitionGeneration ?? 'unknown'}`, + pendingSubmissionReason: 'provider_closed_before_acknowledgement', + verdict: { state: 'interrupted', completedAt: context.now() }, + showUnexpectedExitOutcome: false, + onError: (id, error) => { + settlementError = error + context.deps.onEventSinkError?.({ sessionId: id, error }) + } + }) + if (!settled) { + // Without the cause the quit log names the step and nothing else. + throw new Error('dead generation work settlement failed', { cause: settlementError }) + } + }, + releaseLease: async () => { + await releaseStoredStructuredAgentSessionOwner({ store: context.deps.store, sessionId, - hasProviderChild: hasProviderChild(context, sessionId), + hasProviderChild: owesWindDown, + expectedFence: session.fence, now: context.now() }) + session.owesProviderChildWindDown = false + context.forgetStatus(sessionId) + } } await evictStructuredAgentSession( eviction, @@ -79,6 +126,38 @@ export async function evictHeldStructuredAgentSession( ) } +/** Stops every provider child owned by this host while keeping failed evictions reachable. A + * session whose child is already stopped but whose wind-down aborted is still in scope — that is + * the retry. */ +export async function evictOwnedStructuredAgentSessions( + context: StructuredAgentSessionLifetimeContext, + retainOnFailure: Set +): Promise { + const ownedSessionIds = [...context.sessions] + .filter(([, session]) => owesProviderChildWindDown(session)) + .map(([sessionId]) => sessionId) + // Retained up front and cleared only once an eviction settles: the quit phase is bounded, and a + // timeout leaves these still running. Closing their journals underneath them is the one outcome + // the retain set exists to prevent. + for (const sessionId of ownedSessionIds) { + retainOnFailure.add(sessionId) + } + const failures: unknown[] = [] + await Promise.all( + ownedSessionIds.map(async (sessionId) => { + try { + await evictHeldStructuredAgentSession(context, sessionId) + retainOnFailure.delete(sessionId) + } catch (error) { + failures.push(error) + } + }) + ) + if (failures.length > 0) { + throw new AggregateError(failures, 'structured agent-session child eviction failed') + } +} + /** The first hold on a childless session: reconcile the lease, settle recovery, then attach. */ export async function resumeStructuredAgentSessionForHold( context: StructuredAgentSessionLifetimeContext & { diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-host-teardown.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-host-teardown.ts index b948ac08abd..a4e53d2f4c7 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-host-teardown.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-host-teardown.ts @@ -18,6 +18,26 @@ export type StructuredAgentSessionTeardownPhase = { /** Quit must not wait indefinitely on an in-flight handoff; see `drain-handoffs` below. */ const HANDOFF_DRAIN_TIMEOUT_MS = 5_000 +/** Eight steps at ten seconds each would outlast the global quit deadline, and a quit that dies + * mid-eviction leaves the lease unreleased — the exact state restart has to clean up. Bounded + * well below that deadline so the phases after this one still get to run. */ +const CHILD_EVICTION_TIMEOUT_MS = 8_000 + +/** Bounds a phase without swallowing its failure, which `withTimeout` alone would. */ +async function withPhaseTimeout(run: () => Promise, timeoutMs: number): Promise { + const settled = run().then( + () => ({ failed: false }) as const, + (error: unknown) => ({ failed: true, error }) as const + ) + const outcome = await withTimeout | null>(settled, timeoutMs, null) + if (outcome === null) { + throw new Error(`agent session host teardown phase did not finish within ${timeoutMs}ms`) + } + if (outcome.failed) { + throw outcome.error + } +} + /** * The quit-path phase order, which is load-bearing rather than incidental. * @@ -34,6 +54,7 @@ export function structuredAgentSessionHostTeardownPhases(collaborators: { } handoffs: { stopTuiHistoryCatchup: () => void; drain: () => Promise } tasks: { drainAttaches: () => Promise } + evictOwnedSessions: () => Promise }): StructuredAgentSessionTeardownPhase[] { return [ { name: 'dispose-holds', run: () => collaborators.holds.dispose() }, @@ -44,6 +65,10 @@ export function structuredAgentSessionHostTeardownPhases(collaborators: { run: () => withTimeout(collaborators.handoffs.drain(), HANDOFF_DRAIN_TIMEOUT_MS, undefined) }, { name: 'drain-attaches', run: () => collaborators.tasks.drainAttaches() }, + { + name: 'evict-owned-sessions', + run: () => withPhaseTimeout(collaborators.evictOwnedSessions, CHILD_EVICTION_TIMEOUT_MS) + }, { name: 'flush-event-sinks', run: () => collaborators.runtimeState.flushAllEventSinks() } ] } @@ -51,6 +76,8 @@ export function structuredAgentSessionHostTeardownPhases(collaborators: { export async function tearDownStructuredAgentSessionHost(input: { phases: readonly StructuredAgentSessionTeardownPhase[] sessions: Map + retainSessionIds?: ReadonlySet + acknowledgeSessionRelease?: (sessionId: string) => void }): Promise { const failures: unknown[] = [] for (const phase of input.phases) { @@ -61,7 +88,9 @@ export async function tearDownStructuredAgentSessionHost(input: { } } - const entries = [...input.sessions.entries()] + const entries = [...input.sessions.entries()].filter( + ([sessionId]) => !input.retainSessionIds?.has(sessionId) + ) // `allSettled`, so one rejected close cannot skip the others. const closed = await Promise.allSettled(entries.map(([, session]) => session.journal.close())) closed.forEach((result, index) => { @@ -71,6 +100,7 @@ export async function tearDownStructuredAgentSessionHost(input: { // which is what makes a later close a real retry rather than a no-op. if (sessionId !== undefined) { input.sessions.delete(sessionId) + input.acknowledgeSessionRelease?.(sessionId) } return } diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-host-types.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-host-types.ts index 50b913ee8bd..7131631f4ff 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-host-types.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-host-types.ts @@ -31,6 +31,11 @@ export type StructuredAgentSessionHostSession = { * restored for reading has none, and neither has a session a TUI owns — so neither may be * evicted to free a child, and neither may have its lease released as an observed exit. */ hasProviderChild: boolean + /** The wind-down this host still owes for a child it started: settling that generation's work + * and handing the lease back. A separate fact from `hasProviderChild`, which goes false the + * moment the adapter proves the exit — an eviction that aborts after that point must still be + * able to finish the wind-down on the next close. */ + owesProviderChildWindDown?: boolean /** Exact adapter acquisition behind `hasProviderChild`; retained after exit to fence recovery. */ acquisitionGeneration: string | null } diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-host.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-host.ts index 176cd66b674..c60d9e5db26 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-host.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-host.ts @@ -23,6 +23,7 @@ import { StructuredAgentSessionHostRuntimeState } from './structured-agent-sessi import { attachStructuredAgentSession } from './structured-agent-session-attach-orchestration' import { createStructuredAgentSessionHolds, + evictOwnedStructuredAgentSessions, evictHeldStructuredAgentSession, type StructuredAgentSessionLifetimeContext } from './structured-agent-session-host-lifetime' @@ -244,14 +245,20 @@ export class StructuredAgentSessionHost { this.runtimeState.flushEventSink(sessionId) async flushAllStreamedEvents(): Promise { + const retainSessionIds = new Set() await tearDownStructuredAgentSessionHost({ phases: structuredAgentSessionHostTeardownPhases({ holds: this.holds, runtimeState: this.runtimeState, handoffs: this.handoffs, - tasks: this.tasks + tasks: this.tasks, + evictOwnedSessions: () => + evictOwnedStructuredAgentSessions(this.lifetimeContext(), retainSessionIds) }), - sessions: this.sessions + sessions: this.sessions, + retainSessionIds, + acknowledgeSessionRelease: (sessionId) => + this.deps.adapter.acknowledgeSessionRelease?.(sessionId) }).finally(() => this.clientDelivery.closeAll()) } diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-journal-handles.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-journal-handles.test.ts index b1cfd81b2a5..ea32f171570 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-journal-handles.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-journal-handles.test.ts @@ -197,9 +197,15 @@ describe('site 11: host teardown is failure-complete', () => { it('closes every journal and clears the map on the happy path', async () => { const sessions = await twoSessions() - await tearDownStructuredAgentSessionHost({ phases: [], sessions }) + const acknowledgeSessionRelease = vi.fn() + await tearDownStructuredAgentSessionHost({ + phases: [], + sessions, + acknowledgeSessionRelease + }) expect(sessions.size).toBe(0) + expect(acknowledgeSessionRelease.mock.calls).toEqual([[SESSION], [`${SESSION}-b`]]) await expectNothingHoldsTheDirectory(journalDir) await expectNothingHoldsTheDirectory(join(root, 'journal-b')) }) @@ -231,6 +237,7 @@ describe('site 11: host teardown is failure-complete', () => { it('keeps the entry whose close rejected, and surfaces the rejection', async () => { const sessions = await twoSessions() + const acknowledgeSessionRelease = vi.fn() const failing = sessions.get(SESSION) const closeError = new Error('close rejected') if (failing) { @@ -240,11 +247,12 @@ describe('site 11: host teardown is failure-complete', () => { } await expect( - tearDownStructuredAgentSessionHost({ phases: [], sessions }) + tearDownStructuredAgentSessionHost({ phases: [], sessions, acknowledgeSessionRelease }) ).rejects.toMatchObject({ errors: [closeError] }) // Only the failure stays indexed — `status === 'fulfilled'`, not "settled". expect([...sessions.keys()]).toEqual([SESSION]) + expect(acknowledgeSessionRelease).toHaveBeenCalledExactlyOnceWith(`${SESSION}-b`) await expectNothingHoldsTheDirectory(join(root, 'journal-b')) }) }) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-lease-release.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-lease-release.ts index 8d6cfc39ae2..bacc56fbcaf 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-lease-release.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-lease-release.ts @@ -12,29 +12,39 @@ import { import type { AgentSessionRecordStore } from '../../runtime/agent-session-record-store' import type { AgentSessionRecord } from '../../../shared/agent-session-record' +export type StructuredAgentSessionLeaseStore = Pick< + AgentSessionRecordStore, + 'getRecord' | 'transitionHandoff' +> + export async function releaseStoredStructuredAgentSessionOwner(input: { - store: AgentSessionRecordStore + store: StructuredAgentSessionLeaseStore sessionId: string hasProviderChild: boolean + expectedFence: number now: number }): Promise { if (!input.hasProviderChild) { return } const record = input.store.getRecord(input.sessionId) - if (!record || !isSurfaceReleasableAgentSessionRecord(record)) { + if ( + !record || + record.lease.runtimeFence !== input.expectedFence || + !isSurfaceReleasableAgentSessionRecord(record) + ) { return } await releaseStoredAgentSessionOwnerAfterSurfaceClose(input.store, { sessionId: input.sessionId, - expectedFence: record.lease.runtimeFence, + expectedFence: input.expectedFence, now: input.now }) } /** Releases only the exact provider child whose exit the adapter positively observed. */ export async function releaseStoredStructuredAgentSessionOwnerAfterUnexpectedExit(input: { - store: AgentSessionRecordStore + store: StructuredAgentSessionLeaseStore sessionId: string expectedFence: number expectedAcquisitionGeneration: string diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-option-restoration.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-option-restoration.ts index 6e71f822170..98db575a337 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-option-restoration.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-option-restoration.ts @@ -1,4 +1,5 @@ import type { StructuredAgentSessionAdapter } from './structured-agent-session-adapter' +import { encodeStructuredAgentSessionOptionValue } from '../../../shared/structured-agent-session-option-codec' export async function readNativeSessionOptions(input: { adapter: Pick @@ -15,12 +16,18 @@ export async function readNativeSessionOptions(input: { const restored = priorOptions ? { ...priorOptions } : {} delete restored.model delete restored.effort + delete restored.fastMode for (const key of skipped) { delete restored[key] } + const fastMode = + reported.current.fastMode === undefined + ? undefined + : encodeStructuredAgentSessionOptionValue('fastMode', reported.current.fastMode) return { ...restored, model: reported.current.model, - ...(reported.current.effort ? { effort: reported.current.effort } : {}) + ...(reported.current.effort ? { effort: reported.current.effort } : {}), + ...(fastMode !== undefined && fastMode !== null ? { fastMode } : {}) } } diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-provider-restore.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-provider-restore.test.ts index cfcae081b88..c8a2e4bba14 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-provider-restore.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-provider-restore.test.ts @@ -58,8 +58,15 @@ function createHost( return host } +async function abandonHost(host: StructuredAgentSessionHost): Promise { + host['runtimeState'].stopLeaseRenewal() + host['holds'].dispose() + await Promise.all([...host['sessions'].values()].map((session) => session.journal.close())) + host['sessions'].clear() +} + afterEach(async () => { - await Promise.all(hosts.splice(0).map((host) => host.flushAllStreamedEvents())) + await Promise.all(hosts.splice(0).map(abandonHost)) await rm(root, { recursive: true, force: true }) root = '' }) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-recovery-exits.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-recovery-exits.test.ts index 5cd888cc5cc..7cd92bf521b 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-recovery-exits.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-recovery-exits.test.ts @@ -82,8 +82,17 @@ function openHost(overrides: Partial = {}): void }) } +async function abandonHost(abandonedHost: StructuredAgentSessionHost): Promise { + abandonedHost['runtimeState'].stopLeaseRenewal() + abandonedHost['holds'].dispose() + await Promise.all( + [...abandonedHost['sessions'].values()].map((session) => session.journal.close()) + ) + abandonedHost['sessions'].clear() +} + async function reopenStore(): Promise { - await host.flushAllStreamedEvents() + await abandonHost(host) store = await AgentSessionRecordStore.open({ directory: join(root, 'store'), hostId: 'local' }) } @@ -110,8 +119,8 @@ beforeEach(async () => { }) afterEach(async () => { - await host.flushAllStreamedEvents() - await Promise.all([...supersededHosts].map((superseded) => superseded.flushAllStreamedEvents())) + await abandonHost(host) + await Promise.all([...supersededHosts].map(abandonHost)) supersededHosts.clear() await Promise.all([...spawnedOwners].map((child) => stopOwner(child))) await rm(root, { recursive: true, force: true }) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-refusal-retry.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-refusal-retry.test.ts index f021689db08..ccad5f7225f 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-refusal-retry.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-refusal-retry.test.ts @@ -119,9 +119,16 @@ async function createHarness(options: { attached?: boolean; transport?: boolean return harness } +async function abandonHost(host: StructuredAgentSessionHost): Promise { + host['runtimeState'].stopLeaseRenewal() + host['holds'].dispose() + await Promise.all([...host['sessions'].values()].map((session) => session.journal.close())) + host['sessions'].clear() +} + afterEach(async () => { const completed = harnesses.splice(0) - await Promise.all(completed.map(async ({ host }) => host.flushAllStreamedEvents())) + await Promise.all(completed.map(async ({ host }) => abandonHost(host))) await Promise.all(completed.map(async ({ root }) => rm(root, { recursive: true }))) }) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-settlement-retry.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-settlement-retry.test.ts new file mode 100644 index 00000000000..c0d29f6b9ef --- /dev/null +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-settlement-retry.test.ts @@ -0,0 +1,190 @@ +// The settlement latch governs EVERY unclean restart — SIGKILL, force quit, OOM, a quit that blew +// its deadline — so the evidence it reads decides whether the user sees a failure notice at all. + +import { mkdtemp, rm } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import type { + AgentSessionDeathEvidence, + AgentSessionRecord +} from '../../../shared/agent-session-record' +import { agentSessionRecordFixture } from '../../../shared/agent-session-record.test-fixture' +import { openAgentSessionJournal } from '../agent-session-journal/journal-store-factory' +import type { AgentSessionJournal } from '../agent-session-journal/journal-store' +import type { StructuredAgentSessionLeaseStore } from './structured-agent-session-lease-release' +import { retryLoadedStructuredAgentSessionSettlement } from './structured-agent-session-settlement-retry' + +const SESSION = 'session-alpha-1' +const THREAD = 'thread-1' +const FENCE = 8 + +let root: string +let journal: AgentSessionJournal +let record: AgentSessionRecord + +function store(): StructuredAgentSessionLeaseStore { + return { + getRecord: () => record, + transitionHandoff: async (_sessionId, transition) => { + record = transition(record) + return record + } + } +} + +function retry(settlementId: string, deathEvidence: AgentSessionDeathEvidence) { + record = agentSessionRecordFixture({ + ...agentSessionRecordFixture().lease, + runtimeKind: 'native', + runtimeFence: FENCE, + deathEvidence, + settlementRetryRequired: true, + settlementRetryId: settlementId + }) + return retryLoadedStructuredAgentSessionSettlement({ + deps: { store: store() }, + sessionId: SESSION, + session: { journal, fence: FENCE, acquisitionGeneration: null }, + now: () => 2_000 + }) +} + +function statusTexts(): string[] { + return journal + .snapshot() + .items.flatMap((item) => (item.body.kind === 'status' ? [item.body.text] : [])) +} + +beforeEach(async () => { + root = await mkdtemp(join(tmpdir(), 'orca-settlement-retry-')) + journal = await openAgentSessionJournal({ + identity: { + sessionId: SESSION, + workspaceId: 'workspace-1', + hostId: 'local', + agent: 'codex', + providerHandle: { kind: 'codex', threadId: THREAD } + }, + journalDir: root, + now: () => 1_000 + }) +}) + +/** A turn the dead generation left running: work to settle either way. */ +async function seedRunningTurn(): Promise { + await journal.appendItem( + { provider: 'codex', threadId: THREAD, turnId: 'turn-1', ordinal: 1 }, + { kind: 'turn', turnId: 'turn-1', state: 'running', startedAt: 900 }, + { fence: FENCE } + ) +} + +/** The provider died while the user, not the provider, held the conversation. */ +async function seedIdlePendingApproval(): Promise { + await journal.appendItem( + { provider: 'codex', threadId: THREAD, turnId: 'turn-1', ordinal: 1 }, + { + kind: 'approval', + title: 'Run command?', + detail: null, + options: [{ id: 'yes', label: 'Allow' }], + resolution: { state: 'pending', selectedOptionId: null, resolvedBy: null, resolvedAt: null } + }, + { fence: FENCE } + ) +} + +afterEach(async () => { + await journal.close() + await rm(root, { recursive: true, force: true }) +}) + +describe('pending settlement retry', () => { + it('writes no status row when the death was only adjudicated, not witnessed', async () => { + await seedRunningTurn() + + await expect( + retry(`restart-eviction:${SESSION}:${FENCE}`, { + kind: 'pid-absent', + detail: 'recorded pid absent on host', + observedAt: 1_500 + }) + ).resolves.toBe(true) + + expect(statusTexts()).toEqual([]) + expect(journal.snapshot().items.map((item) => item.body)).toContainEqual( + expect.objectContaining({ kind: 'turn', state: 'unverifiable' }) + ) + expect(record.lease.settlementRetryRequired).toBeUndefined() + }) + + it('writes no status row for an identity mismatch either', async () => { + await seedRunningTurn() + + await expect( + retry(`restart-eviction:${SESSION}:${FENCE}`, { + kind: 'identity-mismatch', + detail: 'mismatched spawn-token', + observedAt: 1_500 + }) + ).resolves.toBe(true) + + expect(statusTexts()).toEqual([]) + }) + + it('reads the evidence, not the settlement id, when deciding to speak', async () => { + // Pins the discriminator: the id shape that normally accompanies a witnessed exit must not + // earn the notice on its own. + await seedRunningTurn() + + await expect( + retry(`provider-exit:${SESSION}:${FENCE}:generation-1`, { + kind: 'pid-absent', + detail: 'recorded pid absent on host', + observedAt: 1_500 + }) + ).resolves.toBe(true) + + expect(statusTexts()).toEqual([]) + }) + + it('writes user-facing copy carrying the cause when the exit was observed', async () => { + await seedRunningTurn() + + await expect( + retry(`provider-exit:${SESSION}:${FENCE}:generation-1`, { + kind: 'exit-observed', + detail: 'transport closed', + observedAt: 1_500 + }) + ).resolves.toBe(true) + + expect(statusTexts()).toEqual([ + 'The provider stopped while this response was in progress: transport closed. You can continue in this conversation.' + ]) + expect(journal.snapshot().items.map((item) => item.body)).toContainEqual( + expect.objectContaining({ kind: 'turn', state: 'interrupted', completedAt: 1_500 }) + ) + }) + + it('stays silent about a witnessed exit that interrupted nothing but a waiting prompt', async () => { + await seedIdlePendingApproval() + + await expect( + retry(`provider-exit:${SESSION}:${FENCE}:generation-1`, { + kind: 'exit-observed', + detail: 'transport closed', + observedAt: 1_500 + }) + ).resolves.toBe(true) + + expect(statusTexts()).toEqual([]) + expect(journal.snapshot().items.map((item) => item.body)).toContainEqual( + expect.objectContaining({ + kind: 'approval', + resolution: expect.objectContaining({ state: 'cancelled' }) + }) + ) + }) +}) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-settlement-retry.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-settlement-retry.ts index 4e5de3f2566..120eeaeb635 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-settlement-retry.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-settlement-retry.ts @@ -4,11 +4,13 @@ import type { StructuredAgentSessionHostDeps, StructuredAgentSessionHostSession } from './structured-agent-session-host-types' +import type { StructuredAgentSessionLeaseStore } from './structured-agent-session-lease-release' import { turnVerdictFromDeathEvidence } from './structured-agent-session-stale-turn-verdict' import { - retryUnexpectedExitSettlement, - type StructuredAgentSessionUnexpectedExitContext -} from './structured-agent-session-unexpected-exit' + captureUnfinishedStructuredAgentSessionWork, + settleStructuredAgentSessionDeadGeneration, + unfinishedStructuredAgentSessionWorkWasInterrupted +} from './structured-agent-session-dead-generation-settlement' export async function retryPendingStructuredAgentSessionSettlement(input: { deps: StructuredAgentSessionHostDeps @@ -56,7 +58,10 @@ export async function retryPendingStructuredAgentSessionSettlement(input: { } export async function retryLoadedStructuredAgentSessionSettlement(input: { - deps: Pick + deps: { + store: StructuredAgentSessionLeaseStore + onEventSinkError?: StructuredAgentSessionHostDeps['onEventSinkError'] + } sessionId: string session: Pick now: () => number @@ -67,23 +72,32 @@ export async function retryLoadedStructuredAgentSessionSettlement(input: { } const retrySession = input.session retrySession.fence = record.lease.runtimeFence - const context: Pick = { - onBarrierError: (id, error) => input.deps.onEventSinkError?.({ sessionId: id, error }) - } - const ok = await retryUnexpectedExitSettlement({ - context, - event: { - type: 'ended', - sessionId: input.sessionId, - reason: record.lease.deathEvidence?.detail ?? 'provider exited', - cause: 'unexpected-exit', - fence: record.lease.runtimeFence, - acquisitionGeneration: retrySession.acquisitionGeneration ?? 'recovery' - }, - session: retrySession, - stableSettlementId: record.lease.settlementRetryId, - // Only an observed exit earns an end time; a probe-proven death never saw one. - verdict: turnVerdictFromDeathEvidence(record.lease.deathEvidence) + const onError = (id: string, error: unknown): void => + input.deps.onEventSinkError?.({ sessionId: id, error }) + // Only an observed exit earns an end time; a probe-proven death never saw one. + const verdict = turnVerdictFromDeathEvidence(record.lease.deathEvidence) + const ok = await settleStructuredAgentSessionDeadGeneration({ + journal: retrySession.journal, + sessionId: input.sessionId, + fence: retrySession.fence, + settlementId: record.lease.settlementRetryId, + pendingSubmissionReason: 'provider_exited_before_acknowledgement', + verdict, + // The same evidence decides the copy: only a witnessed death is worth telling the user + // about. An unverifiable one is a restart artefact, and the session stays sendable. The + // work check matches the live exit path — a provider that died waiting on a prompt + // interrupted no response, so it must not claim one was in progress. + showUnexpectedExitOutcome: + verdict.state === 'interrupted' && + unfinishedStructuredAgentSessionWorkWasInterrupted( + captureUnfinishedStructuredAgentSessionWork(retrySession.journal), + retrySession.journal, + verdict.completedAt + ), + ...(record.lease.deathEvidence?.detail + ? { unexpectedExitReason: record.lease.deathEvidence.detail } + : {}), + onError }) if (!ok) { return false diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-surface-lifetime.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-surface-lifetime.test.ts index 678b790ed4e..2538b61c84b 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-surface-lifetime.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-surface-lifetime.test.ts @@ -3,13 +3,14 @@ // Two leaks meet here and each has to be tested against the real host, not a double: a chat that // closes without stopping its app-server, and a launch that starts one for every record on disk. -import { mkdtemp, rm } from 'node:fs/promises' +import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it, vi, type Mock } from 'vitest' import type { AgentSessionOwnerProbe } from '../../../shared/agent-session-lease-adjudication' import { hasUnansweredStructuredAgentSessionDispatch } from '../../../shared/structured-agent-session-projection' import { computeAgentSessionPayloadFingerprint } from '../../../shared/agent-session-mutation-envelope' +import type { AgentJournalSubmission } from '../../../shared/agent-session-journal-types' import type { AgentSessionMutationEnvelope, AgentSessionSubscribeEvent @@ -19,7 +20,13 @@ import { AgentSessionRecordStore } from '../../runtime/agent-session-record-stor import type { StructuredAgentSessionAdapter } from './structured-agent-session-adapter' import type { StructuredAgentSessionEventSink } from './structured-agent-session-event-sink' import { StructuredAgentSessionHost } from './structured-agent-session-host' -import type { StructuredAgentSessionHandoffTransport } from './structured-agent-session-handoff-types' +import type { + StructuredAgentSessionHandoffTransport, + StructuredTuiOwner +} from './structured-agent-session-handoff-types' +import { StructuredHandoffTestRequests } from './structured-agent-session-handoff-test-requests' +import { unexpectedProviderExitOutcome } from './structured-agent-session-dead-generation-settlement' +import type { StructuredAgentSessionStatusSink } from './structured-agent-session-status-feed' import { HOST_TEST_NOW as NOW, HOST_TEST_SESSION as SESSION, @@ -43,6 +50,7 @@ let closeSession: Mock let sink: StructuredAgentSessionEventSink | null let hostErrors: unknown[] +let statusSink: StructuredAgentSessionStatusSink function adapter(): StructuredAgentSessionAdapter { return { acquire, @@ -68,6 +76,7 @@ function openHost( releaseGraceMs: GRACE_MS, now: () => NOW, onEventSinkError: ({ error }) => hostErrors.push(error), + statusSink, ...(probeOwner ? { probeOwner: probeOwner as never } : {}), ...(handoffTransport ? { handoffTransport } : {}) }) @@ -119,11 +128,111 @@ function waitOutSeveralGraceWindows(): Promise { return new Promise((resolve) => setTimeout(resolve, GRACE_MS * 20)) } +const handoffRequests = new StructuredHandoffTestRequests( + NOW, + SESSION, + () => store.getRecord(SESSION)?.lease.runtimeFence ?? 0 +) +/** Whether the terminal this host handed the session to can be reached again. */ +let tuiRecoverable: boolean + +/** One operation-id source with the rest of the suite, so the durable ledger sees no duplicate. */ +function handoffRequest(direction: 'to-tui' | 'to-native') { + return handoffRequests.request(direction, 'now', { operationId: hostTestOperationId() }) +} + +function tuiOwner(fence: number, spawnToken: string, transcriptPath: string): StructuredTuiOwner { + return { + terminal: { handle: 'term-tui', tabId: 'tab-tui', paneKey: 'pane-tui', ptyId: 'pty-tui' }, + process: { hostId: 'local', pid: 5200, processStartTimeMs: NOW, spawnToken }, + link: { + linkId: `tui-link-${fence}`, + handle: { provider: 'codex', threadId: THREAD }, + origin: 'resumed', + mintedAtFence: fence, + observedAt: NOW + }, + transcriptPath + } +} + +/** A codex rollout the return trip can import, so a real to-native handoff has history to read. */ +async function writeTuiTranscript(): Promise { + const sessionsDir = join(root, 'codex-home', 'sessions', '2026', '08', '12') + await mkdir(sessionsDir, { recursive: true }) + const transcriptPath = join(sessionsDir, `rollout-2026-08-12T10-00-00-${THREAD}.jsonl`) + await writeFile( + transcriptPath, + `${JSON.stringify({ + type: 'session_meta', + timestamp: '2026-08-12T10:00:00.000Z', + payload: { id: THREAD, session_id: THREAD } + })}\n`, + 'utf8' + ) + return transcriptPath +} + +/** Replaces the current host with one that can hand the session to a terminal and take it back. */ +function openHandoffHost(transcriptPath: string): void { + openHost(undefined, { + hostLabel: 'Test host', + launchTui: async ({ fence, spawnToken }) => tuiOwner(fence, spawnToken, transcriptPath), + reproveTuiOwner: async ({ owner }) => owner, + recoverTuiOwner: async (record) => { + if (!tuiRecoverable) { + throw new Error('the owning terminal could not be reached') + } + return tuiOwner( + record.lease.runtimeFence, + record.lease.reservedSpawnToken ?? 'recovered', + transcriptPath + ) + }, + stopRecoveredOwner: async () => undefined, + closeTuiOwner: async (owner) => ({ transcriptPath: owner.transcriptPath }), + waitForTuiExit: async (owner) => ({ transcriptPath: owner.transcriptPath }), + waitForTuiIdleOrExit: async () => 'idle', + tuiStatus: () => 'idle' + }) +} + +/** Fails the next eviction at `drain-published`, which leaves the session indexed for a retry. */ +function failNextDrain(): void { + vi.spyOn(host['runtimeState'].eventSinkFor(SESSION), 'drained').mockResolvedValueOnce({ + ok: false, + error: new Error('drain barrier lost') + }) +} + +/** The submissions as they stood when the session was forgotten; its journal is gone after that. */ +function captureSettledSubmissions(): { value: AgentJournalSubmission[] } { + const captured: { value: AgentJournalSubmission[] } = { value: [] } + const journal = host['sessions'].get(SESSION)!.journal + const closeJournal = journal.close.bind(journal) + vi.spyOn(journal, 'close').mockImplementation(async () => { + captured.value = journal.snapshot().submissions + await closeJournal() + }) + return captured +} + +async function sendPending(text: string): Promise { + dispatch.mockResolvedValueOnce({ state: 'admitted' }) + const body = hostTestMessage(text) + expect( + await host.send(CALLER, { envelope: envelope('agentSession.send', { body }), body }) + ).toMatchObject({ ok: true, value: { submission: { dispatchState: 'pending' } } }) +} + beforeEach(async () => { root = await mkdtemp(join(tmpdir(), 'orca-surface-lifetime-')) + handoffRequests.reset() + tuiRecoverable = true resetHostTestOperationIds() sink = null hostErrors = [] + statusSink = { publish: vi.fn(), forget: vi.fn() } let generation = 0 acquire = vi.fn(async ({ fence, spawnToken, events }) => { sink = events ?? null @@ -235,6 +344,66 @@ describe('a chat that closes', () => { await expect(settlement).resolves.toBeUndefined() }) + + it('retries teardown after journal close loses its result', async () => { + await attach() + const session = host['sessions'].get(SESSION) + expect(session).toBeDefined() + const closeJournal = session!.journal.close.bind(session!.journal) + vi.spyOn(session!.journal, 'close') + .mockImplementationOnce(async () => { + await closeJournal() + throw new Error('journal close result lost') + }) + .mockImplementation(closeJournal) + + await expect(host.close(SESSION)).rejects.toMatchObject({ + step: 'forget-session', + cause: expect.objectContaining({ message: 'journal close result lost' }) + }) + expect(host.hasSession(SESSION)).toBe(true) + expect(host['sessions'].get(SESSION)?.hasProviderChild).toBe(false) + expect(store.getRecord(SESSION)?.lease).toMatchObject({ + claimStatus: 'released', + ownerProcess: null + }) + expect(statusSink.forget).toHaveBeenCalledWith(SESSION) + + await expect(host.close(SESSION)).resolves.toBeUndefined() + expect(host.hasSession(SESSION)).toBe(false) + expect(closeSession).toHaveBeenCalledOnce() + }) + + it('settles and releases on the retry when a step after the child stopped aborts', async () => { + await attach() + dispatch.mockResolvedValueOnce({ state: 'admitted' }) + const body = hostTestMessage('pending across an aborted eviction') + const sent = await host.send(CALLER, { + envelope: envelope('agentSession.send', { body }), + body + }) + expect(sent).toMatchObject({ ok: true, value: { submission: { dispatchState: 'pending' } } }) + const session = host['sessions'].get(SESSION) + expect(session).toBeDefined() + vi.spyOn(host['runtimeState'].eventSinkFor(SESSION), 'drained').mockResolvedValueOnce({ + ok: false, + error: new Error('drain barrier lost') + }) + const settled = captureSettledSubmissions() + + await expect(host.close(SESSION)).rejects.toMatchObject({ step: 'drain-published' }) + // The child is proven gone, but the wind-down it owes is not done: nothing settled, no release. + expect(session!.hasProviderChild).toBe(false) + expect(store.getRecord(SESSION)?.lease.claimStatus).not.toBe('released') + + await expect(host.close(SESSION)).resolves.toBeUndefined() + expect(closeSession).toHaveBeenCalledOnce() + expect(store.getRecord(SESSION)?.lease).toMatchObject({ + claimStatus: 'released', + ownerProcess: null + }) + expect(hasUnansweredStructuredAgentSessionDispatch(settled.value)).toBe(false) + }) }) describe('a session with a turn in flight', () => { @@ -258,6 +427,35 @@ describe('a session with a turn in flight', () => { }) describe('startup', () => { + it('settles an idle absent owner without chat pollution and resumes the same provider identity', async () => { + await attach() + const beforeRestart = store.getRecord(SESSION) + host['runtimeState'].stopLeaseRenewal() + host['holds'].dispose() + await host['sessions'].get(SESSION)?.journal.close() + host['sessions'].clear() + + store = await AgentSessionRecordStore.open({ directory: join(root, 'store'), hostId: 'local' }) + openHost(async () => ({ outcome: 'pid-absent' })) + await host.restoreReadableSessions() + + const restored = host.history({ sessionId: SESSION, direction: 'tail' }) + expect(restored.ok && restored.page.items.some((item) => item.body.kind === 'status')).toBe( + false + ) + expect(store.getRecord(SESSION)?.lease).toMatchObject({ + claimStatus: 'released', + ownerProcess: null, + settlementRetryRequired: undefined + }) + + await host.hold(SESSION, SURFACE) + expect(store.getRecord(SESSION)?.providerHandleChain.at(-1)?.handle).toEqual( + beforeRestart?.providerHandleChain.at(-1)?.handle + ) + expect(store.getRecord(SESSION)?.providerHandleChain.at(-1)?.origin).toBe('resumed') + }) + it('restores a session for reading without spawning a provider child', async () => { await attach() await reboot() @@ -377,7 +575,7 @@ describe('an unexpected provider exit', () => { history.page.items.some( (item) => item.body.kind === 'status' && item.body.text.includes('journal sink failure') ) - ).toBe(true) + ).toBe(false) // Replace the failed cached sink so suite cleanup can drain the host. ;( @@ -525,13 +723,13 @@ describe('an unexpected provider exit', () => { expect(hostErrors).toContainEqual(expect.objectContaining({ message: 'journal failed' })) const history = host.history({ sessionId: SESSION, direction: 'tail' }) expect(history.ok && history.page.submissions[0]?.dispatchState).toBe('unknown') - expect( - history.ok && - history.page.items.some( - (item) => - item.body.kind === 'status' && item.body.text === 'Provider exited: provider exited' - ) - ).toBe(true) + // A send whose delivery outcome is unknown IS work in progress, so the reassuring outcome is + // written — carrying the cause, and never the old bare `Provider exited: ` row. + const statuses = history.ok + ? history.page.items.flatMap((item) => (item.body.kind === 'status' ? [item.body.text] : [])) + : [] + expect(statuses).toEqual([unexpectedProviderExitOutcome('provider exited')]) + expect(statuses.some((text) => text.startsWith('Provider exited'))).toBe(false) dispatch.mockResolvedValueOnce({ state: 'accepted', @@ -547,6 +745,8 @@ describe('an unexpected provider exit', () => { it('latches a failed exit settlement and blocks attach until the terminal batch is written', async () => { await attach() await host.hold(SESSION, SURFACE) + emitTurnLifecycle('running', 1) + await host.flushStreamedEvents(SESSION) const runtimeState = ( host as unknown as { runtimeState: { lifecycleBarrier: () => Promise<{ ok: false; error: Error }> } @@ -605,3 +805,82 @@ describe('an unexpected provider exit', () => { expect(acquire).toHaveBeenCalledTimes(2) }) }) + +describe('a chat handed to a terminal and taken back', () => { + // The wind-down a close owes belongs to the child in front of it, not to whatever the LAST + // eviction found. A session a terminal owns is indexed with no child of its own, so a close + // there records "nothing owed" — and the trip back re-acquires into that SAME session object. + it('settles and releases the child it was given back', async () => { + const transcriptPath = await writeTuiTranscript() + await host.flushAllStreamedEvents() + openHandoffHost(transcriptPath) + await attach() + expect(await host.requestHandoff(CALLER, handoffRequest('to-tui'))).toMatchObject({ ok: true }) + await vi.waitFor(async () => + expect(await host.handoffStatus(SESSION)).toMatchObject({ owner: 'tui' }) + ) + + // The app restarts and cannot reach the terminal, so this generation restores the session for + // reading and holds no handle to the owner it would otherwise stop on a close. + await host.flushAllStreamedEvents() + store = await AgentSessionRecordStore.open({ directory: join(root, 'store'), hostId: 'local' }) + tuiRecoverable = false + openHandoffHost(transcriptPath) + await host.restoreReadableSessions() + expect(store.getRecord(SESSION)?.lease).toMatchObject({ + runtimeKind: 'tui', + claimStatus: 'live' + }) + + failNextDrain() + await expect(host.close(SESSION)).rejects.toMatchObject({ step: 'drain-published' }) + expect(host.hasSession(SESSION)).toBe(true) + + // The terminal answers again, and the status read the reopened pane makes recovers the owner. + tuiRecoverable = true + expect(await host.handoffStatus(SESSION)).toMatchObject({ owner: 'tui' }) + expect(await host.requestHandoff(CALLER, handoffRequest('to-native'))).toMatchObject({ + ok: true + }) + await vi.waitFor(async () => + expect(await host.handoffStatus(SESSION)).toMatchObject({ owner: 'native' }) + ) + expect(host['sessions'].get(SESSION)?.hasProviderChild).toBe(true) + await sendPending('pending when the retaken chat closes') + const settled = captureSettledSubmissions() + + await expect(host.close(SESSION)).resolves.toBeUndefined() + + expect(store.getRecord(SESSION)?.lease).toMatchObject({ + claimStatus: 'released', + ownerProcess: null + }) + expect(hasUnansweredStructuredAgentSessionDispatch(settled.value)).toBe(false) + }) +}) + +describe('a quit over an eviction that never got its retry', () => { + // Nothing calls `close` a second time when the user quits instead of reopening the chat, so the + // quit sweep is the last thing that can hand the lease back — and it only reaches the session if + // it still counts a stopped child's unfinished wind-down as owed. + it('finishes the wind-down the aborted close left behind', async () => { + await attach() + await sendPending('pending across an abandoned eviction') + const settled = captureSettledSubmissions() + failNextDrain() + + await expect(host.close(SESSION)).rejects.toMatchObject({ step: 'drain-published' }) + expect(host['sessions'].get(SESSION)?.hasProviderChild).toBe(false) + expect(store.getRecord(SESSION)?.lease.claimStatus).not.toBe('released') + + await host.flushAllStreamedEvents() + + expect(closeSession).toHaveBeenCalledOnce() + expect(host.hasSession(SESSION)).toBe(false) + expect(store.getRecord(SESSION)?.lease).toMatchObject({ + claimStatus: 'released', + ownerProcess: null + }) + expect(hasUnansweredStructuredAgentSessionDispatch(settled.value)).toBe(false) + }) +}) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-teardown-handoff-drain.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-teardown-handoff-drain.test.ts index 340d45c05af..12d3e6dfe43 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-teardown-handoff-drain.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-teardown-handoff-drain.test.ts @@ -11,6 +11,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { AgentSessionRecordStore } from '../../runtime/agent-session-record-store' import type { StructuredAgentSessionAdapter } from './structured-agent-session-adapter' import { StructuredAgentSessionHost } from './structured-agent-session-host' +import { structuredAgentSessionHostTeardownPhases } from './structured-agent-session-host-teardown' import { HOST_TEST_NOW as NOW, HOST_TEST_SESSION as SESSION, @@ -147,6 +148,26 @@ describe('structured agent-session host teardown', () => { expect(host.hasSession(SESSION)).toBe(false) }) + it('names every phase, so the quit-path order is pinned rather than incidental', () => { + const noop = async (): Promise => undefined + const phases = structuredAgentSessionHostTeardownPhases({ + holds: { dispose: noop }, + runtimeState: { stopLeaseRenewal: () => undefined, flushAllEventSinks: noop }, + handoffs: { stopTuiHistoryCatchup: () => undefined, drain: noop }, + tasks: { drainAttaches: noop }, + evictOwnedSessions: noop + }) + expect(phases.map((phase) => phase.name)).toEqual([ + 'dispose-holds', + 'stop-lease-renewal', + 'stop-tui-catchup', + 'drain-handoffs', + 'drain-attaches', + 'evict-owned-sessions', + 'flush-event-sinks' + ]) + }) + it('gives up on a wedged handoff instead of holding the quit open', async () => { const request = requests.request('to-tui', 'now', { operationId: hostTestOperationId() }) expect(await host.requestHandoff(CALLER, request)).toMatchObject({ ok: true }) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.test.ts index 813e2f8f3e8..8dc2112b18a 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.test.ts @@ -2,11 +2,18 @@ import { describe, expect, it, vi } from 'vitest' import { agentJournalItemKey } from '../../../shared/agent-session-journal-item-key' import type { AgentJournalRenderItem } from '../../../shared/agent-session-journal-types' import type { AgentSessionRecord } from '../../../shared/agent-session-record' +import { + agentSessionLeaseFixture, + agentSessionRecordFixture +} from '../../../shared/agent-session-record.test-fixture' import type { StructuredAgentSessionHostSession } from './structured-agent-session-host-types' +import { unexpectedProviderExitOutcome } from './structured-agent-session-dead-generation-settlement' import { retryLoadedStructuredAgentSessionSettlement } from './structured-agent-session-settlement-retry' import { isStructuredAgentSessionRecoveryTicketCurrent, settleUnexpectedStructuredAgentSessionExit, + type StructuredAgentSessionUnexpectedExitContext, + type StructuredAgentSessionUnexpectedExitSession, type StructuredAgentSessionRecoveryTicket } from './structured-agent-session-unexpected-exit' @@ -17,8 +24,7 @@ const ticket: StructuredAgentSessionRecoveryTicket = { sessionId: SESSION, releasedFence: 8, deadAcquisitionGeneration: GENERATION, - stableSettlementId: 'settlement-1', - settlementRetryRequired: false + stableSettlementId: 'settlement-1' } function recoveryContext(input: { @@ -48,7 +54,11 @@ function recoveryContext(input: { function lifecycleItem( turnId: string, sequence: number, - turnLifecycle: { state: 'running' | 'completed'; startedAt: number; completedAt?: number } + turnLifecycle: { + state: 'running' | 'completed' | 'interrupted' + startedAt: number + completedAt?: number + } ): AgentJournalRenderItem { return { itemId: agentJournalItemKey({ provider: 'codex', threadId: 'thread-1', turnId, ordinal: 0 }), @@ -59,6 +69,39 @@ function lifecycleItem( } } +function liveRecord(): AgentSessionRecord { + return agentSessionRecordFixture( + agentSessionLeaseFixture({ + sessionId: SESSION, + runtimeKind: 'native', + runtimeFence: 7, + handoffStage: null, + ownerProcess: { + hostId: 'local', + pid: 4242, + processStartTimeMs: 1, + spawnToken: 'spawn-1' + }, + reservedSpawnToken: 'spawn-1', + claimStatus: 'live', + unreconciled: false + }) + ) +} + +function mutableStore() { + let record = liveRecord() + return { + store: { + getRecord: () => record, + transitionHandoff: async ( + _sessionId: string, + transition: (current: AgentSessionRecord) => AgentSessionRecord + ) => (record = transition(record)) + } + } +} + describe('provider-exit recovery tickets', () => { it.each([undefined, 2_000])('keeps exit receipt %s on retry', async (observedAt) => { let now = observedAt === undefined ? 2_000 : 30_000 @@ -200,7 +243,7 @@ describe('provider-exit recovery tickets', () => { } ) - expect(result).toMatchObject({ settlementRetryRequired: false, releasedFence: 8 }) + expect(result).toMatchObject({ releasedFence: 8 }) expect(session.journal.markPendingSubmissionsUnknown).toHaveBeenCalledWith( 7, 'provider_exited_before_acknowledgement' @@ -208,7 +251,7 @@ describe('provider-exit recovery tickets', () => { expect(session.hasProviderChild).toBe(false) // The running row is revised to interrupted at exit receipt, never tombstoned. expect(appendLifecycleBatch).toHaveBeenCalledExactlyOnceWith({ - settlementId: `provider-exit:${SESSION}:7:${GENERATION}`, + settlementId: `dead-generation:provider-exit:${SESSION}:7:${GENERATION}`, fence: 7, recovered: true, mutations: [ @@ -218,7 +261,7 @@ describe('provider-exit recovery tickets', () => { provider: 'orca', clientMessageId: `provider-exit:${SESSION}:7:${GENERATION}` }, - body: { kind: 'status', text: 'Provider exited: provider exited' } + body: { kind: 'status', text: unexpectedProviderExitOutcome('provider exited') } }, { kind: 'item', @@ -235,71 +278,149 @@ describe('provider-exit recovery tickets', () => { }) }) + it.each([ + { initialState: 'running' as const, terminalState: 'completed' as const, expectedOutcomes: 0 }, + { + initialState: 'running' as const, + terminalState: 'interrupted' as const, + expectedOutcomes: 1 + }, + { + initialState: 'interrupted' as const, + terminalState: 'interrupted' as const, + expectedOutcomes: 1 + } + ])( + 'reports $expectedOutcomes outcome(s) when the barrier sees $initialState then $terminalState', + async ({ initialState, terminalState, expectedOutcomes }) => { + let items = [ + lifecycleItem('turn-1', 1, { + state: initialState, + startedAt: 30, + ...(initialState === 'running' ? {} : { completedAt: 40 }) + }) + ] + const appendLifecycleBatch = vi.fn(async (_input: { mutations: readonly unknown[] }) => ({ + epoch: 'epoch-1', + sequence: 3 + })) + const session: StructuredAgentSessionUnexpectedExitSession = { + hasProviderChild: true, + fence: 7, + acquisitionGeneration: GENERATION, + journal: { + snapshot: () => ({ items }), + appendLifecycleBatch, + markPendingSubmissionsUnknown: vi.fn(async () => []) + } + } + + const { store } = mutableStore() + const context: StructuredAgentSessionUnexpectedExitContext = { + store, + sessions: new Map([[SESSION, session]]), + flushLifecycle: async () => { + items = [ + lifecycleItem('turn-1', 1, { + state: terminalState, + startedAt: 30, + completedAt: 40 + }) + ] + return { ok: true } + }, + publishFence: vi.fn(), + hasResumeCapableHolder: () => true, + serialize: async (_sessionId: string, task: () => Promise) => task(), + now: () => 1_234 + } + await settleUnexpectedStructuredAgentSessionExit(context, { + type: 'ended', + sessionId: SESSION, + reason: 'provider exited after completing the turn', + cause: 'unexpected-exit', + fence: 7, + acquisitionGeneration: GENERATION, + observedAt: 40 + }) + + expect(appendLifecycleBatch).toHaveBeenCalledTimes(expectedOutcomes) + if (expectedOutcomes > 0) { + expect(appendLifecycleBatch.mock.calls[0]?.[0].mutations).toEqual([ + expect.objectContaining({ + body: { + kind: 'status', + text: unexpectedProviderExitOutcome('provider exited after completing the turn') + } + }) + ]) + } + } + ) + it('settles a submission the dead child never acknowledged', async () => { const markPendingSubmissionsUnknown = vi.fn(async () => ['client-1']) - const session = { + const session: StructuredAgentSessionUnexpectedExitSession = { hasProviderChild: true, fence: 7, acquisitionGeneration: GENERATION, journal: { snapshot: () => ({ items: [] }), appendLifecycleBatch: vi.fn(async () => ({ epoch: 'epoch-1', sequence: 1 })), - markPendingSubmissionsUnknown + markPendingSubmissionsUnknown, + submissions: () => [{ clientMessageId: 'client-1', dispatchState: 'pending' }] } - } as unknown as StructuredAgentSessionHostSession + } - await settleUnexpectedStructuredAgentSessionExit( - { - store: { - getRecord: () => ({ - lease: { - handoffStage: null, - runtimeFence: 7, - runtimeKind: 'native', - claimStatus: 'live', - ownerProcess: 'provider', - reservedSpawnToken: null, - processlessAt: null - } - }), - transitionHandoff: async () => ({ lease: { runtimeFence: 8 } }) - }, - sessions: new Map([[SESSION, session]]), - flushLifecycle: async () => ({ ok: true }), - publishFence: vi.fn(), - hasResumeCapableHolder: () => true, - serialize: async (_sessionId, task: () => Promise) => task(), - now: () => 1 - } as never, - { - type: 'ended', - sessionId: SESSION, - reason: 'provider exited', - cause: 'unexpected-exit', - fence: 7, - acquisitionGeneration: GENERATION - } - ) + const { store } = mutableStore() + const context: StructuredAgentSessionUnexpectedExitContext = { + store, + sessions: new Map([[SESSION, session]]), + flushLifecycle: async () => ({ ok: true }), + publishFence: vi.fn(), + hasResumeCapableHolder: () => true, + serialize: async (_sessionId: string, task: () => Promise) => task(), + now: () => 1 + } + await settleUnexpectedStructuredAgentSessionExit(context, { + type: 'ended', + sessionId: SESSION, + reason: 'provider exited', + cause: 'unexpected-exit', + fence: 7, + acquisitionGeneration: GENERATION + }) expect(markPendingSubmissionsUnknown).toHaveBeenCalledWith( 7, 'provider_exited_before_acknowledgement' ) + expect(session.journal.appendLifecycleBatch).toHaveBeenCalledWith( + expect.objectContaining({ + mutations: [ + expect.objectContaining({ + body: { kind: 'status', text: unexpectedProviderExitOutcome('provider exited') } + }) + ] + }) + ) }) it('does not release or reacquire while terminal settlement retry is still failing', async () => { - const session = { + const session: StructuredAgentSessionUnexpectedExitSession = { hasProviderChild: true, fence: 7, acquisitionGeneration: GENERATION, journal: { markPendingSubmissionsUnknown: vi.fn(async () => []), - snapshot: () => ({ items: [] }), + snapshot: () => ({ + items: [lifecycleItem('turn-failing', 1, { state: 'running', startedAt: 1 })] + }), appendLifecycleBatch: vi.fn(async () => { throw new Error('journal still unavailable') }) } - } as unknown as StructuredAgentSessionHostSession + } const release = vi.fn() const publishFence = vi.fn() const event = { @@ -310,32 +431,18 @@ describe('provider-exit recovery tickets', () => { fence: 7, acquisitionGeneration: GENERATION } - const result = await settleUnexpectedStructuredAgentSessionExit( - { - store: { - getRecord: () => ({ - lease: { - handoffStage: null, - runtimeFence: 7, - runtimeKind: 'native', - claimStatus: 'live', - ownerProcess: 'provider', - reservedSpawnToken: null, - processlessAt: null - } - }), - transitionHandoff: async () => ({ lease: { runtimeFence: 8 } }) - }, - sessions: new Map([[SESSION, session]]), - flushLifecycle: async () => ({ ok: false, error: new Error('sink failed') }), - publishFence, - hasResumeCapableHolder: () => true, - serialize: async (_sessionId, task) => task(), - now: () => 1, - onBarrierError: release - } as never, - event - ) + const { store } = mutableStore() + const context: StructuredAgentSessionUnexpectedExitContext = { + store, + sessions: new Map([[SESSION, session]]), + flushLifecycle: async () => ({ ok: false, error: new Error('sink failed') }), + publishFence, + hasResumeCapableHolder: () => true, + serialize: async (_sessionId, task) => task(), + now: () => 1, + onBarrierError: release + } + const result = await settleUnexpectedStructuredAgentSessionExit(context, event) expect(result).toBeNull() expect(session.hasProviderChild).toBe(false) diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.ts index c4b32f71647..11d004089ca 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-unexpected-exit.ts @@ -1,23 +1,18 @@ -import { parseAgentJournalItemKey } from '../../../shared/agent-session-journal-item-key' -import { - runningTurnLifecycleRevisions, - type StructuredAgentSessionTurnVerdict -} from './structured-agent-session-stale-turn-verdict' -import type { - AgentJournalItemBody, - AgentJournalRenderItem -} from '../../../shared/agent-session-journal-types' -import type { AgentSessionRecordStore } from '../../runtime/agent-session-record-store' -import { partitionJournalLifecycleMutations } from '../agent-session-journal/journal-lifecycle-batch-partition' -import type { JournalLifecycleMutationInput } from '../agent-session-journal/journal-row-builders' -import { - boundJournalStatusText, - cancelledJournalPromptBody -} from '../agent-session-journal/journal-prompt-body-bounds' import type { StructuredAgentSessionLifecycleEvent } from './structured-agent-session-adapter' import type { StructuredAgentSessionHostSession } from './structured-agent-session-host-types' -import { releaseStoredStructuredAgentSessionOwnerAfterUnexpectedExit } from './structured-agent-session-lease-release' +import { + releaseStoredStructuredAgentSessionOwnerAfterUnexpectedExit, + type StructuredAgentSessionLeaseStore +} from './structured-agent-session-lease-release' import type { StructuredAgentSessionSinkBarrier } from './structured-agent-session-event-sink' +import { + captureUnfinishedStructuredAgentSessionWork, + MAX_UNEXPECTED_EXIT_REASON_CHARS, + settleStructuredAgentSessionDeadGeneration, + type DeadGenerationJournal, + unfinishedStructuredAgentSessionWorkWasInterrupted +} from './structured-agent-session-dead-generation-settlement' +import type { StructuredAgentSessionTurnVerdict } from './structured-agent-session-stale-turn-verdict' type UnexpectedExitLifecycleEvent = StructuredAgentSessionLifecycleEvent & { cause: 'unexpected-exit' @@ -28,14 +23,22 @@ export type StructuredAgentSessionRecoveryTicket = { releasedFence: number deadAcquisitionGeneration: string stableSettlementId: string - settlementRetryRequired: boolean } -export type StructuredAgentSessionUnexpectedExitContext = { - store: AgentSessionRecordStore - sessions: Map +export type StructuredAgentSessionUnexpectedExitSession = { + journal: DeadGenerationJournal + hasProviderChild: boolean + fence: number + acquisitionGeneration: string | null +} + +export type StructuredAgentSessionUnexpectedExitContext< + TSession extends StructuredAgentSessionUnexpectedExitSession = StructuredAgentSessionHostSession +> = { + store: StructuredAgentSessionLeaseStore + sessions: Map flushLifecycle: (sessionId: string) => Promise - publishFence: (sessionId: string, session: StructuredAgentSessionHostSession) => void + publishFence: (sessionId: string, session: TSession) => void publishStatus?: (sessionId: string) => void hasResumeCapableHolder: (sessionId: string) => boolean serialize: (sessionId: string, task: () => Promise) => Promise @@ -43,8 +46,10 @@ export type StructuredAgentSessionUnexpectedExitContext = { onBarrierError?: (sessionId: string, error: unknown) => void } -export async function settleUnexpectedStructuredAgentSessionExit( - context: StructuredAgentSessionUnexpectedExitContext, +export async function settleUnexpectedStructuredAgentSessionExit< + TSession extends StructuredAgentSessionUnexpectedExitSession +>( + context: StructuredAgentSessionUnexpectedExitContext, event: StructuredAgentSessionLifecycleEvent ): Promise { if (event.cause !== 'unexpected-exit') { @@ -70,9 +75,9 @@ export async function settleUnexpectedStructuredAgentSessionExit( return null } - let settlementRetryRequired = false let settlementFailed = false const stableSettlementId = providerExitSettlementId(unexpectedEvent) + const unfinishedWork = captureUnfinishedStructuredAgentSessionWork(session.journal) let released: Awaited< ReturnType > | null = null @@ -80,37 +85,23 @@ export async function settleUnexpectedStructuredAgentSessionExit( try { const barrier = await context.flushLifecycle(unexpectedEvent.sessionId) if (!barrier.ok) { - settlementRetryRequired = true context.onBarrierError?.(unexpectedEvent.sessionId, barrier.error) } } catch (error) { - settlementRetryRequired = true context.onBarrierError?.(unexpectedEvent.sessionId, error) } - try { - await session.journal.markPendingSubmissionsUnknown( - session.fence, - 'provider_exited_before_acknowledgement' + settlementFailed = !(await retryUnexpectedExitSettlement({ + context, + event: unexpectedEvent, + session, + stableSettlementId, + verdict: { state: 'interrupted', completedAt: observedAt }, + showUnexpectedExitOutcome: unfinishedStructuredAgentSessionWorkWasInterrupted( + unfinishedWork, + session.journal, + observedAt ) - } catch (error) { - settlementRetryRequired = true - context.onBarrierError?.(unexpectedEvent.sessionId, error) - } - if (unexpectedEvent.settlementRetryRequired || settlementRetryRequired) { - const retried = await retryUnexpectedExitSettlement({ - context, - event: unexpectedEvent, - session, - stableSettlementId, - verdict: { state: 'interrupted', completedAt: observedAt } - }) - if (!retried) { - settlementFailed = true - } - if (!settlementFailed) { - settlementRetryRequired = false - } - } + })) } finally { // Provider exit was positively observed, so release the owner even when // terminal settlement could not be durably accepted. @@ -127,7 +118,8 @@ export async function settleUnexpectedStructuredAgentSessionExit( ? { settlementRetry: { settlementId: stableSettlementId, - detail: `provider exited: ${unexpectedEvent.reason}`.slice(0, 512) + // Bare cause: the retry renders it, and `exit-observed` already says the rest. + detail: unexpectedEvent.reason.slice(0, MAX_UNEXPECTED_EXIT_REASON_CHARS) } } : {}) @@ -153,23 +145,28 @@ export async function settleUnexpectedStructuredAgentSessionExit( sessionId: unexpectedEvent.sessionId, releasedFence: released.lease.runtimeFence, deadAcquisitionGeneration: unexpectedEvent.acquisitionGeneration, - stableSettlementId, - settlementRetryRequired + stableSettlementId } }) } export function isStructuredAgentSessionRecoveryTicketCurrent( - context: Pick< - StructuredAgentSessionUnexpectedExitContext, - 'store' | 'sessions' | 'hasResumeCapableHolder' - >, + context: { + store: Pick + sessions: Map< + string, + Pick< + StructuredAgentSessionUnexpectedExitSession, + 'hasProviderChild' | 'fence' | 'acquisitionGeneration' + > + > + hasResumeCapableHolder: (sessionId: string) => boolean + }, ticket: StructuredAgentSessionRecoveryTicket ): boolean { const session = context.sessions.get(ticket.sessionId) const record = context.store.getRecord(ticket.sessionId) return ( - !ticket.settlementRetryRequired && session?.hasProviderChild === false && session.fence === ticket.releasedFence && session.acquisitionGeneration === ticket.deadAcquisitionGeneration && @@ -180,75 +177,25 @@ export function isStructuredAgentSessionRecoveryTicketCurrent( ) } -export async function retryUnexpectedExitSettlement(input: { +async function retryUnexpectedExitSettlement(input: { context: Pick event: UnexpectedExitLifecycleEvent - session: Pick + session: Pick stableSettlementId: string verdict: StructuredAgentSessionTurnVerdict + showUnexpectedExitOutcome?: boolean }): Promise { - try { - await input.session.journal.markPendingSubmissionsUnknown( - input.session.fence, - 'provider_exited_before_acknowledgement' - ) - const mutations = unexpectedExitFallbackMutations( - input.event, - input.session, - input.stableSettlementId, - input.verdict - ) - for (const chunk of partitionJournalLifecycleMutations(input.stableSettlementId, mutations)) { - await input.session.journal.appendLifecycleBatch({ - settlementId: chunk.settlementId, - fence: input.session.fence, - recovered: true, - mutations: chunk.mutations - }) - } - return true - } catch (error) { - input.context.onBarrierError?.(input.event.sessionId, error) - return false - } -} - -function unexpectedExitFallbackMutations( - event: UnexpectedExitLifecycleEvent, - session: Pick, - stableSettlementId: string, - verdict: StructuredAgentSessionTurnVerdict -): JournalLifecycleMutationInput[] { - const mutations: JournalLifecycleMutationInput[] = [] - const { items } = session.journal.snapshot() - for (const item of items) { - const identity = parseAgentJournalItemKey(item.itemId) - if (!identity) { - continue - } - const terminal = terminalExitBody(item) - if (terminal) { - mutations.push({ kind: 'item', identity, body: terminal }) - } - } - mutations.push({ - kind: 'item', - identity: { provider: 'orca', clientMessageId: stableSettlementId }, - body: { kind: 'status', text: boundJournalStatusText(`Provider exited: ${event.reason}`) } + return settleStructuredAgentSessionDeadGeneration({ + journal: input.session.journal, + sessionId: input.event.sessionId, + fence: input.session.fence, + settlementId: input.stableSettlementId, + verdict: input.verdict, + pendingSubmissionReason: 'provider_exited_before_acknowledgement', + showUnexpectedExitOutcome: input.showUnexpectedExitOutcome, + unexpectedExitReason: input.event.reason, + onError: input.context.onBarrierError }) - // Lifecycle rows settle last, in place: the turn's endpoints outlive the child. - mutations.push(...runningTurnLifecycleRevisions(items, verdict)) - return mutations -} - -function terminalExitBody(item: AgentJournalRenderItem): AgentJournalItemBody | null { - if (item.body.kind === 'tool-call' && item.body.state === 'running') { - return { ...item.body, state: 'failed' } - } - if (item.body.kind === 'approval' || item.body.kind === 'question') { - return item.body.resolution.state === 'pending' ? cancelledJournalPromptBody(item.body) : null - } - return null } function providerExitSettlementId(event: UnexpectedExitLifecycleEvent): string { diff --git a/src/main/native-chat/agent-session-wire/structured-conversation-command.test.ts b/src/main/native-chat/agent-session-wire/structured-conversation-command.test.ts index a2d15da389f..68939c0889d 100644 --- a/src/main/native-chat/agent-session-wire/structured-conversation-command.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-conversation-command.test.ts @@ -146,6 +146,23 @@ describe('host conversation commands', () => { expect(compact).toHaveBeenCalledTimes(1) }) + /** The replacement seeds from what the provider reports now, not from what the + * retired record happened to store — the same rule acquire and handoff apply. */ + it('adopts the reported Fast preference into the replacement record', async () => { + adapter.readOptions = async () => ({ + models: [], + current: { model: 'test-model', effort: 'high', fastMode: false } + }) + const result = await host.conversationCommand(caller, commandParams('clear')) + expect(result.ok).toBe(true) + if (!result.ok) { + return + } + expect(store.getRecord(result.value.replacementSessionId!)).toMatchObject({ + options: { model: 'test-model', effort: 'high', fastMode: 'false' } + }) + }) + it('clears with a fresh record and effective options, retaining old history and idempotent mapping', async () => { const before = store.getRecord(HOST_TEST_SESSION)! const params = commandParams('clear') diff --git a/src/main/native-chat/transcript-stream-lines.ts b/src/main/native-chat/transcript-stream-lines.ts index 5396ecd076a..4a58b4e180f 100644 --- a/src/main/native-chat/transcript-stream-lines.ts +++ b/src/main/native-chat/transcript-stream-lines.ts @@ -13,44 +13,17 @@ export async function decodeTranscriptStream( includeTrailingLine: boolean ): Promise<{ messages: NativeChatMessage[]; consumedBytes: number }> { const messages: NativeChatMessage[] = [] - // Why: a Buffer chunk can end mid-codepoint, and decoding it standalone would - // both corrupt the line and shift `consumedBytes` (which seeds fallback ids). - const decoder = new StringDecoder('utf8') - let pending: string[] = [] let consumedBytes = 0 - + const framer = createTranscriptLineFramer((line, byteLength, terminated) => { + if (terminated || includeTrailingLine) { + decodeLine(line, consumedBytes) + consumedBytes += byteLength + } + }) for await (const chunk of stream) { - const text = typeof chunk === 'string' ? chunk : decoder.write(Buffer.from(chunk)) - // Only the new chunk is scanned; partial records wait in `pending` unrescanned. - let lineStart = 0 - let newlineIndex = text.indexOf('\n') - while (newlineIndex !== -1) { - let segment = text.slice(lineStart, newlineIndex + 1) - if (pending.length > 0) { - // Join a fragmented record only once, including split string surrogate pairs. - pending.push(segment) - segment = pending.join('') - pending = [] - } - decodeLine(segment.slice(0, -1), consumedBytes) - consumedBytes += Buffer.byteLength(segment, 'utf8') - lineStart = newlineIndex + 1 - newlineIndex = text.indexOf('\n', lineStart) - } - if (lineStart < text.length) { - pending.push(text.slice(lineStart)) - } - } - const tail = decoder.end() - if (tail) { - pending.push(tail) - } - - if (includeTrailingLine && pending.length > 0) { - const line = pending.join('') - decodeLine(line, consumedBytes) - consumedBytes += Buffer.byteLength(line, 'utf8') + framer.write(chunk) } + framer.end() return { messages, consumedBytes } @@ -65,3 +38,64 @@ export async function decodeTranscriptStream( } } } + +type TranscriptLine = { line: string; byteLength: number; terminated: boolean } + +export async function* splitTranscriptStreamLines( + stream: AsyncIterable +): AsyncGenerator { + let records: TranscriptLine[] = [] + const framer = createTranscriptLineFramer((line, byteLength, terminated) => { + records.push({ line, byteLength, terminated }) + }) + for await (const chunk of stream) { + framer.write(chunk) + for (const record of records) { + yield record + } + records = [] + } + framer.end() + for (const record of records) { + yield record + } +} + +/** Frame chunks synchronously so native decoding avoids a promise per record. */ +function createTranscriptLineFramer( + emit: (line: string, byteLength: number, terminated: boolean) => void +): { write(chunk: Buffer | string): void; end(): void } { + const decoder = new StringDecoder('utf8') + let pending: string[] = [] + return { write, end } + + function write(chunk: Buffer | string): void { + const text = typeof chunk === 'string' ? chunk : decoder.write(chunk) + let lineStart = 0 + let newlineIndex = text.indexOf('\n') + while (newlineIndex !== -1) { + let segment = text.slice(lineStart, newlineIndex + 1) + if (pending.length > 0) { + pending.push(segment) + segment = pending.join('') + pending = [] + } + emit(segment.slice(0, -1), Buffer.byteLength(segment, 'utf8'), true) + lineStart = newlineIndex + 1 + newlineIndex = text.indexOf('\n', lineStart) + } + if (lineStart < text.length) { + pending.push(text.slice(lineStart)) + } + } + + function end(): void { + const tail = decoder.end() + if (tail) { + pending.push(tail) + } + const line = pending.join('') + emit(line, Buffer.byteLength(line, 'utf8'), false) + pending = [] + } +} diff --git a/src/main/notifications/notification-delivery-service.test.ts b/src/main/notifications/notification-delivery-service.test.ts new file mode 100644 index 00000000000..1e1b09bfc42 --- /dev/null +++ b/src/main/notifications/notification-delivery-service.test.ts @@ -0,0 +1,163 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' +import type { BrowserWindow } from 'electron' +import { createNotificationDeliveryService } from './notification-delivery-service' +import type { NotificationDeliveryDependencies } from './notification-delivery-service' +import type { + NotificationDispatchRequest, + NotificationSettings +} from '../../shared/notification-settings-types' + +function makeSettings(overrides: Partial = {}): NotificationSettings { + return { + enabled: true, + agentTaskComplete: true, + terminalBell: true, + suppressWhenFocused: false, + customSoundId: 'system', + customSoundPath: null, + customSoundVolume: 1, + ...overrides + } +} + +function makeRequest( + overrides: Partial = {} +): NotificationDispatchRequest { + return { + source: 'agent-task-complete', + worktreeId: 'wt-1', + worktreeLabel: 'wt-1', + ...overrides + } +} + +type Harness = { + deps: NotificationDeliveryDependencies + order: string[] + setTrayAttention: ReturnType + dispatchMobileNotification: ReturnType + deliverNative: ReturnType +} + +let now = 1_000 + +/** The delivery policy only asks a window whether it is focused. */ +function makeFocusedWindowStub(): BrowserWindow { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the service reads only isFocused(); a full BrowserWindow cannot be constructed outside Electron. + return { isFocused: () => true } as unknown as BrowserWindow +} + +function makeHarness(settings: NotificationSettings, windowVisible = false): Harness { + const order: string[] = [] + const setTrayAttention = vi.fn(() => order.push('tray')) + const dispatchMobileNotification = vi.fn(() => order.push('mobile')) + const deliverNative = vi.fn(() => { + order.push('native') + return { delivered: true } as const + }) + return { + order, + setTrayAttention, + dispatchMobileNotification, + deliverNative, + deps: { + readNotificationSettings: () => settings, + findActiveWindow: () => null, + isWindowVisible: () => windowVisible, + setTrayAttention, + isNotificationSupported: () => true, + dispatchMobileNotification, + readAuthorizationStatus: () => Promise.resolve('authorized'), + recordDeliveryOutcome: vi.fn(), + deliverNative, + platform: 'linux', + now: () => now + } + } +} + +beforeEach(() => { + now += 60_000 +}) + +describe('createNotificationDeliveryService', () => { + it('lights the tray dot before the enabled/cooldown gates can reject the event', () => { + const harness = makeHarness(makeSettings({ enabled: false })) + const result = createNotificationDeliveryService(harness.deps).dispatch(makeRequest()) + + expect(harness.setTrayAttention).toHaveBeenCalledWith(true) + expect(result).toEqual({ delivered: false, reason: 'disabled' }) + expect(harness.deliverNative).not.toHaveBeenCalled() + expect(harness.order[0]).toBe('tray') + }) + + it('leaves the tray dot alone while the window is visible', () => { + const harness = makeHarness(makeSettings(), true) + createNotificationDeliveryService(harness.deps).dispatch(makeRequest()) + expect(harness.setTrayAttention).not.toHaveBeenCalled() + }) + + it('fans out to mobile before the desktop-disabled early return', () => { + const harness = makeHarness(makeSettings({ agentTaskComplete: false })) + const result = createNotificationDeliveryService(harness.deps).dispatch(makeRequest()) + + expect(result).toEqual({ delivered: false, reason: 'source-disabled' }) + expect(harness.dispatchMobileNotification).toHaveBeenCalledWith( + expect.objectContaining({ desktopAllowed: false, source: 'agent-task-complete' }) + ) + expect(harness.order).toEqual(['tray', 'mobile']) + }) + + it('keeps the desktop source gates distinct per source', () => { + const harness = makeHarness(makeSettings({ terminalBell: false })) + const service = createNotificationDeliveryService(harness.deps) + expect(service.dispatch(makeRequest({ source: 'terminal-bell' }))).toEqual({ + delivered: false, + reason: 'source-disabled' + }) + expect(service.dispatch(makeRequest({ worktreeId: 'wt-2', worktreeLabel: 'wt-2' }))).toEqual({ + delivered: true + }) + }) + + it('suppresses a focused active workspace without touching mobile delivery', () => { + const harness = makeHarness(makeSettings({ suppressWhenFocused: true })) + const focusedWindow = makeFocusedWindowStub() + harness.deps.findActiveWindow = () => focusedWindow + const result = createNotificationDeliveryService(harness.deps).dispatch( + makeRequest({ isActiveWorktree: true }) + ) + + expect(result).toEqual({ delivered: false, reason: 'suppressed-focus' }) + expect(harness.dispatchMobileNotification).toHaveBeenCalledTimes(1) + }) + + it('dedupes desktop bursts per workspace but still reports the first delivery', () => { + const harness = makeHarness(makeSettings()) + const service = createNotificationDeliveryService(harness.deps) + expect(service.dispatch(makeRequest())).toEqual({ delivered: true }) + expect(service.dispatch(makeRequest({ source: 'terminal-bell' }))).toEqual({ + delivered: false, + reason: 'cooldown' + }) + }) + + it('skips mobile fan-out entirely when no runtime is paired', () => { + const harness = makeHarness(makeSettings()) + harness.deps.dispatchMobileNotification = null + expect(createNotificationDeliveryService(harness.deps).dispatch(makeRequest())).toEqual({ + delivered: true + }) + expect(harness.dispatchMobileNotification).not.toHaveBeenCalled() + }) + + it('reports blocked-by-system on macOS when permission is undecided', async () => { + const harness = makeHarness(makeSettings()) + harness.deps.platform = 'darwin' + harness.deps.readAuthorizationStatus = () => Promise.resolve('not-determined') + await expect( + createNotificationDeliveryService(harness.deps).dispatch(makeRequest()) + ).resolves.toEqual({ delivered: false, reason: 'blocked-by-system' }) + expect(harness.deliverNative).not.toHaveBeenCalled() + }) +}) diff --git a/src/main/notifications/notification-delivery-service.ts b/src/main/notifications/notification-delivery-service.ts new file mode 100644 index 00000000000..7ca85c61f92 --- /dev/null +++ b/src/main/notifications/notification-delivery-service.ts @@ -0,0 +1,148 @@ +/** + * Desktop delivery policy for dispatched notifications. + * + * Lifted out of the `notifications:dispatch` IPC closure so the ordering that matters — + * tray attention before the gates, mobile fan-out before the desktop early returns — is + * expressed once against injected collaborators instead of ambient Electron singletons. + */ +import type { BrowserWindow } from 'electron' +import type { + NotificationDispatchRequest, + NotificationDispatchResult, + NotificationSettings +} from '../../shared/notification-settings-types' +import type { OrcaRuntimeService } from '../runtime/orca-runtime' +import { buildNotificationOptions } from '../ipc/notification-options' +import { reserveNotificationCooldown } from '../ipc/notification-burst-cooldown' + +export type NotificationDeliveryDependencies = { + readNotificationSettings: () => NotificationSettings + /** The window the user would see the banner on, or null when none is open. */ + findActiveWindow: () => BrowserWindow | null + isWindowVisible: (window: BrowserWindow | null) => boolean + setTrayAttention: (attention: boolean) => void + isNotificationSupported: () => boolean + /** Null when no runtime is paired, so mobile fan-out is skipped entirely. */ + dispatchMobileNotification: OrcaRuntimeService['dispatchMobileNotification'] | null + readAuthorizationStatus: () => Promise< + 'authorized' | 'denied' | 'not-determined' | 'unknown' | null + > + recordDeliveryOutcome: (outcome: 'delivered' | 'failed') => void + deliverNative: ( + request: NotificationDispatchRequest, + options: ReturnType, + settings: NotificationSettings + ) => NotificationDispatchResult | Promise + platform: NodeJS.Platform + now: () => number +} + +export type NotificationDeliveryService = { + dispatch: ( + request: NotificationDispatchRequest + ) => NotificationDispatchResult | Promise +} + +export function createNotificationDeliveryService( + deps: NotificationDeliveryDependencies +): NotificationDeliveryService { + const recentDesktopNotifications = new Map() + const recentMobileNotifications = new Map() + + const dedupeKeyFor = (request: NotificationDispatchRequest): string => + request.worktreeId ?? request.worktreeLabel ?? 'global' + + return { + dispatch: (request) => { + // Why: light the tray attention dot before the cooldown/focus/enabled gates so they + // can't hold it back (clears on window show/restore; see index.ts). + if (request.source === 'agent-task-complete' || request.source === 'terminal-bell') { + if (!deps.isWindowVisible(deps.findActiveWindow())) { + deps.setTrayAttention(true) + } + } + + const settings = deps.readNotificationSettings() + const desktopAllowed = + settings.enabled && + (request.source !== 'agent-task-complete' || settings.agentTaskComplete) && + (request.source !== 'terminal-bell' || settings.terminalBell) + + const notificationOptions = buildNotificationOptions(request) + + // Why: desktop focus only means this computer sees the worktree; the paired phone may still need the alert. + if (deps.dispatchMobileNotification && request.source !== 'test') { + if ( + reserveNotificationCooldown( + recentMobileNotifications, + JSON.stringify([ + desktopAllowed, + request.source, + request.agentState, + dedupeKeyFor(request) + ]), + deps.now() + ) + ) { + deps.dispatchMobileNotification({ + type: 'notification', + emittedAt: deps.now(), + source: request.source, + ...(!desktopAllowed ? { desktopAllowed: false } : {}), + title: notificationOptions.title, + body: notificationOptions.body, + worktreeId: request.worktreeId, + ...(request.notificationId ? { notificationId: request.notificationId } : {}), + // Why: background push needs the agent's real state to pick "needs input" + // vs "finished" — and to stay silent while the agent is still working. + ...(request.agentState ? { agentState: request.agentState } : {}) + }) + } + } + + if (!desktopAllowed) { + return { delivered: false, reason: settings.enabled ? 'source-disabled' : 'disabled' } + } + + const browserWindow = deps.findActiveWindow() + if ( + settings.suppressWhenFocused && + request.isActiveWorktree && + browserWindow && + browserWindow.isFocused() + ) { + return { delivered: false, reason: 'suppressed-focus' } + } + + // Why: the Settings test button is an explicit, often-repeated user action, so it bypasses burst dedupe. + if (request.source !== 'test') { + // Dedupe by worktree, not source — agent-finish and terminal-bell often fire in one chunk; surface only the first. + if ( + !reserveNotificationCooldown( + recentDesktopNotifications, + dedupeKeyFor(request), + deps.now() + ) + ) { + return { delivered: false, reason: 'cooldown' } + } + } + + if (!deps.isNotificationSupported()) { + return { delivered: false, reason: 'not-supported' } + } + + if (deps.platform !== 'darwin') { + return deps.deliverNative(request, notificationOptions, settings) + } + // Why: macOS silently swallows notifications while permission is denied/undecided (verified macOS 26); skip so the renderer can show a fallback. + return deps.readAuthorizationStatus().then((authorization) => { + if (authorization === 'denied' || authorization === 'not-determined') { + deps.recordDeliveryOutcome('failed') + return { delivered: false, reason: 'blocked-by-system' } + } + return deps.deliverNative(request, notificationOptions, settings) + }) + } + } +} diff --git a/src/main/orca-profiles/profile-cloud-pkce.test.ts b/src/main/orca-profiles/profile-cloud-pkce.test.ts index 357a5389465..81b706f82bc 100644 --- a/src/main/orca-profiles/profile-cloud-pkce.test.ts +++ b/src/main/orca-profiles/profile-cloud-pkce.test.ts @@ -114,9 +114,24 @@ describe('Orca cloud PKCE flow', () => { const response = await readHttp(callbackUrl(redirectUri, { error: 'access_denied', state })) expect(response.statusCode).toBe(400) + expect(response.body).toBe('Orca sign-in was cancelled.') await expect(observedFlow).resolves.toMatchObject({ message: 'orca_cloud_auth_denied' }) }) + it.each(['server_error', 'temporarily_unavailable', 'unknown-error', ''])( + 'reports %s as a failed sign-in rather than user cancellation', + async (error) => { + const { flow, redirectUri, state } = await startedFlow() + const observedFlow = flow.catch((failure: unknown) => failure) + const response = await readHttp(callbackUrl(redirectUri, { error, state })) + expect(response.statusCode).toBe(400) + expect(response.body).toBe('Orca sign-in failed. Return to Orca and try again.') + await expect(observedFlow).resolves.toMatchObject({ + message: 'orca_cloud_auth_callback_failed' + }) + } + ) + it('adds desktop PKCE parameters to the authorize URL', async () => { const { authUrl, flow, nonce, redirectUri, state } = await startedFlow() diff --git a/src/main/orca-profiles/profile-cloud-pkce.ts b/src/main/orca-profiles/profile-cloud-pkce.ts index 79e6819cfd8..5cb908e1702 100644 --- a/src/main/orca-profiles/profile-cloud-pkce.ts +++ b/src/main/orca-profiles/profile-cloud-pkce.ts @@ -97,9 +97,16 @@ export function beginOrcaCloudPkceFlow( return } if (url.searchParams.has('error')) { + const cancelled = url.searchParams.get('error') === 'access_denied' response.writeHead(400) - response.end('Orca sign-in was cancelled.') - rejectFlow(new Error('orca_cloud_auth_denied')) + response.end( + cancelled + ? 'Orca sign-in was cancelled.' + : 'Orca sign-in failed. Return to Orca and try again.' + ) + rejectFlow( + new Error(cancelled ? 'orca_cloud_auth_denied' : 'orca_cloud_auth_callback_failed') + ) return } if (!code) { diff --git a/src/main/orca-profiles/profile-cloud-service.test.ts b/src/main/orca-profiles/profile-cloud-service.test.ts index 552a2ee8ea1..c4e0c8331e8 100644 --- a/src/main/orca-profiles/profile-cloud-service.test.ts +++ b/src/main/orca-profiles/profile-cloud-service.test.ts @@ -178,6 +178,17 @@ describe('Orca cloud profile service', () => { }) }) + it('reports callback failures as failed instead of cancelled', async () => { + configureCloudEnv() + beginOrcaCloudPkceFlowMock.mockRejectedValue(new Error('orca_cloud_auth_callback_failed')) + + const result = await connectCurrentOrcaProfile(userDataPath) + + expect(result).toMatchObject({ status: 'failed', error: 'orca_cloud_auth_callback_failed' }) + expect(exchangeOrcaCloudAuthCodeMock).not.toHaveBeenCalled() + expect(getCurrentOrcaProfileAuthStatus(userDataPath)).toMatchObject({ state: 'local' }) + }) + it('does not report a saved cloud session as connected when cloud config is unavailable', async () => { configureCloudEnv() mockSuccessfulConnect() diff --git a/src/main/persistence-flush-and-save-scheduling.test.ts b/src/main/persistence-flush-and-save-scheduling.test.ts index 74572c2a7d1..2d6180d5fa8 100644 --- a/src/main/persistence-flush-and-save-scheduling.test.ts +++ b/src/main/persistence-flush-and-save-scheduling.test.ts @@ -11,9 +11,14 @@ import { dataFile, writeDataFile, readDataFile, - makeRepo + makeRepo, + makeTerminalTab } from './persistence-test-harness' -import { TEST_LEAF_1 } from './persistence-session-fixtures' +import { TEST_LEAF_1, TEST_LEAF_2 } from './persistence-session-fixtures' +import { getDefaultPersistedState, getDefaultWorkspaceSession } from '../shared/constants' +import type { WorkspaceSessionState } from '../shared/workspace-session-state-types' +import { _resetTracerForTests, setActiveSink } from './observability/tracer' +import { _resetPtyBindingSpanSamplingForTests } from './persistence/loading-store/pty-binding-span' // Stub the ~/.ssh/config parser so the SSH-import test drives the real Store with deterministic hosts, not the operator's actual ~/.ssh/config. const { loadUserSshConfigMock, sshConfigHostsToTargetsMock } = vi.hoisted(() => ({ @@ -64,6 +69,8 @@ describe('Store', () => { }) afterEach(() => { + vi.restoreAllMocks() + _resetPtyBindingSpanSamplingForTests() rmSync(testState.dir, { recursive: true, force: true }) }) // ── 10. flush writes synchronously ───────────────────────────────── @@ -379,4 +386,367 @@ describe('Store', () => { store.flush() expect((readDataFile() as { githubCache?: unknown }).githubCache).toBeUndefined() }) + + // ── persistPtyBinding fast lane ──────────────────────────────────── + + describe('persistPtyBinding fast lane', () => { + const WORKTREE = 'repo1::/worktree' + const binding = { worktreeId: WORKTREE, tabId: 'tab1', leafId: TEST_LEAF_1, ptyId: 'pty-1' } + const paneKey = `tab1:${TEST_LEAF_1}` + + const boundSession = ( + overrides: Partial = {} + ): WorkspaceSessionState => ({ + ...getDefaultWorkspaceSession(), + activeRepoId: 'repo1', + activeWorktreeId: WORKTREE, + activeTabId: 'tab1', + tabsByWorktree: { + [WORKTREE]: [makeTerminalTab({ id: 'tab1', worktreeId: WORKTREE, ptyId: 'pty-1' })] + }, + terminalLayoutsByTabId: { + tab1: { + root: { type: 'leaf', leafId: TEST_LEAF_1 }, + activeLeafId: TEST_LEAF_1, + expandedLeafId: null, + ptyIdsByLeafId: { [TEST_LEAF_1]: 'pty-1' } + } + }, + ...overrides + }) + + const runtimeCounters = (store: ReturnType) => { + const runtime = store['runtime'] + return { + writeGeneration: runtime.writeGeneration, + lastDurableWriteGeneration: runtime.lastDurableWriteGeneration + } + } + + afterEach(() => { + _resetTracerForTests() + }) + + it.each([undefined, 'ssh:ssh-1', 'runtime:runtime-1'])( + 'skips the clone and the flush when the binding is already durable on %s', + async (hostId) => { + const store = await createStore() + store.setWorkspaceSession(boundSession(), hostId) + expect(store.persistPtyBinding(binding, hostId)).toBe(true) + const inoBefore = statSync(dataFile()).ino + const flushSpy = vi.spyOn(store, 'flushOrThrow') + const cloneSpy = vi.spyOn(globalThis, 'structuredClone') + + expect(store.persistPtyBinding(binding, hostId)).toBe(true) + + expect(flushSpy).not.toHaveBeenCalled() + expect(cloneSpy).not.toHaveBeenCalled() + expect(statSync(dataFile()).ino).toBe(inoBefore) + } + ) + + it('flushes while a save is pending, and the sync hash match makes the next call durable', async () => { + const store = await createStore() + store.setWorkspaceSession(boundSession()) + store.persistPtyBinding(binding) + const inoBefore = statSync(dataFile()).ino + // Bumps the write generation without changing any binding. + store.setWorkspaceSession({ ...store.getWorkspaceSession() }) + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + expect(store.persistPtyBinding(binding)).toBe(true) + expect(flushSpy).toHaveBeenCalledTimes(1) + expect(statSync(dataFile()).ino).toBe(inoBefore) + + // Without the writeToDiskSync counter fix the hash-match flush leaves the durable + // generation one behind and this third bind would flush again. + expect(store.persistPtyBinding(binding)).toBe(true) + expect(flushSpy).toHaveBeenCalledTimes(1) + }) + + it('falls through on an incarnation change and persists the new incarnation', async () => { + const store = await createStore() + store.setWorkspaceSession(boundSession()) + store.persistPtyBinding({ ...binding, incarnationId: 'a' }) + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + expect(store.persistPtyBinding({ ...binding, incarnationId: 'b' })).toBe(true) + + expect(flushSpy).toHaveBeenCalledTimes(1) + expect(readDataFile()).toHaveProperty( + ['workspaceSession', 'terminalPtyIncarnationsByPaneKey', paneKey], + 'b' + ) + }) + + it('does not acknowledge an unpersisted binding published after the final flush', async () => { + const store = await createStore() + store.setWorkspaceSession(boundSession()) + store.persistPtyBinding(binding) + await store.flushAsync() + + const next = boundSession() + next.tabsByWorktree[WORKTREE][0].ptyId = 'pty-after-quit' + next.terminalLayoutsByTabId.tab1.ptyIdsByLeafId = { [TEST_LEAF_1]: 'pty-after-quit' } + store.setWorkspaceSession(next) + expect(store.getWorkspaceSession().tabsByWorktree[WORKTREE][0].ptyId).toBe('pty-after-quit') + + expect(() => store.persistPtyBinding({ ...binding, ptyId: 'pty-after-quit' })).toThrow( + 'Cannot synchronously flush after final persistence has started' + ) + expect(readDataFile()).toHaveProperty( + ['workspaceSession', 'tabsByWorktree', WORKTREE, '0', 'ptyId'], + 'pty-1' + ) + }) + + it('treats an undefined incarnation against a recorded one as a miss', async () => { + const store = await createStore() + store.setWorkspaceSession(boundSession()) + store.persistPtyBinding({ ...binding, incarnationId: 'a' }) + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + expect(store.persistPtyBinding(binding)).toBe(true) + + expect(flushSpy).toHaveBeenCalledTimes(1) + }) + + it('falls through on a tombstone and lets the write path clear it', async () => { + const persisted = getDefaultPersistedState(testState.dir) + persisted.repos = [makeRepo({ id: 'repo1', path: '/repo1' })] + persisted.workspaceSession = boundSession({ + terminalPtyIncarnationsByPaneKey: { [paneKey]: 'inc-1' }, + terminalSurfaceTombstonesByPaneKey: { + [paneKey]: { + worktreeId: WORKTREE, + parentTabId: 'tab1', + leafId: TEST_LEAF_1, + ptyId: 'pty-1', + incarnationId: 'inc-1', + retiredAt: 1 + } + } + }) + writeDataFile(persisted) + const store = await createStore() + expect( + store.getWorkspaceSession().terminalSurfaceTombstonesByPaneKey?.[paneKey] + ).toBeDefined() + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + expect(store.persistPtyBinding({ ...binding, incarnationId: 'inc-1' })).toBe(true) + + expect(flushSpy).toHaveBeenCalledTimes(1) + expect( + store.getWorkspaceSession().terminalSurfaceTombstonesByPaneKey?.[paneKey] + ).toBeUndefined() + }) + + it('still bumps the topology fence for a reconciled incarnation', async () => { + const store = await createStore() + store.setWorkspaceSession( + boundSession({ terminalPtyIncarnationsByPaneKey: { [paneKey]: 'inc-stale' } }) + ) + store.persistPtyBinding({ ...binding, incarnationId: 'inc-stale' }) + const revisionBefore = + store.getWorkspaceSession().terminalTopologyRevisionByRepoId?.repo1 ?? 0 + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + expect( + store.persistPtyBinding({ + ...binding, + incarnationId: 'inc-live', + expectedBinding: { ptyId: 'pty-1', incarnationId: 'inc-stale' } + }) + ).toBe(true) + + expect(flushSpy).toHaveBeenCalledTimes(1) + expect(store.getWorkspaceSession().terminalTopologyRevisionByRepoId?.repo1).toBe( + revisionBefore + 1 + ) + }) + + it('keeps every refusal ahead of the fast lane', async () => { + const store = await createStore() + store.setWorkspaceSession( + boundSession({ terminalPtyIncarnationsByPaneKey: { [paneKey]: 'inc-1' } }) + ) + store.persistPtyBinding({ ...binding, incarnationId: 'inc-1' }) + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + const refusals = [ + { + ...binding, + expectedSourceBinding: { tabId: 'other-tab', leafId: TEST_LEAF_1, ptyId: 'pty-1' } + }, + { ...binding, incarnationId: 'inc-1', expectedBinding: { ptyId: 'pty-other' } }, + { ...binding, tabId: 'missing-tab', mayCreate: false } + ] + for (const refusal of refusals) { + expect(store.persistPtyBinding(refusal)).toBe(false) + } + expect(flushSpy).not.toHaveBeenCalled() + }) + + it.each([undefined, 'ssh:ssh-1', 'runtime:runtime-1'])( + 'flushes unrelated dirty state once, then skips unchanged reattachments on %s', + async (hostId) => { + const store = await createStore() + store.setWorkspaceSession(boundSession(), hostId) + expect(store.persistPtyBinding(binding, hostId)).toBe(true) + store.addRepo(makeRepo({ id: 'r-dirty', path: '/dirty' })) + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + expect(store.persistPtyBinding(binding, hostId)).toBe(true) + expect(store.persistPtyBinding(binding, hostId)).toBe(true) + + expect(flushSpy).toHaveBeenCalledTimes(1) + expect(readDataFile()).toMatchObject({ + repos: expect.arrayContaining([expect.objectContaining({ id: 'r-dirty' })]) + }) + } + ) + + it('flushes again once the session object is replaced', async () => { + const store = await createStore() + store.setWorkspaceSession(boundSession()) + store.persistPtyBinding(binding) + // A renderer publish schedules another save, so global durability must be re-established. + store.setWorkspaceSession({ ...store.getWorkspaceSession() }) + store.addRepo(makeRepo({ id: 'r-dirty', path: '/dirty' })) + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + expect(store.persistPtyBinding(binding)).toBe(true) + + expect(flushSpy).toHaveBeenCalledTimes(1) + }) + + it('flushes a changed pty for a pane whose old binding was durable', async () => { + const store = await createStore() + store.setWorkspaceSession(boundSession()) + store.persistPtyBinding(binding) + store.addRepo(makeRepo({ id: 'r-dirty', path: '/dirty' })) + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + expect(store.persistPtyBinding({ ...binding, ptyId: 'pty-next' })).toBe(true) + + expect(flushSpy).toHaveBeenCalledTimes(1) + expect(readDataFile()).toHaveProperty( + ['workspaceSession', 'terminalLayoutsByTabId', 'tab1', 'ptyIdsByLeafId', TEST_LEAF_1], + 'pty-next' + ) + }) + + it('lets every pane of a split tab hit the fast lane', async () => { + const store = await createStore() + store.setWorkspaceSession( + boundSession({ + terminalLayoutsByTabId: { + tab1: { + root: { + type: 'split', + direction: 'vertical', + first: { type: 'leaf', leafId: TEST_LEAF_1 }, + second: { type: 'leaf', leafId: TEST_LEAF_2 } + }, + activeLeafId: TEST_LEAF_2, + expandedLeafId: null, + ptyIdsByLeafId: { [TEST_LEAF_1]: 'pty-1', [TEST_LEAF_2]: 'pty-2' } + } + } + }) + ) + const sibling = { ...binding, leafId: TEST_LEAF_2, ptyId: 'pty-2' } + // First remount after a cold park: both panes reattach back to back. + expect(store.persistPtyBinding(binding)).toBe(true) + expect(store.persistPtyBinding(sibling)).toBe(true) + expect(store.getWorkspaceSession().tabsByWorktree?.[WORKTREE]?.[0]?.ptyId).toBe('pty-1') + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + // Second remount: neither pane may rewrite the tab row, so neither flushes. + expect(store.persistPtyBinding(sibling)).toBe(true) + expect(store.persistPtyBinding(binding)).toBe(true) + + expect(flushSpy).not.toHaveBeenCalled() + expect(store.getWorkspaceSession().tabsByWorktree?.[WORKTREE]?.[0]?.ptyId).toBe('pty-1') + }) + + it('resolves the SSH partition without re-pointing it', async () => { + const store = await createStore() + const hostId = 'ssh:ssh-1' + store.setWorkspaceSession(boundSession(), hostId) + expect(store.persistPtyBinding(binding, hostId)).toBe(true) + const partitionBefore = store.getWorkspaceSession(hostId) + const partitionsBefore = store['runtime'].state.workspaceSessionsByHostId + const flushSpy = vi.spyOn(store, 'flushOrThrow') + + expect(store.persistPtyBinding(binding, hostId)).toBe(true) + + expect(flushSpy).not.toHaveBeenCalled() + expect(store.getWorkspaceSession(hostId)).toBe(partitionBefore) + expect(store['runtime'].state.workspaceSessionsByHostId).toBe(partitionsBefore) + expect(store.getWorkspaceSession().tabsByWorktree?.[WORKTREE]).toBeUndefined() + }) + + it('records a sync hash match as durable', async () => { + const store = await createStore() + store.addRepo(makeRepo()) + store.flushOrThrow() + const inoBefore = statSync(dataFile()).ino + const after = runtimeCounters(store) + expect(after.lastDurableWriteGeneration).toBe(after.writeGeneration) + + store.flushOrThrow() + + expect(statSync(dataFile()).ino).toBe(inoBefore) + const counters = runtimeCounters(store) + expect(counters.writeGeneration).toBe(after.writeGeneration + 1) + expect(counters.lastDurableWriteGeneration).toBe(counters.writeGeneration) + }) + + it('emits one persistence.pty-binding span per call with its outcome', async () => { + const records: unknown[] = [] + setActiveSink({ + push: (record) => { + records.push(record) + }, + flush: () => {}, + close: () => {} + }) + const store = await createStore() + store.setWorkspaceSession(boundSession()) + + store.persistPtyBinding(binding) + store.persistPtyBinding(binding) + store.persistPtyBinding({ ...binding, tabId: 'missing-tab', mayCreate: false }) + + const spans = records.filter( + (record) => + typeof record === 'object' && + record !== null && + 'name' in record && + record.name === 'persistence.pty-binding' + ) + expect(spans).toMatchObject([ + { + attributes: { + 'binding.outcome': 'flushed', + 'binding.eligible': false, + 'binding.misses': 'not_durable' + } + }, + { + attributes: { + 'binding.outcome': 'fast_lane', + 'binding.eligible': true, + 'binding.generation_gap': 0, + 'binding.host': 'local' + } + }, + { attributes: { 'binding.outcome': 'refused' } } + ]) + expect(JSON.stringify(spans)).not.toContain(TEST_LEAF_1) + expect(JSON.stringify(spans)).not.toContain('pty-1') + }) + }) }) diff --git a/src/main/persistence/loading-store/primary-state-writes.ts b/src/main/persistence/loading-store/primary-state-writes.ts index c112b4a9ba0..f61f6c691bd 100644 --- a/src/main/persistence/loading-store/primary-state-writes.ts +++ b/src/main/persistence/loading-store/primary-state-writes.ts @@ -231,6 +231,12 @@ export function writeToDiskSync( !opts.force && stateHash === owner[primaryStateWriteOperationsContext].runtime.lastWrittenStateHash ) { + // Why: flushOrThrow already bumped writeGeneration; the file holds this state, so record it + // durable or persistPtyBinding's fast lane stays parked one generation behind forever. + owner[primaryStateWriteOperationsContext].runtime.lastDurableWriteGeneration = Math.max( + owner[primaryStateWriteOperationsContext].runtime.lastDurableWriteGeneration, + owner[primaryStateWriteOperationsContext].runtime.writeGeneration + ) return } const dataFile = owner[primaryStateWriteOperationsContext].runtime.dataFile diff --git a/src/main/persistence/loading-store/pty-binding-fast-lane.test.ts b/src/main/persistence/loading-store/pty-binding-fast-lane.test.ts new file mode 100644 index 00000000000..8ac6de70a0d --- /dev/null +++ b/src/main/persistence/loading-store/pty-binding-fast-lane.test.ts @@ -0,0 +1,130 @@ +import { describe, expect, it } from 'vitest' +import type { WorkspaceSessionState } from '../../../shared/workspace-session-state-types' +import { getDefaultWorkspaceSession } from '../../../shared/constants' +import { evaluatePtyBindingFastLane } from './pty-binding-fast-lane' + +const LEAF = '11111111-1111-4111-8111-111111111111' +const WORKTREE = 'repo1::/worktree' +const request = { tabId: 'tab1', leafId: LEAF, ptyId: 'pty-1' } +const paneKey = `tab1:${LEAF}` + +function session(overrides: Partial = {}): WorkspaceSessionState { + return { + ...getDefaultWorkspaceSession(), + tabsByWorktree: { + [WORKTREE]: [ + { + id: 'tab1', + worktreeId: WORKTREE, + title: 'Terminal', + customTitle: null, + color: null, + sortOrder: 0, + createdAt: 1, + ptyId: 'pty-1' + } + ] + }, + terminalLayoutsByTabId: { + tab1: { + root: { type: 'leaf', leafId: LEAF }, + activeLeafId: LEAF, + expandedLeafId: null, + ptyIdsByLeafId: { [LEAF]: 'pty-1' } + } + }, + ...overrides + } +} + +describe('evaluatePtyBindingFastLane', () => { + it('is eligible only when memory matches and the session is durable', () => { + expect(evaluatePtyBindingFastLane(request, session(), WORKTREE, true)).toEqual({ + eligible: true, + misses: [] + }) + expect(evaluatePtyBindingFastLane(request, session(), WORKTREE, false)).toEqual({ + eligible: false, + misses: ['not_durable'] + }) + }) + + it('names every miss', () => { + const miss = ( + args: Partial[0]>, + state: WorkspaceSessionState = session() + ) => evaluatePtyBindingFastLane({ ...request, ...args }, state, WORKTREE, true).misses + + expect(miss({ expectedSourceBinding: {} })).toEqual(['split']) + expect(miss({ leafId: 'legacy-pane-1' })).toEqual(['legacy_leaf', 'leaf_absent', 'leaf_pty']) + expect(miss({}, session({ tabsByWorktree: {} }))).toEqual(['tab_missing']) + expect(miss({ ptyId: 'pty-2' })).toEqual(['tab_pty', 'leaf_pty']) + expect(miss({}, session({ terminalLayoutsByTabId: {} }))).toEqual(['layout_missing']) + expect( + miss( + {}, + session({ + terminalLayoutsByTabId: { + tab1: { root: null, activeLeafId: null, expandedLeafId: null, ptyIdsByLeafId: {} } + } + }) + ) + ).toEqual(['layout_missing']) + expect(miss({ incarnationId: 'a' })).toEqual(['incarnation']) + expect(miss({}, session({ terminalPtyIncarnationsByPaneKey: { [paneKey]: 'a' } }))).toEqual([ + 'incarnation' + ]) + expect( + miss( + { incarnationId: 'a' }, + session({ + terminalPtyIncarnationsByPaneKey: { [paneKey]: 'a' }, + terminalSurfaceTombstonesByPaneKey: { + [paneKey]: { + worktreeId: WORKTREE, + parentTabId: 'tab1', + leafId: LEAF, + ptyId: 'pty-1', + incarnationId: 'a', + retiredAt: 1 + } + } + }) + ) + ).toEqual(['tombstone']) + }) + + it('accepts a sibling pane whose tab row names the first pane', () => { + const LEAF_B = '22222222-2222-4222-8222-222222222222' + const state = session({ + terminalLayoutsByTabId: { + tab1: { + root: { + type: 'split', + direction: 'vertical', + first: { type: 'leaf', leafId: LEAF }, + second: { type: 'leaf', leafId: LEAF_B } + }, + activeLeafId: LEAF_B, + expandedLeafId: null, + ptyIdsByLeafId: { [LEAF]: 'pty-1', [LEAF_B]: 'pty-2' } + } + } + }) + expect( + evaluatePtyBindingFastLane( + { ...request, leafId: LEAF_B, ptyId: 'pty-2' }, + state, + WORKTREE, + true + ) + ).toEqual({ eligible: true, misses: [] }) + }) + + it('accepts a matching incarnation', () => { + const state = session({ terminalPtyIncarnationsByPaneKey: { [paneKey]: 'a' } }) + expect( + evaluatePtyBindingFastLane({ ...request, incarnationId: 'a' }, state, WORKTREE, true).eligible + ).toBe(true) + }) +}) diff --git a/src/main/persistence/loading-store/pty-binding-fast-lane.ts b/src/main/persistence/loading-store/pty-binding-fast-lane.ts new file mode 100644 index 00000000000..9ae6304ed0f --- /dev/null +++ b/src/main/persistence/loading-store/pty-binding-fast-lane.ts @@ -0,0 +1,87 @@ +import { isTerminalLeafId } from '../../../shared/stable-pane-id' +import type { WorkspaceSessionState } from '../../../shared/workspace-session-state-types' +import { layoutContainsLeafId } from '../restoring-sessions/terminal-layout-normalization' +import { tabRowPtyIdAfterLeafBinding } from './terminal-tab-pty-ownership' + +/** + * Why a reattach can be ineligible. `not_durable` alone means memory already matched but the + * binding was still waiting in the debounced save — the bucket that says whether skipping the + * flush on a durable match is enough, or the autosave itself has to move off the main thread. + */ +export type PtyBindingFastLaneMiss = + | 'split' + | 'legacy_leaf' + | 'tab_missing' + | 'tab_pty' + | 'layout_missing' + | 'leaf_absent' + | 'leaf_pty' + | 'incarnation' + | 'tombstone' + | 'not_durable' + +export type PtyBindingFastLaneRequest = { + tabId: string + leafId: string + ptyId: string + incarnationId?: string + expectedSourceBinding?: unknown +} + +export type PtyBindingFastLaneVerdict = { + eligible: boolean + misses: PtyBindingFastLaneMiss[] +} + +/** + * True only when `persistPtyBinding` would change nothing: the requested binding is already the + * in-memory session's binding and that session is already on disk. Every miss falls through to + * the write path, so the predicate must be at least as strict as the mutations it stands in for. + */ +export function evaluatePtyBindingFastLane( + args: PtyBindingFastLaneRequest, + session: WorkspaceSessionState, + bindingWorktreeId: string, + durable: boolean +): PtyBindingFastLaneVerdict { + const misses: PtyBindingFastLaneMiss[] = [] + const paneKey = `${args.tabId}:${args.leafId}` + if (args.expectedSourceBinding !== undefined) { + misses.push('split') + } + if (!isTerminalLeafId(args.leafId)) { + misses.push('legacy_leaf') + } + const tab = session.tabsByWorktree?.[bindingWorktreeId]?.find( + (candidate) => candidate.id === args.tabId + ) + const layout = session.terminalLayoutsByTabId?.[args.tabId] + if (!tab) { + misses.push('tab_missing') + } else if ( + tab.ptyId !== tabRowPtyIdAfterLeafBinding(tab, layout?.ptyIdsByLeafId, args.leafId, args.ptyId) + ) { + misses.push('tab_pty') + } + if (!layout || !layout.root) { + misses.push('layout_missing') + } else { + if (!layoutContainsLeafId(layout.root, args.leafId)) { + misses.push('leaf_absent') + } + if (layout.ptyIdsByLeafId?.[args.leafId] !== args.ptyId) { + misses.push('leaf_pty') + } + } + // Strict: undefined on both sides matches, undefined on one side does not. + if (session.terminalPtyIncarnationsByPaneKey?.[paneKey] !== args.incarnationId) { + misses.push('incarnation') + } + if (session.terminalSurfaceTombstonesByPaneKey?.[paneKey]) { + misses.push('tombstone') + } + if (!durable) { + misses.push('not_durable') + } + return { eligible: misses.length === 0, misses } +} diff --git a/src/main/persistence/loading-store/pty-binding-persistence.ts b/src/main/persistence/loading-store/pty-binding-persistence.ts index 6167687e065..27d62c8602b 100644 --- a/src/main/persistence/loading-store/pty-binding-persistence.ts +++ b/src/main/persistence/loading-store/pty-binding-persistence.ts @@ -1,5 +1,6 @@ -import { LOCAL_EXECUTION_HOST_ID } from '../../../shared/execution-host' +import { LOCAL_EXECUTION_HOST_ID, parseExecutionHostId } from '../../../shared/execution-host' import { isTerminalLeafId } from '../../../shared/stable-pane-id' +import type { WorkspaceSessionState } from '../../../shared/workspace-session-state-types' import { getRepoIdFromWorktreeId } from '../../../shared/worktree/id' import { cloneLayoutNode, @@ -15,8 +16,45 @@ import type { PtyBindingSourceExpectation } from './store' import type { StoreRuntimeState } from './store-runtime-state' import type { SessionHostPartitionOperations } from './session-host-partitions' import { resolveHostId } from './session-host-partitions' +import { evaluatePtyBindingFastLane } from './pty-binding-fast-lane' +import { ptyBindingIsRefused } from './pty-binding-refusals' +import { startPtyBindingSpan, type PtyBindingOrigin } from './pty-binding-span' +import { tabRowPtyIdAfterLeafBinding } from './terminal-tab-pty-ownership' -type PtyBindingPersistenceOperationsRuntime = Pick +type PtyBindingPersistenceOperationsRuntime = Pick< + StoreRuntimeState, + | 'flushOrThrow' + | 'lastDurableWriteGeneration' + | 'pendingWrite' + | 'quitFlushStarted' + | 'state' + | 'writeGeneration' + | 'writeTimer' +> + +type PersistPtyBindingArgs = { + worktreeId: string + tabId: string + leafId: string + ptyId: string + incarnationId?: string + startupCwd?: string + expectedBinding?: { ptyId: string; incarnationId?: string } + expectedSourceBinding?: PtyBindingSourceExpectation + /** Set by host-initiated creates, which have no renderer session writer behind them. */ + hostAdmittedMembership?: boolean + /** + * Defaults true, which is what `pty:spawn` needs — it can beat the debounced layout writer + * and must be able to mint the surface it is binding. A reattach is the opposite: the pane + * either still exists or the user closed it, so creating one grafts back a tab they closed. + * Callers pass false only once absence is meaningful; see the relay's reattach bind. + */ + mayCreate?: boolean + /** Reattach must not revive a surface a prior build durably recorded as retired. */ + mayReviveRetiredSurface?: boolean + /** Span metadata only; see `PtyBindingOrigin`. The write path never reads it. */ + origin?: PtyBindingOrigin +} const ptyBindingPersistenceOperationsContext = Symbol('PtyBindingPersistenceOperations') type PtyBindingPersistenceOperationsContext = { @@ -34,235 +72,199 @@ export class PtyBindingPersistenceOperations { this[ptyBindingPersistenceOperationsContext] = { runtime, sessions } } - persistPtyBinding( - args: { - worktreeId: string - tabId: string - leafId: string - ptyId: string - incarnationId?: string - startupCwd?: string - expectedBinding?: { ptyId: string; incarnationId?: string } - expectedSourceBinding?: PtyBindingSourceExpectation - /** Set by host-initiated creates, which have no renderer session writer behind them. */ - hostAdmittedMembership?: boolean - /** - * Defaults true, which is what `pty:spawn` needs — it can beat the debounced layout writer - * and must be able to mint the surface it is binding. A reattach is the opposite: the pane - * either still exists or the user closed it, so creating one grafts back a tab they closed. - * Callers pass false only once absence is meaningful; see the relay's reattach bind. - */ - mayCreate?: boolean - /** Reattach must not revive a surface a prior build durably recorded as retired. */ - mayReviveRetiredSurface?: boolean - }, - hostId?: string | null - ): boolean { + persistPtyBinding(args: PersistPtyBindingArgs, hostId?: string | null): boolean { + const runtime = this[ptyBindingPersistenceOperationsContext].runtime const resolvedHostId = resolveHostId(hostId) const session = this[ptyBindingPersistenceOperationsContext].sessions.getWorkspaceSession(resolvedHostId) const paneKey = `${args.tabId}:${args.leafId}` const bindingWorktreeId = args.expectedSourceBinding?.worktreeId ?? args.worktreeId - if (args.expectedSourceBinding) { - const expected = args.expectedSourceBinding - if (expected.tabId !== args.tabId) { - return false - } - const sourceTab = session.tabsByWorktree?.[bindingWorktreeId]?.find( - (candidate) => candidate.id === expected.tabId && candidate.worktreeId === bindingWorktreeId - ) - const sourceLayout = session.terminalLayoutsByTabId?.[expected.tabId] - const sourcePaneKey = `${expected.tabId}:${expected.leafId}` - if ( - !sourceTab || - sourceLayout?.ptyIdsByLeafId?.[expected.leafId] !== expected.ptyId || - !layoutContainsLeafId(sourceLayout.root, expected.leafId) || - (expected.incarnationId !== undefined && - session.terminalPtyIncarnationsByPaneKey?.[sourcePaneKey] !== expected.incarnationId) - ) { - return false - } - } - if (args.expectedBinding) { - const tab = session.tabsByWorktree?.[bindingWorktreeId]?.find( - (candidate) => candidate.id === args.tabId && candidate.worktreeId === bindingWorktreeId - ) - const boundPtyId = session.terminalLayoutsByTabId?.[args.tabId]?.ptyIdsByLeafId?.[args.leafId] - if ( - !tab || - boundPtyId !== args.expectedBinding.ptyId || - session.terminalPtyIncarnationsByPaneKey?.[paneKey] !== args.expectedBinding.incarnationId - ) { - return false - } - } - // Decided before any mutation so a refusal leaves nothing half-written. Mirrors the four - // creating branches below — mint a tab, mint a root leaf, split the root and graft a leaf, - // mint a layout — each of which sets `terminalMembershipChanged`. - if ( - args.mayReviveRetiredSurface === false && - session.terminalSurfaceTombstonesByPaneKey?.[paneKey] - ) { + const span = startPtyBindingSpan({ + hostKind: parseExecutionHostId(resolvedHostId)?.kind ?? 'local', + origin: args.origin ?? 'unknown', + savePending: runtime.writeTimer !== null || runtime.pendingWrite !== null, + generationGap: runtime.writeGeneration - runtime.lastDurableWriteGeneration + }) + if (ptyBindingIsRefused(args, session, bindingWorktreeId, paneKey)) { + span.finish('refused') return false } - if (args.mayCreate === false) { - const existingTab = session.tabsByWorktree?.[bindingWorktreeId]?.find( - (candidate) => candidate.id === args.tabId - ) - const existingLayout = session.terminalLayoutsByTabId?.[args.tabId] - const wouldCreateTopology = - !existingTab || - (isTerminalLeafId(args.leafId) && - (!existingLayout || - !existingLayout.root || - !layoutContainsLeafId(existingLayout.root, args.leafId))) - if (wouldCreateTopology) { - return false - } + // A durable reattach needs neither a session clone nor whole-state serialization. + const verdict = evaluatePtyBindingFastLane( + args, + session, + bindingWorktreeId, + !runtime.quitFlushStarted && runtime.lastDurableWriteGeneration >= runtime.writeGeneration + ) + span.setEligibility(verdict) + if (verdict.eligible) { + span.finish('fast_lane') + return true } + try { + writePtyBinding(this, args, session, resolvedHostId, bindingWorktreeId, paneKey) + } catch (err) { + span.finish('threw', err) + throw err + } + span.finish('flushed') + return true + } +} + +function writePtyBinding( + owner: PtyBindingPersistenceOperations, + args: PersistPtyBindingArgs, + session: WorkspaceSessionState, + resolvedHostId: ReturnType, + bindingWorktreeId: string, + paneKey: string +): void { + const runtime = owner[ptyBindingPersistenceOperationsContext].runtime + const sessionBeforeBinding = cloneWorkspaceSessionState(session) + try { if (resolvedHostId !== LOCAL_EXECUTION_HOST_ID) { - this[ptyBindingPersistenceOperationsContext].runtime.state.workspaceSessionsByHostId = { - ...this[ptyBindingPersistenceOperationsContext].runtime.state.workspaceSessionsByHostId, + runtime.state.workspaceSessionsByHostId = { + ...runtime.state.workspaceSessionsByHostId, [resolvedHostId]: session } } - const sessionBeforeBinding = cloneWorkspaceSessionState(session) - const reconciledIncarnation = - args.expectedBinding !== undefined && - args.incarnationId !== args.expectedBinding.incarnationId - let terminalMembershipChanged = false - let hostAdmittedTabCreated = false - const advanceTopologyFence = (): void => { - const repoId = getRepoIdFromWorktreeId(bindingWorktreeId) - const currentRevision = session.terminalTopologyRevisionByRepoId?.[repoId] ?? 0 - // Why: a split, or a host-admitted tab the renderer has never seen, is itself - // the authority — with no fence the renderer's pre-create tab list replays - // over it and the tab is lost even on the repo's first such change. - const establishesMembershipAuthority = - args.expectedSourceBinding !== undefined || hostAdmittedTabCreated - if ( - !reconciledIncarnation && - (!terminalMembershipChanged || (currentRevision <= 0 && !establishesMembershipAuthority)) - ) { - return - } - // Why: host-admitted membership or incarnation changes must outrank a stale renderer replay. - session.terminalTopologyRevisionByRepoId = { - ...session.terminalTopologyRevisionByRepoId, - [repoId]: currentRevision + 1 - } - } - const restoreSession = (): void => { - if (resolvedHostId === LOCAL_EXECUTION_HOST_ID) { - this[ptyBindingPersistenceOperationsContext].runtime.state.workspaceSession = - sessionBeforeBinding - } else { - this[ptyBindingPersistenceOperationsContext].runtime.state.workspaceSessionsByHostId = { - ...this[ptyBindingPersistenceOperationsContext].runtime.state.workspaceSessionsByHostId, - [resolvedHostId]: sessionBeforeBinding - } - } - } - if (args.incarnationId) { - session.terminalPtyIncarnationsByPaneKey = { - ...session.terminalPtyIncarnationsByPaneKey, - [paneKey]: args.incarnationId - } - if (session.terminalSurfaceTombstonesByPaneKey?.[paneKey]) { - session.terminalSurfaceTombstonesByPaneKey = { - ...session.terminalSurfaceTombstonesByPaneKey - } - delete session.terminalSurfaceTombstonesByPaneKey[paneKey] - } - } - const tabs = session.tabsByWorktree?.[bindingWorktreeId] - const tab = tabs?.find((t) => t.id === args.tabId) - if (tab) { - tab.ptyId = args.ptyId + applyPtyBinding(args, session, bindingWorktreeId, paneKey) + runtime.flushOrThrow() + } catch (err) { + if (resolvedHostId === LOCAL_EXECUTION_HOST_ID) { + runtime.state.workspaceSession = sessionBeforeBinding } else { - terminalMembershipChanged = true - hostAdmittedTabCreated = args.hostAdmittedMembership === true - // Why: pty:spawn can beat the debounced writer; persist a minimal tab so hydration won't prune the binding as orphaned. - const nextTabs = [ - ...(tabs ?? []), - createMinimalPersistedTerminalTab({ - ...args, - worktreeId: bindingWorktreeId, - existingTabCount: tabs?.length ?? 0 - }) - ] - session.tabsByWorktree = { - ...session.tabsByWorktree, - [bindingWorktreeId]: nextTabs - } - session.activeWorktreeId ??= bindingWorktreeId - session.activeTabId ??= args.tabId - session.activeTabIdByWorktree = { - ...session.activeTabIdByWorktree, - [bindingWorktreeId]: session.activeTabIdByWorktree?.[bindingWorktreeId] ?? args.tabId + runtime.state.workspaceSessionsByHostId = { + ...runtime.state.workspaceSessionsByHostId, + [resolvedHostId]: sessionBeforeBinding } } - if (!isTerminalLeafId(args.leafId)) { - // Why: keep legacy renderer-local pane ids out of durable leaf-keyed layout state after the UUID migration. - advanceTopologyFence() - try { - this[ptyBindingPersistenceOperationsContext].runtime.flushOrThrow() - } catch (err) { - restoreSession() - throw err - } - return true - } - const layout = session.terminalLayoutsByTabId?.[args.tabId] - if (layout) { - if (!layout.root) { - terminalMembershipChanged = true - // Why: createTab can persist an empty layout before TerminalPane mounts; the sync binding still needs a durable root. - layout.root = { type: 'leaf', leafId: args.leafId } - layout.activeLeafId = args.leafId - layout.expandedLeafId = null - } else if (!layoutContainsLeafId(layout.root, args.leafId)) { - terminalMembershipChanged = true - // Why: splitPane spawns before its snapshot reaches main; add a minimal leaf so a crash can't strand the pane's binding. - layout.root = { - type: 'split', - direction: 'vertical', - first: cloneLayoutNode(layout.root), - second: { type: 'leaf', leafId: args.leafId } - } - layout.activeLeafId = args.leafId - if (layout.expandedLeafId && !layoutContainsLeafId(layout.root, layout.expandedLeafId)) { - layout.expandedLeafId = null - } - } - layout.ptyIdsByLeafId = { - ...layout.ptyIdsByLeafId, - [args.leafId]: args.ptyId - } - } else { - terminalMembershipChanged = true - // Why: first tab spawn — persist a minimal layout so a SIGKILL before the renderer snapshot can't lose ptyIdsByLeafId. - session.terminalLayoutsByTabId = { - ...session.terminalLayoutsByTabId, - [args.tabId]: { - root: { type: 'leaf', leafId: args.leafId }, - activeLeafId: args.leafId, - expandedLeafId: null, - ptyIdsByLeafId: { [args.leafId]: args.ptyId } - } - } - } - advanceTopologyFence() - try { - this[ptyBindingPersistenceOperationsContext].runtime.flushOrThrow() - } catch (err) { - restoreSession() - throw err - } - return true + throw err } } +function applyPtyBinding( + args: PersistPtyBindingArgs, + session: WorkspaceSessionState, + bindingWorktreeId: string, + paneKey: string +): void { + const reconciledIncarnation = + args.expectedBinding !== undefined && args.incarnationId !== args.expectedBinding.incarnationId + let terminalMembershipChanged = false + let hostAdmittedTabCreated = false + const advanceTopologyFence = (): void => { + const repoId = getRepoIdFromWorktreeId(bindingWorktreeId) + const currentRevision = session.terminalTopologyRevisionByRepoId?.[repoId] ?? 0 + // Why: a split, or a host-admitted tab the renderer has never seen, is itself + // the authority — with no fence the renderer's pre-create tab list replays + // over it and the tab is lost even on the repo's first such change. + const establishesMembershipAuthority = + args.expectedSourceBinding !== undefined || hostAdmittedTabCreated + if ( + !reconciledIncarnation && + (!terminalMembershipChanged || (currentRevision <= 0 && !establishesMembershipAuthority)) + ) { + return + } + // Why: host-admitted membership or incarnation changes must outrank a stale renderer replay. + session.terminalTopologyRevisionByRepoId = { + ...session.terminalTopologyRevisionByRepoId, + [repoId]: currentRevision + 1 + } + } + if (args.incarnationId) { + session.terminalPtyIncarnationsByPaneKey = { + ...session.terminalPtyIncarnationsByPaneKey, + [paneKey]: args.incarnationId + } + if (session.terminalSurfaceTombstonesByPaneKey?.[paneKey]) { + session.terminalSurfaceTombstonesByPaneKey = { + ...session.terminalSurfaceTombstonesByPaneKey + } + delete session.terminalSurfaceTombstonesByPaneKey[paneKey] + } + } + const tabs = session.tabsByWorktree?.[bindingWorktreeId] + const tab = tabs?.find((t) => t.id === args.tabId) + if (tab) { + tab.ptyId = tabRowPtyIdAfterLeafBinding( + tab, + session.terminalLayoutsByTabId?.[args.tabId]?.ptyIdsByLeafId, + args.leafId, + args.ptyId + ) + } else { + terminalMembershipChanged = true + hostAdmittedTabCreated = args.hostAdmittedMembership === true + // Why: pty:spawn can beat the debounced writer; persist a minimal tab so hydration won't prune the binding as orphaned. + const nextTabs = [ + ...(tabs ?? []), + createMinimalPersistedTerminalTab({ + ...args, + worktreeId: bindingWorktreeId, + existingTabCount: tabs?.length ?? 0 + }) + ] + session.tabsByWorktree = { + ...session.tabsByWorktree, + [bindingWorktreeId]: nextTabs + } + session.activeWorktreeId ??= bindingWorktreeId + session.activeTabId ??= args.tabId + session.activeTabIdByWorktree = { + ...session.activeTabIdByWorktree, + [bindingWorktreeId]: session.activeTabIdByWorktree?.[bindingWorktreeId] ?? args.tabId + } + } + if (!isTerminalLeafId(args.leafId)) { + // Why: keep legacy renderer-local pane ids out of durable leaf-keyed layout state after the UUID migration. + advanceTopologyFence() + return + } + const layout = session.terminalLayoutsByTabId?.[args.tabId] + if (layout) { + if (!layout.root) { + terminalMembershipChanged = true + // Why: createTab can persist an empty layout before TerminalPane mounts; the sync binding still needs a durable root. + layout.root = { type: 'leaf', leafId: args.leafId } + layout.activeLeafId = args.leafId + layout.expandedLeafId = null + } else if (!layoutContainsLeafId(layout.root, args.leafId)) { + terminalMembershipChanged = true + // Why: splitPane spawns before its snapshot reaches main; add a minimal leaf so a crash can't strand the pane's binding. + layout.root = { + type: 'split', + direction: 'vertical', + first: cloneLayoutNode(layout.root), + second: { type: 'leaf', leafId: args.leafId } + } + layout.activeLeafId = args.leafId + if (layout.expandedLeafId && !layoutContainsLeafId(layout.root, layout.expandedLeafId)) { + layout.expandedLeafId = null + } + } + layout.ptyIdsByLeafId = { + ...layout.ptyIdsByLeafId, + [args.leafId]: args.ptyId + } + } else { + terminalMembershipChanged = true + // Why: first tab spawn — persist a minimal layout so a SIGKILL before the renderer snapshot can't lose ptyIdsByLeafId. + session.terminalLayoutsByTabId = { + ...session.terminalLayoutsByTabId, + [args.tabId]: { + root: { type: 'leaf', leafId: args.leafId }, + activeLeafId: args.leafId, + expandedLeafId: null, + ptyIdsByLeafId: { [args.leafId]: args.ptyId } + } + } + } + advanceTopologyFence() +} + export function installPtyBindingPersistenceOperationsContext( target: object, source: PtyBindingPersistenceOperations diff --git a/src/main/persistence/loading-store/pty-binding-refusals.ts b/src/main/persistence/loading-store/pty-binding-refusals.ts new file mode 100644 index 00000000000..3c61056bfca --- /dev/null +++ b/src/main/persistence/loading-store/pty-binding-refusals.ts @@ -0,0 +1,83 @@ +import { isTerminalLeafId } from '../../../shared/stable-pane-id' +import type { WorkspaceSessionState } from '../../../shared/workspace-session-state-types' +import { layoutContainsLeafId } from '../restoring-sessions/terminal-layout-normalization' +import type { PtyBindingSourceExpectation } from './store' + +export type PtyBindingRefusalRequest = { + tabId: string + leafId: string + expectedBinding?: { ptyId: string; incarnationId?: string } + expectedSourceBinding?: PtyBindingSourceExpectation + mayCreate?: boolean + mayReviveRetiredSurface?: boolean +} + +/** + * The four fences a binding must clear before anything is mutated, so a refusal leaves nothing + * half-written. Order matters: every `false` here is returned before the write path or the + * fast lane can run, which is what the relay's lease expiry and the stable-owner throw rely on. + */ +export function ptyBindingIsRefused( + args: PtyBindingRefusalRequest, + session: WorkspaceSessionState, + bindingWorktreeId: string, + paneKey: string +): boolean { + if (args.expectedSourceBinding) { + const expected = args.expectedSourceBinding + if (expected.tabId !== args.tabId) { + return true + } + const sourceTab = session.tabsByWorktree?.[bindingWorktreeId]?.find( + (candidate) => candidate.id === expected.tabId && candidate.worktreeId === bindingWorktreeId + ) + const sourceLayout = session.terminalLayoutsByTabId?.[expected.tabId] + const sourcePaneKey = `${expected.tabId}:${expected.leafId}` + if ( + !sourceTab || + sourceLayout?.ptyIdsByLeafId?.[expected.leafId] !== expected.ptyId || + !layoutContainsLeafId(sourceLayout.root, expected.leafId) || + (expected.incarnationId !== undefined && + session.terminalPtyIncarnationsByPaneKey?.[sourcePaneKey] !== expected.incarnationId) + ) { + return true + } + } + if (args.expectedBinding) { + const tab = session.tabsByWorktree?.[bindingWorktreeId]?.find( + (candidate) => candidate.id === args.tabId && candidate.worktreeId === bindingWorktreeId + ) + const boundPtyId = session.terminalLayoutsByTabId?.[args.tabId]?.ptyIdsByLeafId?.[args.leafId] + if ( + !tab || + boundPtyId !== args.expectedBinding.ptyId || + session.terminalPtyIncarnationsByPaneKey?.[paneKey] !== args.expectedBinding.incarnationId + ) { + return true + } + } + // Mirrors the four creating branches of the write path — mint a tab, mint a root leaf, split + // the root and graft a leaf, mint a layout — each of which sets `terminalMembershipChanged`. + if ( + args.mayReviveRetiredSurface === false && + session.terminalSurfaceTombstonesByPaneKey?.[paneKey] + ) { + return true + } + if (args.mayCreate === false) { + const existingTab = session.tabsByWorktree?.[bindingWorktreeId]?.find( + (candidate) => candidate.id === args.tabId + ) + const existingLayout = session.terminalLayoutsByTabId?.[args.tabId] + const wouldCreateTopology = + !existingTab || + (isTerminalLeafId(args.leafId) && + (!existingLayout || + !existingLayout.root || + !layoutContainsLeafId(existingLayout.root, args.leafId))) + if (wouldCreateTopology) { + return true + } + } + return false +} diff --git a/src/main/persistence/loading-store/pty-binding-span.test.ts b/src/main/persistence/loading-store/pty-binding-span.test.ts new file mode 100644 index 00000000000..1b926ca8257 --- /dev/null +++ b/src/main/persistence/loading-store/pty-binding-span.test.ts @@ -0,0 +1,107 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { _resetTracerForTests, setActiveSink } from '../../observability/tracer' +import { + _resetPtyBindingSpanSamplingForTests, + PTY_BINDING_FAST_LANE_SPAN_BUDGET_PER_WINDOW, + spawnCommitBindingOrigin, + startPtyBindingSpan +} from './pty-binding-span' + +let records: unknown[] + +beforeEach(() => { + records = [] + setActiveSink({ + push: (record) => { + records.push(record) + }, + flush: () => {}, + close: () => {} + }) + _resetPtyBindingSpanSamplingForTests() + vi.useFakeTimers() + vi.setSystemTime(1_700_000_000_000) +}) + +afterEach(() => { + vi.useRealTimers() + _resetTracerForTests() +}) + +function finishFastLane(): void { + const span = startPtyBindingSpan({ + hostKind: 'local', + origin: 'reattach', + savePending: false, + generationGap: 0 + }) + span.setEligibility({ eligible: true, misses: [] }) + span.finish('fast_lane') +} + +describe('persistence.pty-binding span', () => { + it('labels adopted relay bindings as reattach without an isReattach flag', () => { + expect(spawnCommitBindingOrigin({ agentSessionEnsure: { disposition: 'adopted' } })).toBe( + 'reattach' + ) + }) + + it('records the entry counters, eligibility, and outcome', () => { + const span = startPtyBindingSpan({ + hostKind: 'ssh', + origin: 'spawn', + savePending: true, + generationGap: 2 + }) + span.setEligibility({ eligible: false, misses: ['tab_pty', 'not_durable'] }) + span.finish('flushed') + + expect(records).toHaveLength(1) + expect(records[0]).toHaveProperty('name', 'persistence.pty-binding') + expect(records[0]).toMatchObject({ + attributes: { + 'binding.host': 'ssh', + 'binding.origin': 'spawn', + 'binding.save_pending': true, + 'binding.generation_gap': 2, + 'binding.eligible': false, + 'binding.misses': 'tab_pty,not_durable', + 'binding.outcome': 'flushed' + } + }) + }) + + it('records a throw as a failed span', () => { + const span = startPtyBindingSpan({ + hostKind: 'local', + origin: 'reattach', + savePending: false, + generationGap: 0 + }) + span.finish('threw', new Error('disk full')) + + expect(records[0]).toHaveProperty('exit._tag', 'Failure') + expect(records[0]).toHaveProperty(['attributes', 'binding.outcome'], 'threw') + }) + + it('caps fast-lane spans per window without dropping writes', () => { + for (let i = 0; i < PTY_BINDING_FAST_LANE_SPAN_BUDGET_PER_WINDOW + 5; i++) { + finishFastLane() + } + expect(records).toHaveLength(PTY_BINDING_FAST_LANE_SPAN_BUDGET_PER_WINDOW) + + // Flushed spans are never dropped, even inside a saturated window. + const span = startPtyBindingSpan({ + hostKind: 'local', + origin: 'reattach', + savePending: false, + generationGap: 0 + }) + span.finish('flushed') + expect(records).toHaveLength(PTY_BINDING_FAST_LANE_SPAN_BUDGET_PER_WINDOW + 1) + + vi.setSystemTime(1_700_000_000_000 + 60_000) + finishFastLane() + expect(records).toHaveLength(PTY_BINDING_FAST_LANE_SPAN_BUDGET_PER_WINDOW + 2) + }) +}) diff --git a/src/main/persistence/loading-store/pty-binding-span.ts b/src/main/persistence/loading-store/pty-binding-span.ts new file mode 100644 index 00000000000..58bed424a51 --- /dev/null +++ b/src/main/persistence/loading-store/pty-binding-span.ts @@ -0,0 +1,92 @@ +import { startSpan } from '../../observability/tracer' +import type { PtyBindingFastLaneMiss } from './pty-binding-fast-lane' + +export type PtyBindingSpanOutcome = 'fast_lane' | 'flushed' | 'refused' | 'threw' + +/** + * Who asked for the bind. `persistPtyBinding` cannot tell a fresh spawn from a warm remount, and + * fresh spawns always flush, so a rate over all calls understates the reattach hit rate. Metadata + * only: nothing in the write path may branch on it. + */ +export type PtyBindingOrigin = 'reattach' | 'spawn' | 'relay_reattach' | 'split' | 'unknown' + +/** The spawn-commit paths share one rule: a split outranks a reattach, a reattach outranks a spawn. */ +export function spawnCommitBindingOrigin( + commit: { isReattach?: boolean; agentSessionEnsure?: { disposition: string } }, + expectedSourceBinding?: unknown +): PtyBindingOrigin { + if (expectedSourceBinding !== undefined) { + return 'split' + } + return commit.isReattach === true || commit.agentSessionEnsure?.disposition === 'adopted' + ? 'reattach' + : 'spawn' +} + +// Bound frequent no-op traces; writes, refusals, and failures are always recorded. +export const PTY_BINDING_FAST_LANE_SPAN_BUDGET_PER_WINDOW = 200 +const FAST_LANE_WINDOW_MS = 60_000 + +let fastLaneWindow: { startMs: number; emitted: number } | null = null + +function admitFastLaneSpan(nowMs: number): boolean { + if (!fastLaneWindow || nowMs - fastLaneWindow.startMs >= FAST_LANE_WINDOW_MS) { + fastLaneWindow = { startMs: nowMs, emitted: 0 } + } + if (fastLaneWindow.emitted >= PTY_BINDING_FAST_LANE_SPAN_BUDGET_PER_WINDOW) { + return false + } + fastLaneWindow.emitted += 1 + return true +} + +export type PtyBindingSpan = { + setEligibility(verdict: { eligible: boolean; misses: readonly PtyBindingFastLaneMiss[] }): void + finish(outcome: PtyBindingSpanOutcome, error?: unknown): void +} + +/** + * One `persistence.pty-binding` span per `persistPtyBinding` call. Attributes are all + * low-cardinality on purpose: no pane key, PTY id, worktree id, path, or SSH target id ever lands + * in the trace file. A local-only NDJSON lane, collected only into a user-submitted bundle. + */ +export function startPtyBindingSpan(entry: { + hostKind: 'local' | 'ssh' | 'runtime' + origin: PtyBindingOrigin + savePending: boolean + generationGap: number +}): PtyBindingSpan { + const span = startSpan('persistence.pty-binding', { + attributes: { + kind: 'persistence', + 'binding.host': entry.hostKind, + 'binding.origin': entry.origin, + 'binding.save_pending': entry.savePending, + 'binding.generation_gap': entry.generationGap + }, + shouldRecord(record) { + if (record.attributes['binding.outcome'] !== 'fast_lane') { + return true + } + return admitFastLaneSpan(Date.now()) + } + }) + return { + setEligibility(verdict) { + span.setAttribute('binding.eligible', verdict.eligible) + span.setAttribute('binding.misses', verdict.misses.join(',')) + }, + finish(outcome, error) { + span.setAttribute('binding.outcome', outcome) + if (outcome === 'threw') { + span.fail(error instanceof Error ? error : String(error)) + return + } + span.end() + } + } +} + +export function _resetPtyBindingSpanSamplingForTests(): void { + fastLaneWindow = null +} diff --git a/src/main/persistence/loading-store/terminal-tab-pty-ownership.test.ts b/src/main/persistence/loading-store/terminal-tab-pty-ownership.test.ts new file mode 100644 index 00000000000..730eca1a8dd --- /dev/null +++ b/src/main/persistence/loading-store/terminal-tab-pty-ownership.test.ts @@ -0,0 +1,42 @@ +import { describe, expect, it } from 'vitest' +import { tabRowPtyIdAfterLeafBinding } from './terminal-tab-pty-ownership' + +const LEAF_A = 'leaf-a' +const LEAF_B = 'leaf-b' + +describe('tabRowPtyIdAfterLeafBinding', () => { + it('fills a null row', () => { + expect(tabRowPtyIdAfterLeafBinding({ ptyId: null }, undefined, LEAF_A, 'pty-1')).toBe('pty-1') + expect(tabRowPtyIdAfterLeafBinding({ ptyId: null }, {}, LEAF_A, 'pty-1')).toBe('pty-1') + }) + + it('follows a respawn of the leaf the row already names', () => { + expect( + tabRowPtyIdAfterLeafBinding({ ptyId: 'pty-1' }, { [LEAF_A]: 'pty-1' }, LEAF_A, 'pty-1b') + ).toBe('pty-1b') + }) + + it('leaves the row on the first pane when a sibling pane binds', () => { + expect( + tabRowPtyIdAfterLeafBinding( + { ptyId: 'pty-1' }, + { [LEAF_A]: 'pty-1', [LEAF_B]: 'pty-2' }, + LEAF_B, + 'pty-2' + ) + ).toBe('pty-1') + // The sibling's first bind, before its leaf is in the map, must not steal the row either. + expect( + tabRowPtyIdAfterLeafBinding({ ptyId: 'pty-1' }, { [LEAF_A]: 'pty-1' }, LEAF_B, 'pty-2') + ).toBe('pty-1') + }) + + it('preserves a non-null row until the renderer clears or replaces it', () => { + expect( + tabRowPtyIdAfterLeafBinding({ ptyId: 'pty-gone' }, { [LEAF_A]: 'pty-1' }, LEAF_B, 'pty-2') + ).toBe('pty-gone') + expect(tabRowPtyIdAfterLeafBinding({ ptyId: 'pty-gone' }, undefined, LEAF_A, 'pty-1')).toBe( + 'pty-gone' + ) + }) +}) diff --git a/src/main/persistence/loading-store/terminal-tab-pty-ownership.ts b/src/main/persistence/loading-store/terminal-tab-pty-ownership.ts new file mode 100644 index 00000000000..d353309bf35 --- /dev/null +++ b/src/main/persistence/loading-store/terminal-tab-pty-ownership.ts @@ -0,0 +1,25 @@ +import type { TerminalTab } from '../../../shared/terminal-tab-types' + +type LeafPtyIds = Readonly> | undefined + +/** + * A tab row names one PTY, but a split tab holds several panes. The renderer keeps the row on + * the first pane and refuses to let later split-pane spawns steal it (see terminal-pty-bindings.ts), + * because a remount reattaches the tab to whatever the row says. Main must agree, or every + * sibling pane's reattach rewrites the row and the two sides ping-pong forever. + * + * The row is rewritten only when it is null or points at the PTY this leaf is replacing. + * A missing leaf is not evidence that a non-null row can be reassigned. + */ +export function tabRowPtyIdAfterLeafBinding( + tab: Pick, + ptyIdsByLeafId: LeafPtyIds, + leafId: string, + ptyId: string +): string { + const current = tab.ptyId + if (current === null || current === ptyIdsByLeafId?.[leafId]) { + return ptyId + } + return current +} diff --git a/src/main/providers/filesystem-provider-contract.ts b/src/main/providers/filesystem-provider-contract.ts index e42bd5b07c9..ae4a59eb7bb 100644 --- a/src/main/providers/filesystem-provider-contract.ts +++ b/src/main/providers/filesystem-provider-contract.ts @@ -1,3 +1,4 @@ +import type { PathExistenceResult } from '../../shared/path-existence-batch' import type { SearchOptions, SearchResult } from '../../shared/code-search-types' import type { DocPreviewFileAccessRequest, @@ -86,6 +87,7 @@ export type IFilesystemProvider = { ): Promise writeFileBase64(filePath: string, contentBase64: string): Promise writeFileBase64Chunk(filePath: string, contentBase64: string, append: boolean): Promise + pathsExist?(filePaths: string[]): Promise stat(filePath: string): Promise lstat?(filePath: string): Promise deletePath(targetPath: string, recursive?: boolean): Promise diff --git a/src/main/providers/ssh-filesystem-path-existence.ts b/src/main/providers/ssh-filesystem-path-existence.ts new file mode 100644 index 00000000000..08570fc17b3 --- /dev/null +++ b/src/main/providers/ssh-filesystem-path-existence.ts @@ -0,0 +1,45 @@ +import type { SshChannelMultiplexer } from '../ssh/ssh-channel-multiplexer' +import { isMethodNotFoundError } from '../ssh/ssh-filesystem-stream-reader' +import { isENOENT } from '../ipc/filesystem-path-containment' +import { + capturePathExistence, + requirePathExistenceResults, + validatePathExistenceBatch, + type PathExistenceResult +} from '../../shared/path-existence-batch' +import { probeSshPathExistenceBatchCapability } from './ssh-filesystem-provider-capabilities' + +export async function readSshPathExistenceBatch( + mux: SshChannelMultiplexer, + paths: string[], + stat: (path: string) => Promise +): Promise { + validatePathExistenceBatch(paths) + if (await probeSshPathExistenceBatchCapability(mux)) { + try { + return requirePathExistenceResults( + await mux.request('fs.pathsExist', { filePaths: paths }), + paths.length + ) + } catch (error) { + if (!isMethodNotFoundError(error)) { + throw error + } + } + } + return Promise.all( + paths.map((path) => + capturePathExistence(async () => { + try { + await stat(path) + return true + } catch (error) { + if (isENOENT(error)) { + return false + } + throw error + } + }) + ) + ) +} diff --git a/src/main/providers/ssh-filesystem-provider-capabilities.ts b/src/main/providers/ssh-filesystem-provider-capabilities.ts index 2703c4d16c7..5d57bd588bb 100644 --- a/src/main/providers/ssh-filesystem-provider-capabilities.ts +++ b/src/main/providers/ssh-filesystem-provider-capabilities.ts @@ -62,3 +62,9 @@ export function probeSshRangedReadCapability( (capabilities) => capabilities?.rangedReadVersion === 1 ) } + +export function probeSshPathExistenceBatchCapability(mux: SshChannelMultiplexer): Promise { + return readSshFsCapabilities(mux).then( + (capabilities) => capabilities?.pathExistenceBatchVersion === 1 + ) +} diff --git a/src/main/providers/ssh-filesystem-provider.ts b/src/main/providers/ssh-filesystem-provider.ts index f6208ea00e9..f688d2789b1 100644 --- a/src/main/providers/ssh-filesystem-provider.ts +++ b/src/main/providers/ssh-filesystem-provider.ts @@ -1,3 +1,5 @@ +import { readSshPathExistenceBatch } from './ssh-filesystem-path-existence' +import type { PathExistenceResult } from '../../shared/path-existence-batch' import type { SshChannelMultiplexer } from '../ssh/ssh-channel-multiplexer' import { isMethodNotFoundError, readFileViaStream } from '../ssh/ssh-filesystem-stream-reader' import { uploadBuffer } from '../ssh/sftp-upload' @@ -217,6 +219,10 @@ export class SshFilesystemProvider implements IFilesystemProvider { } } + pathsExist(filePaths: string[]): Promise { + return readSshPathExistenceBatch(this.mux, filePaths, (path) => this.stat(path)) + } + async stat(filePath: string): Promise { return (await this.mux.request('fs.stat', { filePath })) as FileStat } diff --git a/src/main/providers/terminal-path-existence-batch.integration.test.ts b/src/main/providers/terminal-path-existence-batch.integration.test.ts new file mode 100644 index 00000000000..c67b627d682 --- /dev/null +++ b/src/main/providers/terminal-path-existence-batch.integration.test.ts @@ -0,0 +1,113 @@ +import { afterEach, expect, it, vi } from 'vitest' +import { mkdtemp, writeFile, rm } from 'node:fs/promises' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { pathsExistOnRelay } from '../../relay/fs-path-existence' +import { statRelayPath } from '../../relay/fs-path-metadata-requests' +import { readSshPathExistenceBatch } from './ssh-filesystem-path-existence' +import { JsonRpcErrorCode } from '../ssh/relay-protocol' +const handlers = vi.hoisted(() => new Map Promise>()) +vi.mock('electron', () => ({ + ipcMain: { + handle: (name: string, fn: (...args: unknown[]) => Promise) => handlers.set(name, fn) + }, + shell: {}, + dialog: {} +})) +import { registerShellHandlers } from '../ipc/shell' +let root: string | undefined +afterEach(async () => { + if (root) { + await rm(root, { recursive: true, force: true }) + } + root = undefined + handlers.clear() +}) +async function fixture() { + root = await mkdtemp(join(tmpdir(), 'orca-link-batch-')) + const paths = Array.from({ length: 8 }, (_, i) => join(root!, `file-${i}.ts`)) + await Promise.all(paths.map((path) => writeFile(path, 'fixture'))) + return paths +} +it('one actual shell IPC handler probes eight distinct temporary files and retains scalar answers', async () => { + const paths = await fixture() + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: This registration fixture never invokes unrelated store operations. + registerShellHandlers({} as never) + const all = [...paths, join(root!, 'missing'), root!] + expect(await handlers.get('shell:pathsExist')!(null, all)).toEqual( + await Promise.all(all.map((path) => handlers.get('shell:pathExists')!(null, path))) + ) + expect(await handlers.get('shell:pathsExist')!(null, all)).toEqual([ + ...paths.map(() => true), + false, + true + ]) + await expect(handlers.get('shell:pathsExist')!(null, Array(129).fill('x'))).rejects.toThrow( + 'Invalid' + ) +}) +it('one real relay batch serves eight distinct SSH paths after one shared capability probe', async () => { + const paths = await fixture() + const request = vi.fn(async (method: string, params: Record) => + method === 'fs.getCapabilities' ? { pathExistenceBatchVersion: 1 } : pathsExistOnRelay(params) + ) + const scalar = vi.fn((path: string) => statRelayPath({ filePath: path })) + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The fixture implements request, the only multiplexer operation exercised here. + const mux = { request } as never + expect(await readSshPathExistenceBatch(mux, paths, scalar)).toEqual( + paths.map(() => ({ exists: true })) + ) + expect(request.mock.calls.map((c) => c[0])).toEqual(['fs.getCapabilities', 'fs.pathsExist']) + expect(scalar).not.toHaveBeenCalled() + await rm(paths[0]) + expect(await readSshPathExistenceBatch(mux, [paths[0]], scalar)).toEqual([{ exists: false }]) + await writeFile(paths[0], 'new') + expect(await readSshPathExistenceBatch(mux, [paths[0]], scalar)).toEqual([{ exists: true }]) + expect(request.mock.calls.filter((c) => c[0] === 'fs.getCapabilities')).toHaveLength(1) +}) +it('old relay falls back on the same host without retrying a missing capability document', async () => { + const paths = await fixture() + const request = vi + .fn() + .mockRejectedValue( + Object.assign(new Error('method not found'), { code: JsonRpcErrorCode.MethodNotFound }) + ) + const scalar = vi.fn((path: string) => statRelayPath({ filePath: path })) + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The fixture implements request, the only multiplexer operation exercised here. + const mux = { request } as never + expect(await readSshPathExistenceBatch(mux, paths, scalar)).toEqual( + paths.map(() => ({ exists: true })) + ) + expect(scalar).toHaveBeenCalledTimes(8) + await readSshPathExistenceBatch(mux, [paths[0]], scalar) + expect(request).toHaveBeenCalledTimes(1) +}) +it('connection failure is neither a missing path nor permission to use local/scalar fallback', async () => { + const scalar = vi.fn() + const request = vi.fn().mockRejectedValue(new Error('connection closed')) + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The fixture implements request, the only multiplexer operation exercised here. + const mux = { request } as never + await expect(readSshPathExistenceBatch(mux, ['/remote/path'], scalar)).rejects.toThrow( + 'connection closed' + ) + expect(scalar).not.toHaveBeenCalled() + request + .mockResolvedValueOnce({ pathExistenceBatchVersion: 1 }) + .mockResolvedValueOnce([{ error: 'EACCES denied' }]) + expect(await readSshPathExistenceBatch(mux, ['/remote/path'], scalar)).toEqual([ + { error: 'EACCES denied' } + ]) + expect(request).toHaveBeenCalledTimes(3) +}) +it('malformed batch replies fail rather than manufacturing negative cache entries', async () => { + const scalar = vi.fn() + const request = vi + .fn() + .mockResolvedValueOnce({ pathExistenceBatchVersion: 1 }) + .mockResolvedValueOnce([]) + await expect( + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The fixture implements request, the only multiplexer operation exercised here. + readSshPathExistenceBatch({ request } as never, ['/remote/path'], scalar) + ).rejects.toThrow('Invalid path existence response') + expect(scalar).not.toHaveBeenCalled() +}) diff --git a/src/main/runtime/agent-session-surface-release-transition.ts b/src/main/runtime/agent-session-surface-release-transition.ts index 9fd3ef9cfda..a59d5cb5141 100644 --- a/src/main/runtime/agent-session-surface-release-transition.ts +++ b/src/main/runtime/agent-session-surface-release-transition.ts @@ -12,6 +12,8 @@ import type { AgentSessionRecord } from '../../shared/agent-session-record' import { assertFence, withLease } from './agent-session-lease-transitions' import type { AgentSessionRecordStore } from './agent-session-record-store' +export type AgentSessionRecordTransitionStore = Pick + /** Whether this record is one THIS host may release on its own proof. A TUI owner, a session * mid-handoff, and a lease nobody holds are all somebody else's transition. */ export function isSurfaceReleasableAgentSessionRecord(record: AgentSessionRecord): boolean { @@ -57,7 +59,7 @@ export function releaseAgentSessionOwnerAfterSurfaceClose(args: { /** Applied through the store's generic transition, the same way handoff records move. */ export function releaseStoredAgentSessionOwnerAfterSurfaceClose( - store: AgentSessionRecordStore, + store: AgentSessionRecordTransitionStore, args: { sessionId: string expectedFence: number diff --git a/src/main/runtime/orca-runtime-structured-agent-session-create-intent.test.ts b/src/main/runtime/orca-runtime-structured-agent-session-create-intent.test.ts index 9d2c6589508..84a9bac131a 100644 --- a/src/main/runtime/orca-runtime-structured-agent-session-create-intent.test.ts +++ b/src/main/runtime/orca-runtime-structured-agent-session-create-intent.test.ts @@ -59,7 +59,7 @@ describe('structured agent-session create intent', () => { variable: 'CODEX_HOME', path: '/accounts/selected/home' }) - expect(intent.options).toEqual({ model: 'gpt-5.6-sol', effort: 'medium' }) + expect(intent.options).toEqual({ model: 'gpt-5.6-sol', effort: 'medium', fastMode: 'true' }) }) it('pins the configured Claude launch home without Codex launch preparation', async () => { @@ -116,7 +116,7 @@ describe('structured agent-session create intent', () => { variable: 'CLAUDE_CONFIG_DIR', path: '/configured/claude-home' }) - expect(intent.options).toEqual({ model: 'opus', effort: 'high' }) + expect(intent.options).toEqual({ model: 'opus', effort: 'high', fastMode: 'true' }) }) it('uses the managed Claude launch home before falling back to ~/.claude', async () => { diff --git a/src/main/runtime/orchestration/db/contract-constants.ts b/src/main/runtime/orchestration/db/contract-constants.ts index 56c2e2d542f..a8ddf9994d0 100644 --- a/src/main/runtime/orchestration/db/contract-constants.ts +++ b/src/main/runtime/orchestration/db/contract-constants.ts @@ -17,4 +17,5 @@ export const LEGACY_CONTRACT_VERSION = 0 export const CURRENT_CONTRACT_VERSION = ORCHESTRATION_CONTRACT_VERSION // Schema versions: v2 'heartbeat'+last_heartbeat_at, v3 delivered_at, v4 task-creator terminal, v5 task_title/display_name, v6 pane identity, v7 lightweight Runs, v8 crash-safe Run deliveries, v9 durable question threads, v10 Dispatch capabilities, v11 durable mutation receipts, v12 composed worker state, v18 post-v6 version-skew repair, v19 adopted legacy Runs and compatibility receipts, v20 legacy question backfill, v21 legacy scheduler-loss provenance, v22 dispatch assignee lookup, v23 worker terminal resource ownership, v24 creator-incarnation authority, v25 active Dispatch handle lookup, v26 indexed mutation receipt capacity, v27 durable federation acknowledgments, v28 durable local mutation caller identity, v31 dispatch/resource identity links, v32 bounded worker-terminal recovery metadata, v33 durable mailbox pointer Enter state, v34 role-addressed mailbox deliveries, v35 mailbox delivery default and index-predicate repair, v36 dispatch mailbox consumer generation, v37 recorded dispatch creator identity, v39 structured session journal archives. -export const SCHEMA_VERSION = 40 +// v41: derive outstanding deliveries from unread messages. +export const SCHEMA_VERSION = 41 diff --git a/src/main/runtime/orchestration/db/dispatch-context/dispatch-capability.ts b/src/main/runtime/orchestration/db/dispatch-context/dispatch-capability.ts index 4f6861a17d0..007e81d1016 100644 --- a/src/main/runtime/orchestration/db/dispatch-context/dispatch-capability.ts +++ b/src/main/runtime/orchestration/db/dispatch-context/dispatch-capability.ts @@ -38,7 +38,7 @@ export function mintDispatchCapability( params.processIncarnation, params.dispatchId ) - this.fenceOutstandingMailboxDelivery(`dispatch:${params.dispatchId}`) + this.fenceUnacknowledgedMailboxDeliveries(`dispatch:${params.dispatchId}`) this.db.exec('COMMIT') } catch (error) { this.db.exec('ROLLBACK') diff --git a/src/main/runtime/orchestration/db/dispatch-mailbox-consumer-fencing.test.ts b/src/main/runtime/orchestration/db/dispatch-mailbox-consumer-fencing.test.ts index 29a2e468ee8..608b91a2586 100644 --- a/src/main/runtime/orchestration/db/dispatch-mailbox-consumer-fencing.test.ts +++ b/src/main/runtime/orchestration/db/dispatch-mailbox-consumer-fencing.test.ts @@ -1,7 +1,6 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest' import { OrchestrationDb } from '../db' import { ORCHESTRATION_CONTRACT_VERSION } from '../../../../shared/protocol-version' -import { ORCHESTRATION_LEGACY_RUN_ID } from '../../../../shared/orchestration-rpc-contract' import { createRootDispatch } from './root-dispatch-test-fixture' import type { DeliveryRow } from '../types' @@ -35,11 +34,17 @@ describe('dispatch mailbox consumer fencing', () => { return { id: dispatch.id, runId: dispatch.run_id } } - function openDelivery(dispatchId: string, runId: string, generation: number) { + function openDelivery( + dispatchId: string, + runId: string, + generation: number, + consumerSource: 'dispatch' | 'attachment' = 'dispatch' + ) { return db.getOrCreateMailboxDelivery({ runId, mailboxHandle: `dispatch:${dispatchId}`, - consumerGeneration: generation + consumerGeneration: generation, + consumerSource }) } @@ -169,9 +174,9 @@ describe('dispatch mailbox consumer fencing', () => { from: 'home-peer', to: `dispatch:${dispatchId}`, subject: 'relayed before attach', - runId: ORCHESTRATION_LEGACY_RUN_ID + runId: 'run-home' }) - const stale = openDelivery(dispatchId, ORCHESTRATION_LEGACY_RUN_ID, 0) + const stale = openDelivery(dispatchId, 'run-home', 0, 'attachment') // The worker host holds no dispatch_contexts row for a federated Dispatch. expect(db.getDispatchContextById(dispatchId)).toBeUndefined() diff --git a/src/main/runtime/orchestration/db/federation/remote-dispatch-attachment-authority.ts b/src/main/runtime/orchestration/db/federation/remote-dispatch-attachment-authority.ts index 5b2dc60615c..ac85fc7c3c9 100644 --- a/src/main/runtime/orchestration/db/federation/remote-dispatch-attachment-authority.ts +++ b/src/main/runtime/orchestration/db/federation/remote-dispatch-attachment-authority.ts @@ -71,7 +71,7 @@ export function prepareRemoteAttachmentAuthority( `Remote Dispatch ${params.dispatchId} is not starting.` ) } - this.fenceOutstandingMailboxDelivery(`dispatch:${params.dispatchId}`) + this.fenceUnacknowledgedMailboxDeliveries(`dispatch:${params.dispatchId}`) if (params.terminalOwnership && !this.getWorkerTerminalResourceByOwner(params.dispatchId)) { const resource = params.terminalOwnership === 'external' diff --git a/src/main/runtime/orchestration/db/messages/mailbox-consumer-lifecycle-fencing.test.ts b/src/main/runtime/orchestration/db/messages/mailbox-consumer-lifecycle-fencing.test.ts new file mode 100644 index 00000000000..3f81901b208 --- /dev/null +++ b/src/main/runtime/orchestration/db/messages/mailbox-consumer-lifecycle-fencing.test.ts @@ -0,0 +1,234 @@ +import { mkdtempSync, rmSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { afterEach, describe, expect, it } from 'vitest' +import { ORCHESTRATION_CONTRACT_VERSION } from '../../../../../shared/protocol-version' +import { OrchestrationDb } from '../orchestration-db' +import { createRootDispatch } from '../root-dispatch-test-fixture' + +type Settlement = 'local completion' | 'local failure' | 'remote stop' | 'remote failure' +type DeliveryOperation = 'create' | 'acknowledge' + +describe('mailbox consumer lifecycle fencing', () => { + const connections: OrchestrationDb[] = [] + const directories: string[] = [] + + afterEach(() => { + for (const db of connections.splice(0)) { + db.close() + } + for (const directory of directories.splice(0)) { + rmSync(directory, { recursive: true, force: true }) + } + }) + + function open(path: string): OrchestrationDb { + const db = new OrchestrationDb(path) + connections.push(db) + return db + } + + function databasePath(): string { + const directory = mkdtempSync(join(tmpdir(), 'orca-mailbox-consumer-lifecycle-')) + directories.push(directory) + return join(directory, 'orchestration.db') + } + + function setup(settlement: Settlement): { + db: OrchestrationDb + peer: OrchestrationDb + messageId: string + params: { + runId: string + mailboxHandle: string + consumerGeneration: number + consumerSource: 'dispatch' | 'attachment' + } + settle: () => void + } { + const path = databasePath() + const db = open(path) + const run = db.createRun({ + objective: 'Fence settled mailbox consumers', + coordinatorHandle: 'coord', + coordinatorPaneKey: 'tab:11111111-1111-4111-8111-111111111111' + }) + const remote = settlement.startsWith('remote') + const dispatchId = remote + ? `ctx_${settlement.replace(' ', '_')}` + : createRootDispatch(db, db.createTask({ runId: run.id, spec: settlement }).id, 'worker').id + let consumerGeneration = 0 + + if (remote) { + db.createRemoteDispatchAttachment({ + runId: run.id, + dispatchId, + taskId: `task_${dispatchId}`, + homePeerFingerprint: 'home-peer', + protocolVersion: ORCHESTRATION_CONTRACT_VERSION, + runtimeEpoch: 'epoch-1', + mutationReceipt: { + callerFingerprint: 'home-peer', + requestId: `request_${dispatchId}`, + method: 'orchestration.federationAttachStart', + payloadHash: `hash_${dispatchId}` + } + }) + if (settlement === 'remote stop') { + db.prepareRemoteAttachmentAuthority({ + dispatchId, + paneKey: 'worker:22222222-2222-4222-9222-222222222222', + processIncarnation: 'runtime:worker:1', + worktreeId: 'folder', + terminalHandle: 'worker', + setupState: 'not_applicable', + effects: [] + }) + db.markRemoteAttachmentReady(dispatchId) + consumerGeneration = 1 + } + } + + const mailboxHandle = `dispatch:${dispatchId}` + const message = db.insertMessage({ + runId: run.id, + from: 'coord', + to: mailboxHandle, + subject: 'must remain unread' + }) + const peer = open(path) + const settle = (): void => { + if (settlement === 'local completion') { + peer.completeDispatch(dispatchId) + } else if (settlement === 'local failure') { + peer.failDispatch(dispatchId, 'settled by peer') + } else if (settlement === 'remote stop') { + peer.beginRemoteAttachmentStop(dispatchId) + peer.settleRemoteAttachmentStop(dispatchId) + } else { + peer.failRemoteAttachment(dispatchId, 'peer_failure', 'settled by peer', false) + } + } + + return { + db, + peer, + messageId: message.id, + params: { + runId: run.id, + mailboxHandle, + consumerGeneration, + consumerSource: remote ? 'attachment' : 'dispatch' + }, + settle + } + } + + function currentGeneration( + db: OrchestrationDb, + params: { + mailboxHandle: string + consumerSource: 'dispatch' | 'attachment' + } + ): number | undefined { + const dispatchId = params.mailboxHandle.slice('dispatch:'.length) + return params.consumerSource === 'dispatch' + ? db.getDispatchContextById(dispatchId)?.consumer_generation + : db.getRemoteDispatchAttachment(dispatchId)?.consumer_generation + } + + it.each<{ + operation: DeliveryOperation + settlement: Settlement + }>([ + { operation: 'create', settlement: 'local completion' }, + { operation: 'create', settlement: 'local failure' }, + { operation: 'create', settlement: 'remote stop' }, + { operation: 'create', settlement: 'remote failure' }, + { operation: 'acknowledge', settlement: 'local completion' }, + { operation: 'acknowledge', settlement: 'local failure' }, + { operation: 'acknowledge', settlement: 'remote stop' }, + { operation: 'acknowledge', settlement: 'remote failure' } + ])('rejects $operation after $settlement on another connection', ({ operation, settlement }) => { + const { db, peer, messageId, params, settle } = setup(settlement) + const delivery = + operation === 'acknowledge' ? db.getOrCreateMailboxDelivery(params)?.delivery : undefined + + settle() + + const operationCall = (): unknown => + operation === 'create' + ? db.getOrCreateMailboxDelivery(params) + : db.acknowledgeMailboxDelivery({ ...params, deliveryId: delivery!.id }) + expect(operationCall).toThrow(expect.objectContaining({ code: 'consumer_fenced' })) + expect(db.getMessageById(messageId)?.read).toBe(0) + expect(currentGeneration(peer, params)).toBe(params.consumerGeneration) + if (delivery) { + expect(db.getDeliveryRaw(delivery.id)?.acknowledged_at).toBeNull() + } + }) + + it.each(['start_unknown', 'stop_unknown'] as const)( + 'keeps a remote %s attachment eligible to consume mail', + (state) => { + const path = databasePath() + const db = open(path) + const run = db.createRun({ + objective: 'Preserve unverifiable remote consumers', + coordinatorHandle: 'coord', + coordinatorPaneKey: 'tab:11111111-1111-4111-8111-111111111111' + }) + const dispatchId = `ctx_${state}` + db.createRemoteDispatchAttachment({ + runId: run.id, + dispatchId, + taskId: `task_${state}`, + homePeerFingerprint: 'home-peer', + protocolVersion: ORCHESTRATION_CONTRACT_VERSION, + runtimeEpoch: 'epoch-1', + mutationReceipt: { + callerFingerprint: 'home-peer', + requestId: `request_${state}`, + method: 'orchestration.federationAttachStart', + payloadHash: `hash_${state}` + } + }) + let consumerGeneration = 0 + if (state === 'start_unknown') { + db.failRemoteAttachment(dispatchId, 'start_unknown', 'contact lost', true) + } else { + db.prepareRemoteAttachmentAuthority({ + dispatchId, + paneKey: 'worker:22222222-2222-4222-9222-222222222222', + processIncarnation: 'runtime:worker:1', + worktreeId: 'folder', + terminalHandle: 'worker', + setupState: 'not_applicable', + effects: [] + }) + db.markRemoteAttachmentReady(dispatchId) + db.beginRemoteAttachmentStop(dispatchId) + db.markRemoteAttachmentStopUnknown(dispatchId, 'contact lost') + consumerGeneration = 1 + } + const mailboxHandle = `dispatch:${dispatchId}` + const message = db.insertMessage({ + runId: run.id, + from: 'coord', + to: mailboxHandle, + subject: 'still deliverable' + }) + + expect( + db + .getOrCreateMailboxDelivery({ + runId: run.id, + mailboxHandle, + consumerGeneration, + consumerSource: 'attachment' + }) + ?.messages.map((row) => row.id) + ).toEqual([message.id]) + } + ) +}) diff --git a/src/main/runtime/orchestration/db/messages/mailbox-consumer.ts b/src/main/runtime/orchestration/db/messages/mailbox-consumer.ts new file mode 100644 index 00000000000..66d72fb63d4 --- /dev/null +++ b/src/main/runtime/orchestration/db/messages/mailbox-consumer.ts @@ -0,0 +1,45 @@ +import type { OrchestrationDb } from '../orchestration-db' +import { OrchestrationError } from '../../orchestration-error' +import { potentiallyLiveRemoteAttachmentSql } from '../federation/remote-attachment-liveness' + +const ACTIVE_DISPATCH_CONSUMER_SQL = ` + SELECT run_id, consumer_generation FROM dispatch_contexts + WHERE id = ? AND status IN ('pending', 'dispatched') +` +const ACTIVE_ATTACHMENT_CONSUMER_SQL = ` + SELECT home_run_id AS run_id, consumer_generation FROM remote_dispatch_attachments + WHERE dispatch_id = ? AND ${potentiallyLiveRemoteAttachmentSql()} +` + +// Validate inside the delivery transaction, so another connection cannot replace the consumer mid-check. +export function requireMailboxConsumer( + db: OrchestrationDb, + params: { + runId: string + mailboxHandle: string + consumerGeneration: number + consumerSource?: 'dispatch' | 'attachment' + } +): void { + if (params.mailboxHandle === `run:${params.runId}`) { + db.requireCurrentConsumer(params.runId, params.consumerGeneration) + return + } + const dispatchId = params.mailboxHandle.startsWith('dispatch:') + ? params.mailboxHandle.slice('dispatch:'.length) + : '' + // A loopback runtime has both records; use the counter belonging to the caller's attachment. + const sql = + params.consumerSource === 'attachment' + ? ACTIVE_ATTACHMENT_CONSUMER_SQL + : ACTIVE_DISPATCH_CONSUMER_SQL + const consumer = db.db.prepare(sql).get(dispatchId) as + | { run_id: string; consumer_generation: number } + | undefined + if ( + consumer?.run_id !== params.runId || + consumer.consumer_generation !== params.consumerGeneration + ) { + throw new OrchestrationError('consumer_fenced', 'This mailbox consumer has been replaced.') + } +} diff --git a/src/main/runtime/orchestration/db/messages/role-mailbox-delivery.ts b/src/main/runtime/orchestration/db/messages/role-mailbox-delivery.ts index c7553c089b7..6c96fc282ac 100644 --- a/src/main/runtime/orchestration/db/messages/role-mailbox-delivery.ts +++ b/src/main/runtime/orchestration/db/messages/role-mailbox-delivery.ts @@ -3,6 +3,7 @@ import { OrchestrationError } from '../../orchestration-error' import { generateId } from '../generated-id' import type { OrchestrationDb } from '../orchestration-db' import { exposeDeliveryTimestamps, exposeMessageListTimestamps } from '../utc-timestamp' +import { requireMailboxConsumer } from './mailbox-consumer' import { ORCHESTRATION_DELIVERY_BATCH_LIMIT } from './mailbox-routing-page' export function getDeliveryRaw(this: OrchestrationDb, id: string): DeliveryRow | undefined { @@ -29,9 +30,9 @@ export function getOrCreateMailboxDelivery( runId: string mailboxHandle: string consumerGeneration: number + consumerSource?: 'dispatch' | 'attachment' limit?: number wakeTypes?: MessageType[] - requireCurrentRunConsumer?: boolean } ): { delivery: DeliveryRow; messages: MessageRow[]; replayed: boolean } | undefined { const limit = Math.min( @@ -40,11 +41,9 @@ export function getOrCreateMailboxDelivery( ) this.db.exec('BEGIN IMMEDIATE') try { - if (params.requireCurrentRunConsumer) { - this.requireCurrentConsumer(params.runId, params.consumerGeneration) - } + requireMailboxConsumer(this, params) const existing = this.db - .prepare("SELECT * FROM deliveries WHERE mailbox_handle = ? AND status = 'outstanding'") + .prepare('SELECT * FROM outstanding_deliveries WHERE mailbox_handle = ?') .get(params.mailboxHandle) as DeliveryRow | undefined if (existing) { if (existing.consumer_generation !== params.consumerGeneration) { @@ -115,15 +114,13 @@ export function acknowledgeMailboxDelivery( runId: string mailboxHandle: string consumerGeneration: number + consumerSource?: 'dispatch' | 'attachment' deliveryId: string - requireCurrentRunConsumer?: boolean } ): { delivery: DeliveryRow; duplicate: boolean } { this.db.exec('BEGIN IMMEDIATE') try { - if (params.requireCurrentRunConsumer) { - this.requireCurrentConsumer(params.runId, params.consumerGeneration) - } + requireMailboxConsumer(this, params) const delivery = this.getDeliveryRaw(params.deliveryId) if ( !delivery || @@ -132,7 +129,7 @@ export function acknowledgeMailboxDelivery( ) { throw new OrchestrationError( 'stale_delivery', - `Delivery ${params.deliveryId} does not belong to this mailbox.` + `Delivery ${params.deliveryId} does not belong to this mailbox. --ack requires a delivery_* ID returned by orchestration check; process the entire batch before acknowledging.` ) } if ( @@ -180,14 +177,12 @@ export function hasOutstandingMailboxDelivery( ): boolean { return Boolean( this.db - .prepare( - "SELECT 1 FROM deliveries WHERE mailbox_handle = ? AND status = 'outstanding' LIMIT 1" - ) + .prepare('SELECT 1 FROM outstanding_deliveries WHERE mailbox_handle = ? LIMIT 1') .get(mailboxHandle) ) } -export function fenceOutstandingMailboxDelivery( +export function fenceUnacknowledgedMailboxDeliveries( this: OrchestrationDb, mailboxHandle: string ): void { @@ -204,7 +199,7 @@ export type RoleMailboxDeliveryMethods = { getOrCreateMailboxDelivery: typeof getOrCreateMailboxDelivery acknowledgeMailboxDelivery: typeof acknowledgeMailboxDelivery hasOutstandingMailboxDelivery: typeof hasOutstandingMailboxDelivery - fenceOutstandingMailboxDelivery: typeof fenceOutstandingMailboxDelivery + fenceUnacknowledgedMailboxDeliveries: typeof fenceUnacknowledgedMailboxDeliveries } export function attachRoleMailboxDelivery(ctor: { prototype: object }): void { @@ -214,6 +209,6 @@ export function attachRoleMailboxDelivery(ctor: { prototype: object }): void { getOrCreateMailboxDelivery, acknowledgeMailboxDelivery, hasOutstandingMailboxDelivery, - fenceOutstandingMailboxDelivery + fenceUnacknowledgedMailboxDeliveries }) } diff --git a/src/main/runtime/orchestration/db/runs/run-binding.ts b/src/main/runtime/orchestration/db/runs/run-binding.ts index a4110dd589f..e2ff77ec818 100644 --- a/src/main/runtime/orchestration/db/runs/run-binding.ts +++ b/src/main/runtime/orchestration/db/runs/run-binding.ts @@ -142,7 +142,7 @@ export function bindRun( WHERE id = ?` ) .run(params.coordinatorHandle, params.coordinatorPaneKey, params.runId) - this.fenceOutstandingDelivery(params.runId) + this.fenceUnacknowledgedMailboxDeliveries(`run:${params.runId}`) if (params.takeoverLegacy || replacesLegacyCoordinator) { this.promoteLegacyCoordinatorMailForTakeover(params.runId, retainedCoordinatorHandle) } diff --git a/src/main/runtime/orchestration/db/runs/run-delivery.ts b/src/main/runtime/orchestration/db/runs/run-delivery.ts index b2fc0ba2b0e..b941c8ae951 100644 --- a/src/main/runtime/orchestration/db/runs/run-delivery.ts +++ b/src/main/runtime/orchestration/db/runs/run-delivery.ts @@ -32,8 +32,7 @@ export function getOrCreateRunDelivery( mailboxHandle: `run:${params.runId}`, consumerGeneration: params.consumerGeneration, limit: params.limit, - wakeTypes: params.wakeTypes, - requireCurrentRunConsumer: true + wakeTypes: params.wakeTypes }) } @@ -49,8 +48,7 @@ export function acknowledgeRunDelivery( runId: params.runId, mailboxHandle: `run:${params.runId}`, consumerGeneration: params.consumerGeneration, - deliveryId: params.deliveryId, - requireCurrentRunConsumer: true + deliveryId: params.deliveryId }) } diff --git a/src/main/runtime/orchestration/db/runs/run-lookup.ts b/src/main/runtime/orchestration/db/runs/run-lookup.ts index 7563effa8c3..194cceffcf0 100644 --- a/src/main/runtime/orchestration/db/runs/run-lookup.ts +++ b/src/main/runtime/orchestration/db/runs/run-lookup.ts @@ -141,7 +141,7 @@ export function unbindOtherRunsForPane( WHERE id = ?` ) .run(run.id) - this.fenceOutstandingDelivery(run.id) + this.fenceUnacknowledgedMailboxDeliveries(`run:${run.id}`) } } } @@ -152,10 +152,6 @@ export function requireRun(this: OrchestrationDb, runId: string): void { } } -export function fenceOutstandingDelivery(this: OrchestrationDb, runId: string): void { - this.fenceOutstandingMailboxDelivery(`run:${runId}`) -} - export type RunLookupMethods = { getRun: typeof getRun getLegacyAdoptedRunMailboxOwner: typeof getLegacyAdoptedRunMailboxOwner @@ -166,7 +162,6 @@ export type RunLookupMethods = { getRunRaw: typeof getRunRaw unbindOtherRunsForPane: typeof unbindOtherRunsForPane requireRun: typeof requireRun - fenceOutstandingDelivery: typeof fenceOutstandingDelivery } export function attachRunLookup(ctor: { prototype: object }): void { @@ -179,7 +174,6 @@ export function attachRunLookup(ctor: { prototype: object }): void { runsBoundToPane, getRunRaw, unbindOtherRunsForPane, - requireRun, - fenceOutstandingDelivery + requireRun }) } diff --git a/src/main/runtime/orchestration/db/schema/create-tables.ts b/src/main/runtime/orchestration/db/schema/create-tables.ts index 70baf6eca74..c0fa229eb3c 100644 --- a/src/main/runtime/orchestration/db/schema/create-tables.ts +++ b/src/main/runtime/orchestration/db/schema/create-tables.ts @@ -1,10 +1,12 @@ import type { OrchestrationDb } from '../orchestration-db' import { createCoreTablesSql } from './create-core-tables-sql' import { createGraphTablesSql } from './create-graph-tables-sql' +import { DERIVED_DELIVERY_SCHEMA_SQL } from './migrate-v41' export function createTables(this: OrchestrationDb): void { this.db.exec(`${createCoreTablesSql()}\n${createGraphTablesSql()}`) this.createMailboxDeliveryIndexesIfPossible() + this.db.exec(DERIVED_DELIVERY_SCHEMA_SQL) } export type CreateTablesMethods = { diff --git a/src/main/runtime/orchestration/db/schema/derived-delivery-migration.test.ts b/src/main/runtime/orchestration/db/schema/derived-delivery-migration.test.ts new file mode 100644 index 00000000000..a868a310e71 --- /dev/null +++ b/src/main/runtime/orchestration/db/schema/derived-delivery-migration.test.ts @@ -0,0 +1,269 @@ +import { mkdtempSync, rmSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { afterEach, describe, expect, it } from 'vitest' +import Database from '../../../../sqlite/sync-database' +import { OrchestrationDb } from '../orchestration-db' +import { dropDerivedDeliverySchema } from './derived-delivery-test-fixture' +import { resolveOrchestrationMigrationStartVersion } from '../../orchestration-schema-version-skew' +import { createRootDispatch } from '../root-dispatch-test-fixture' +import { SCHEMA_VERSION } from '../contract-constants' + +describe('derived delivery migration', () => { + const connections: OrchestrationDb[] = [] + const directories: string[] = [] + afterEach(() => { + for (const db of connections.splice(0)) { + db.close() + } + for (const directory of directories.splice(0)) { + rmSync(directory, { recursive: true, force: true }) + } + }) + function open(path: string) { + const db = new OrchestrationDb(path) + connections.push(db) + return db + } + function databasePath() { + const directory = mkdtempSync(join(tmpdir(), 'orca-derived-delivery-')) + directories.push(directory) + return join(directory, 'orchestration.db') + } + + it('preserves batch identity and terminal facts while removing a persisted wedge', () => { + const path = databasePath() + const original = open(path) + const run = original.createRun({ + objective: 'upgrade', + coordinatorHandle: 'coord', + coordinatorPaneKey: 'tab:11111111-1111-4111-8111-111111111111' + }) + const params = { runId: run.id, consumerGeneration: run.consumer_generation } + const old = original.insertMessage({ + runId: run.id, + from: 'worker', + to: `run:${run.id}`, + subject: 'old' + }) + const batch = original.getDeliveryRaw(original.getOrCreateRunDelivery(params)!.delivery.id)! + const next = original.insertMessage({ + runId: run.id, + from: 'worker', + to: `run:${run.id}`, + subject: 'next' + }) + connections.pop()!.close() + const raw = new Database(path) + dropDerivedDeliverySchema(raw) + raw.prepare('UPDATE messages SET read = 1 WHERE id = ?').run(old.id) + raw.exec(` + INSERT INTO deliveries (id, run_id, mailbox_handle, consumer_generation, message_ids, status, created_at, acknowledged_at) + VALUES ('history_ack', '${run.id}', 'run:${run.id}', 1, '[]', 'acknowledged', '2026-01-01 00:00:00', '2026-01-02 00:00:00'), + ('history_fence', '${run.id}', 'run:${run.id}', 1, '[]', 'fenced', '2026-01-03 00:00:00', NULL); + `) + raw.pragma('user_version = 40') + raw.close() + const db = open(path) + expect(db.getDeliveryRaw(batch.id)).toEqual(batch) + expect(db.hasOutstandingRunDelivery(run.id)).toBe(false) + expect(db.getDeliveryRaw('history_ack')).toMatchObject({ + acknowledged_at: '2026-01-02 00:00:00', + status: 'acknowledged' + }) + expect(db.getDeliveryRaw('history_fence')).toMatchObject({ + acknowledged_at: null, + status: 'fenced' + }) + expect(() => db.acknowledgeRunDelivery({ ...params, deliveryId: 'history_fence' })).toThrow( + expect.objectContaining({ code: 'consumer_fenced' }) + ) + expect(db.getOrCreateRunDelivery(params)?.messages.map((message) => message.id)).toEqual([ + next.id + ]) + expect(db.getDeliveryRaw(batch.id)?.acknowledged_at).toBeNull() + expect(resolveOrchestrationMigrationStartVersion(db.db, SCHEMA_VERSION, SCHEMA_VERSION)).toBe( + SCHEMA_VERSION + ) + const reopened = open(path) + expect(reopened.getOrCreateRunDelivery(params)?.messages.map((message) => message.id)).toEqual([ + next.id + ]) + }) + + it('enforces one active batch using the same derived view and permits history', () => { + const db = open(':memory:') + const run = db.createRun({ + objective: 'constraint', + coordinatorHandle: 'coord', + coordinatorPaneKey: 'tab:11111111-1111-4111-8111-111111111111' + }) + const message = db.insertMessage({ + runId: run.id, + from: 'worker', + to: `run:${run.id}`, + subject: 'one' + }) + const params = { runId: run.id, consumerGeneration: run.consumer_generation } + const first = db.getDeliveryRaw(db.getOrCreateRunDelivery(params)!.delivery.id)! + const insert = db.db.prepare(`INSERT INTO deliveries + (id, run_id, mailbox_handle, consumer_generation, message_ids, acknowledged_at, status) + VALUES (?, ?, ?, ?, ?, ?, ?)`) + const values = [run.id, `run:${run.id}`, run.consumer_generation, JSON.stringify([message.id])] + expect(() => insert.run('duplicate', ...values, null, 'outstanding')).toThrow( + 'Mailbox already has an outstanding delivery' + ) + expect(() => + insert.run('ack_history', ...values, '2026-01-01 00:00:00', 'acknowledged') + ).not.toThrow() + expect(() => insert.run('fenced_history', ...values, null, 'fenced')).not.toThrow() + db.markAsRead([message.id]) + expect(() => insert.run('consumed_history', ...values, null, 'outstanding')).not.toThrow() + expect(db.getDeliveryRaw(first.id)).toEqual(first) + expect(db.hasOutstandingRunDelivery(run.id)).toBe(false) + }) + + it('shares a single batch across connections and rejects replaced consumers after it is consumed', () => { + const path = databasePath() + const first = open(path) + const run = first.createRun({ + objective: 'connections', + coordinatorHandle: 'coord', + coordinatorPaneKey: 'tab:11111111-1111-4111-8111-111111111111' + }) + const params = { runId: run.id, consumerGeneration: run.consumer_generation } + const message = first.insertMessage({ + runId: run.id, + from: 'worker', + to: `run:${run.id}`, + subject: 'one' + }) + const second = open(path) + const batch = first.getOrCreateRunDelivery(params)! + expect(second.getOrCreateRunDelivery(params)?.delivery.id).toBe(batch.delivery.id) + second.markAsRead([message.id]) + const replacement = second.bindRun({ + runId: run.id, + coordinatorHandle: 'replacement', + coordinatorPaneKey: 'other:22222222-2222-4222-9222-222222222222' + })! + expect(first.getDeliveryRaw(batch.delivery.id)).toMatchObject({ + status: 'fenced', + acknowledged_at: null + }) + first.insertMessage({ runId: run.id, from: 'worker', to: `run:${run.id}`, subject: 'next' }) + expect(() => first.getOrCreateRunDelivery(params)).toThrow( + expect.objectContaining({ code: 'consumer_fenced' }) + ) + expect(() => + first.acknowledgeRunDelivery({ ...params, deliveryId: batch.delivery.id }) + ).toThrow(expect.objectContaining({ code: 'consumer_fenced' })) + expect( + second.getOrCreateRunDelivery({ + ...params, + consumerGeneration: replacement.consumer_generation + })?.messages[0].subject + ).toBe('next') + }) + + it.each(['dispatch', 'attachment'] as const)( + 'fences a stale %s consumer across connections even after its batch is read', + (consumerSource) => { + const path = databasePath() + const db = open(path) + const run = db.createRun({ + objective: 'worker connections', + coordinatorHandle: 'coord', + coordinatorPaneKey: 'tab:11111111-1111-4111-8111-111111111111' + }) + const dispatchId = + consumerSource === 'dispatch' + ? createRootDispatch(db, db.createTask({ spec: 'work', runId: run.id }).id, 'worker').id + : 'ctx_remote' + if (consumerSource === 'attachment') { + db.createRemoteDispatchAttachment({ + runId: run.id, + dispatchId, + taskId: 'task_remote', + homePeerFingerprint: 'peer', + runtimeEpoch: 'epoch', + protocolVersion: 1, + mutationReceipt: { + callerFingerprint: 'peer', + requestId: 'attach', + method: 'orchestration.federationAttachStart', + payloadHash: 'hash' + } + }) + } + const mailboxHandle = `dispatch:${dispatchId}` + const message = db.insertMessage({ + runId: run.id, + from: 'coord', + to: mailboxHandle, + subject: 'old' + }) + const params = { runId: run.id, mailboxHandle, consumerGeneration: 0, consumerSource } + const batch = db.getOrCreateMailboxDelivery(params)! + const peer = open(path) + peer.markAsRead([message.id]) + const authority = { + dispatchId, + paneKey: 'other:22222222-2222-4222-9222-222222222222', + processIncarnation: 'worker:2' + } + if (consumerSource === 'dispatch') { + peer.mintDispatchCapability(authority) + } else { + peer.prepareRemoteAttachmentAuthority({ + ...authority, + worktreeId: 'folder', + terminalHandle: 'replacement', + setupState: 'not_applicable', + effects: [] + }) + } + expect(db.getDeliveryRaw(batch.delivery.id)).toMatchObject({ + status: 'fenced', + acknowledged_at: null + }) + peer.insertMessage({ runId: run.id, from: 'coord', to: mailboxHandle, subject: 'next' }) + expect(() => db.getOrCreateMailboxDelivery(params)).toThrow( + expect.objectContaining({ code: 'consumer_fenced' }) + ) + expect(() => + db.acknowledgeMailboxDelivery({ ...params, deliveryId: batch.delivery.id }) + ).toThrow(expect.objectContaining({ code: 'consumer_fenced' })) + expect( + peer.getOrCreateMailboxDelivery({ ...params, consumerGeneration: 1 })?.messages[0].subject + ).toBe('next') + } + ) + + it('keeps the pre-v41 column and index shape a downgraded binary reads', () => { + const db = open(':memory:') + expect( + (db.db.pragma('table_info(deliveries)') as { name: string }[]).map((c) => c.name) + ).toContain('status') + const index = db.db + .prepare("SELECT sql FROM sqlite_master WHERE name = 'idx_deliveries_one_outstanding'") + .get() as { sql: string } + expect(index.sql).not.toContain('UNIQUE') + expect(index.sql).toContain("status = 'outstanding' AND mailbox_handle != ''") + // Why: a v40 binary probes exactly these objects before trusting the stamp; nothing it needs is gone. + expect(resolveOrchestrationMigrationStartVersion(db.db, SCHEMA_VERSION, 40)).toBe( + SCHEMA_VERSION + ) + }) + + it('recreates a missing derived view on reopen without changing batch records', () => { + const path = databasePath() + const db = open(path) + db.db.exec('DROP VIEW outstanding_deliveries') + const reopened = open(path) + expect(reopened.hasOutstandingMailboxDelivery('run:missing')).toBe(false) + expect( + resolveOrchestrationMigrationStartVersion(reopened.db, SCHEMA_VERSION, SCHEMA_VERSION) + ).toBe(SCHEMA_VERSION) + }) +}) diff --git a/src/main/runtime/orchestration/db/schema/derived-delivery-test-fixture.ts b/src/main/runtime/orchestration/db/schema/derived-delivery-test-fixture.ts new file mode 100644 index 00000000000..0c1247b753b --- /dev/null +++ b/src/main/runtime/orchestration/db/schema/derived-delivery-test-fixture.ts @@ -0,0 +1,9 @@ +import type { OrchestrationDb } from '../orchestration-db' + +// Tests that hand-edit the deliveries table must drop the derived objects first: SQLite refuses +// DROP COLUMN / RENAME while a trigger or view still references the table. Reopening recreates them. +export function dropDerivedDeliverySchema(db: OrchestrationDb['db']): void { + db.exec( + 'DROP TRIGGER IF EXISTS trg_deliveries_one_outstanding; DROP VIEW IF EXISTS outstanding_deliveries;' + ) +} diff --git a/src/main/runtime/orchestration/db/schema/migrate-v41.ts b/src/main/runtime/orchestration/db/schema/migrate-v41.ts new file mode 100644 index 00000000000..e3716703142 --- /dev/null +++ b/src/main/runtime/orchestration/db/schema/migrate-v41.ts @@ -0,0 +1,36 @@ +import type { OrchestrationDb } from '../orchestration-db' + +// Why: eligibility comes from unread membership, so a fully read but unacknowledged batch must not +// block the next insert. The index keeps its pre-v41 name and predicate so downgraded binaries' +// IF NOT EXISTS create and schema probes still pass; only uniqueness is dropped. +export const OUTSTANDING_MAILBOX_INDEX_SQL = ` + CREATE INDEX IF NOT EXISTS idx_deliveries_one_outstanding + ON deliveries(mailbox_handle) WHERE status = 'outstanding' AND mailbox_handle != ''; +` + +export const DERIVED_DELIVERY_SCHEMA_SQL = ` + CREATE VIEW IF NOT EXISTS outstanding_deliveries AS + SELECT * FROM deliveries + WHERE status = 'outstanding' + AND EXISTS ( + SELECT 1 FROM json_each(deliveries.message_ids) AS member + JOIN messages ON messages.id = member.value WHERE messages.read = 0 + ); + CREATE TRIGGER IF NOT EXISTS trg_deliveries_one_outstanding + AFTER INSERT ON deliveries + WHEN NEW.mailbox_handle != '' AND EXISTS ( + SELECT 1 FROM outstanding_deliveries WHERE mailbox_handle = NEW.mailbox_handle LIMIT 1 OFFSET 1 + ) + BEGIN + SELECT RAISE(ABORT, 'Mailbox already has an outstanding delivery'); + END; +` + +export function migrateV41(this: OrchestrationDb, current: number): void { + if (current >= 41) { + return + } + this.db.exec( + `DROP INDEX IF EXISTS idx_deliveries_one_outstanding;\n${OUTSTANDING_MAILBOX_INDEX_SQL}` + ) +} diff --git a/src/main/runtime/orchestration/db/schema/migrate.ts b/src/main/runtime/orchestration/db/schema/migrate.ts index 582dedf4752..bcf1b830ebc 100644 --- a/src/main/runtime/orchestration/db/schema/migrate.ts +++ b/src/main/runtime/orchestration/db/schema/migrate.ts @@ -11,6 +11,7 @@ import { migrateV37 } from './migrate-v37' import { migrateV38 } from './migrate-v38' import { migrateV39 } from './migrate-v39' import { migrateV40 } from './migrate-v40' +import { DERIVED_DELIVERY_SCHEMA_SQL, migrateV41 } from './migrate-v41' // Why: CREATE TABLE IF NOT EXISTS won't alter existing DBs; migrate in a txn that bumps user_version only on success (atomic all-or-nothing). export function migrate(this: OrchestrationDb): void { @@ -22,6 +23,9 @@ export function migrate(this: OrchestrationDb): void { this.db.exec('BEGIN IMMEDIATE') try { + this.db.exec( + 'DROP TRIGGER IF EXISTS trg_deliveries_one_outstanding; DROP VIEW IF EXISTS outstanding_deliveries;' + ) applySchemaMigrationsV2ToV12.call(this, current) applySchemaMigrationsV13ToV30.call(this, current) migrateMailboxPointerEnterV33.call(this, current) @@ -32,7 +36,11 @@ export function migrate(this: OrchestrationDb): void { migrateV38.call(this, current) migrateV39.call(this, current) migrateV40.call(this, current) + // Why: older steps recreate the unique index; v41 must run after them. + migrateV41.call(this, current) this.createMailboxDeliveryIndexesIfPossible() + // Why: rebuild steps above RENAME the table, which SQLite refuses while a view names it. + this.db.exec(DERIVED_DELIVERY_SCHEMA_SQL) this.db.pragma(`user_version = ${SCHEMA_VERSION}`) this.db.exec('COMMIT') } catch (err) { diff --git a/src/main/runtime/orchestration/db/schema/schema-column-probes.ts b/src/main/runtime/orchestration/db/schema/schema-column-probes.ts index 07e71e9e9d3..dad0f64d0ad 100644 --- a/src/main/runtime/orchestration/db/schema/schema-column-probes.ts +++ b/src/main/runtime/orchestration/db/schema/schema-column-probes.ts @@ -1,4 +1,5 @@ import type { OrchestrationDb } from '../orchestration-db' +import { OUTSTANDING_MAILBOX_INDEX_SQL } from './migrate-v41' export function hasColumn(this: OrchestrationDb, table: string, column: string): boolean { const rows = this.db.pragma(`table_info(${table})`) as { name: string }[] @@ -7,12 +8,7 @@ export function hasColumn(this: OrchestrationDb, table: string, column: string): export function createMailboxDeliveryIndexesIfPossible(this: OrchestrationDb): void { if (this.hasColumn('deliveries', 'mailbox_handle')) { - // Excluding '' trades the pre-v34 per-run one-outstanding backstop for downgraded binaries; the - // app-level BEGIN IMMEDIATE still serializes one process. - this.db.exec(` - CREATE UNIQUE INDEX IF NOT EXISTS idx_deliveries_one_outstanding - ON deliveries(mailbox_handle) WHERE status = 'outstanding' AND mailbox_handle != ''; - `) + this.db.exec(OUTSTANDING_MAILBOX_INDEX_SQL) } const hasDeliveredAt = this.hasColumn('messages', 'delivered_at') if (hasDeliveredAt) { diff --git a/src/main/runtime/orchestration/db/worker-dispatch/worker-dispatch-authority.ts b/src/main/runtime/orchestration/db/worker-dispatch/worker-dispatch-authority.ts index 57ec354a8cc..b33a8798dc3 100644 --- a/src/main/runtime/orchestration/db/worker-dispatch/worker-dispatch-authority.ts +++ b/src/main/runtime/orchestration/db/worker-dispatch/worker-dispatch-authority.ts @@ -75,7 +75,7 @@ export function prepareStartingWorkerAuthority( `Dispatch ${params.dispatchId} is not starting.` ) } - this.fenceOutstandingMailboxDelivery(`dispatch:${params.dispatchId}`) + this.fenceUnacknowledgedMailboxDeliveries(`dispatch:${params.dispatchId}`) const workerUpdate = this.db .prepare( `UPDATE worker_dispatches diff --git a/src/main/runtime/orchestration/dispatch-consumer-generation-migration.test.ts b/src/main/runtime/orchestration/dispatch-consumer-generation-migration.test.ts index 9cc195d6402..d6bc9ca9477 100644 --- a/src/main/runtime/orchestration/dispatch-consumer-generation-migration.test.ts +++ b/src/main/runtime/orchestration/dispatch-consumer-generation-migration.test.ts @@ -3,6 +3,7 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import Database from '../../sqlite/sync-database' +import { dropDerivedDeliverySchema } from './db/schema/derived-delivery-test-fixture' import { OrchestrationDb } from './db' import { SCHEMA_VERSION } from './db/contract-constants' import { createRootDispatch } from './db/root-dispatch-test-fixture' @@ -48,6 +49,7 @@ describe('OrchestrationDb v35 to v36 migration', () => { seed.close() const raw = new Database(dbPath) + dropDerivedDeliverySchema(raw) raw.exec(` ALTER TABLE dispatch_contexts DROP COLUMN consumer_generation; ALTER TABLE remote_dispatch_attachments DROP COLUMN consumer_generation; @@ -78,6 +80,7 @@ describe('OrchestrationDb v35 to v36 migration', () => { it('does not send a v35 stamp back to the pre-Run repair floor', () => { const v35 = createV35Database() const raw = new Database(v35.path) + dropDerivedDeliverySchema(raw) try { expect(resolveOrchestrationMigrationStartVersion(raw, 35, SCHEMA_VERSION)).toBe(35) } finally { @@ -88,6 +91,7 @@ describe('OrchestrationDb v35 to v36 migration', () => { it('repairs a database stamped v36 that never got the columns', () => { const v35 = createV35Database() const raw = new Database(v35.path) + dropDerivedDeliverySchema(raw) raw.pragma('user_version = 36') try { // Why: the skew repair is the only thing that catches a partially-written v36. diff --git a/src/main/runtime/orchestration/federation-acknowledgment-migration.test.ts b/src/main/runtime/orchestration/federation-acknowledgment-migration.test.ts index ede53f0d521..9791dbde9b3 100644 --- a/src/main/runtime/orchestration/federation-acknowledgment-migration.test.ts +++ b/src/main/runtime/orchestration/federation-acknowledgment-migration.test.ts @@ -3,6 +3,7 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import Database from '../../sqlite/sync-database' +import { dropDerivedDeliverySchema } from './db/schema/derived-delivery-test-fixture' import { OrchestrationDb } from './db' import { resolveOrchestrationMigrationStartVersion } from './orchestration-schema-version-skew' import { SCHEMA_VERSION } from './db/contract-constants' @@ -26,6 +27,7 @@ describe('federation acknowledgment migration', () => { db = undefined const oldDb = new Database(dbPath) + dropDerivedDeliverySchema(oldDb) oldDb.exec('ALTER TABLE federated_dispatches DROP COLUMN to_home_acknowledged_sequence') oldDb.pragma('user_version = 26') expect(resolveOrchestrationMigrationStartVersion(oldDb, 26, 28)).toBe(26) diff --git a/src/main/runtime/orchestration/nested-worker-depth-migration.test.ts b/src/main/runtime/orchestration/nested-worker-depth-migration.test.ts index 9d05c0dac07..eb0f53a30d5 100644 --- a/src/main/runtime/orchestration/nested-worker-depth-migration.test.ts +++ b/src/main/runtime/orchestration/nested-worker-depth-migration.test.ts @@ -3,6 +3,7 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import Database from '../../sqlite/sync-database' +import { dropDerivedDeliverySchema } from './db/schema/derived-delivery-test-fixture' import { OrchestrationDb } from './db' import { resolveOrchestrationMigrationStartVersion } from './orchestration-schema-version-skew' import { SCHEMA_VERSION } from './db/contract-constants' @@ -32,6 +33,7 @@ describe('nested worker depth migration (v30)', () => { fresh.close() const oldDb = new Database(dbPath) + dropDerivedDeliverySchema(oldDb) oldDb.exec('ALTER TABLE dispatch_contexts DROP COLUMN depth') oldDb.exec('ALTER TABLE remote_dispatch_attachments DROP COLUMN depth') oldDb.exec('ALTER TABLE remote_dispatch_attachments DROP COLUMN home_run_id') @@ -95,6 +97,7 @@ describe('nested worker depth migration (v30)', () => { // replay migrations from v6 instead of starting at 29. const dbPath = createV29Database() const oldDb = new Database(dbPath) + dropDerivedDeliverySchema(oldDb) expect(resolveOrchestrationMigrationStartVersion(oldDb, 29, SCHEMA_VERSION)).toBe(29) oldDb.close() }) diff --git a/src/main/runtime/orchestration/orchestration-delivery-consumption.test.ts b/src/main/runtime/orchestration/orchestration-delivery-consumption.test.ts new file mode 100644 index 00000000000..49c8977c417 --- /dev/null +++ b/src/main/runtime/orchestration/orchestration-delivery-consumption.test.ts @@ -0,0 +1,146 @@ +import { afterEach, describe, expect, it } from 'vitest' +import { OrchestrationDb } from './db' +import { createRootDispatch } from './db/root-dispatch-test-fixture' +import { reconcileLifecycleMessage } from './lifecycle-reconciliation' + +describe('mailbox delivery consumption', () => { + let db: OrchestrationDb + afterEach(() => db?.close()) + + function setup() { + db = new OrchestrationDb(':memory:') + const run = db.createRun({ + objective: 'Retired delivery', + coordinatorHandle: 'term_coord', + coordinatorPaneKey: 'tab:11111111-1111-4111-8111-111111111111' + }) + const params = { runId: run.id, consumerGeneration: run.consumer_generation } + const insert = (subject: string) => + db.insertMessage({ runId: run.id, from: 'worker', to: `run:${run.id}`, subject }) + return { run, params, insert } + } + + it('advances past a heartbeat batch when completion suppresses its contents', () => { + const { run, params } = setup() + const task = db.createTask({ runId: run.id, spec: 'work' }) + const dispatch = createRootDispatch(db, task.id, 'worker') + const insert = (type: 'heartbeat' | 'worker_done') => + db.insertMessage({ + runId: run.id, + from: 'worker', + to: `run:${run.id}`, + subject: type, + type, + payload: JSON.stringify({ taskId: task.id, dispatchId: dispatch.id, outcome: 'succeeded' }) + }) + insert('heartbeat') + const first = db.getOrCreateRunDelivery(params)! + const done = insert('worker_done') + expect(reconcileLifecycleMessage(db, done).action).toBe('completed') + expect(db.getDeliveryRaw(first.delivery.id)?.acknowledged_at).toBeNull() + expect(db.hasOutstandingRunDelivery(run.id)).toBe(false) + expect( + db + .getOrCreateRunDelivery({ ...params, wakeTypes: ['worker_done'] }) + ?.messages.map((m) => m.id) + ).toEqual([done.id]) + expect(db.acknowledgeRunDelivery({ ...params, deliveryId: first.delivery.id }).duplicate).toBe( + false + ) + }) + + it('ignores a fully read batch without rewriting it', () => { + const { params, insert } = setup() + const old = insert('old') + const first = db.getOrCreateRunDelivery(params)! + db.db.prepare('UPDATE messages SET read = 1 WHERE id = ?').run(old.id) + const next = insert('next') + const current = db.getOrCreateRunDelivery(params)! + expect(current.messages.map((m) => m.id)).toEqual([next.id]) + expect(current.replayed).toBe(false) + expect(db.getDeliveryRaw(first.delivery.id)?.acknowledged_at).toBeNull() + }) + + it('preserves the entire replay batch while any member is unread', () => { + const { params, insert } = setup() + const a = insert('a') + const b = insert('b') + const first = db.getOrCreateRunDelivery(params)! + db.markAsReadAndDelivered([a.id]) + insert('later') + const replay = db.getOrCreateRunDelivery(params)! + expect(replay.delivery.id).toBe(first.delivery.id) + expect(replay.messages.map((m) => m.id)).toEqual([a.id, b.id]) + expect(replay.replayed).toBe(true) + }) + + it('derives eligibility again when a read transaction rolls back', () => { + const { params, insert } = setup() + const message = insert('old') + const first = db.getOrCreateRunDelivery(params)! + const before = db.getDeliveryRaw(first.delivery.id) + db.db.exec('BEGIN') + db.markAsReadAndDelivered([message.id]) + expect(db.getDeliveryRaw(first.delivery.id)?.acknowledged_at).toBeNull() + expect(db.hasOutstandingRunDelivery(params.runId)).toBe(false) + db.db.exec('ROLLBACK') + expect(db.hasOutstandingRunDelivery(params.runId)).toBe(true) + expect(db.getDeliveryRaw(first.delivery.id)).toEqual(before) + expect(db.getMessageById(message.id)?.read).toBe(0) + expect(db.getDeliveryRaw(first.delivery.id)?.acknowledged_at).toBeNull() + }) + + it('explains the delivery ID contract for invalid acknowledgements without consuming mail', () => { + const { params, insert } = setup() + const message = insert('pending') + const first = db.getOrCreateRunDelivery(params)! + expect(() => db.acknowledgeRunDelivery({ ...params, deliveryId: message.id })).toThrow( + '--ack requires a delivery_* ID returned by orchestration check; process the entire batch before acknowledging.' + ) + expect(db.getMessageById(message.id)?.read).toBe(0) + expect(db.getDeliveryRaw(first.delivery.id)?.acknowledged_at).toBeNull() + }) + + it('checks the consumer generation even when the prior batch is already read', () => { + const { run, params, insert } = setup() + const message = insert('old') + const first = db.getOrCreateRunDelivery(params)! + db.db.prepare('UPDATE messages SET read = 1 WHERE id = ?').run(message.id) + expect(() => + db.getOrCreateMailboxDelivery({ + ...params, + mailboxHandle: `run:${run.id}`, + consumerGeneration: params.consumerGeneration + 1 + }) + ).toThrow(expect.objectContaining({ code: 'consumer_fenced' })) + expect(db.getDeliveryRaw(first.delivery.id)?.acknowledged_at).toBeNull() + }) + + it.each(['markAsRead', 'markAsReadAndDelivered'] as const)( + '%s releases dispatch mail without changing a different mailbox', + (method) => { + const { run, params, insert } = setup() + insert('coordinator mail') + db.getOrCreateRunDelivery(params)! + const task = db.createTask({ runId: run.id, spec: 'worker mail' }) + const dispatch = createRootDispatch(db, task.id, 'worker') + const mailboxHandle = `dispatch:${dispatch.id}` + const message = db.insertMessage({ + runId: run.id, + from: 'term_coord', + to: mailboxHandle, + subject: 'worker mail' + }) + const workerParams = { + ...params, + mailboxHandle, + consumerGeneration: dispatch.consumer_generation + } + db.getOrCreateMailboxDelivery(workerParams)! + db[method]([message.id]) + expect(db.hasOutstandingMailboxDelivery(mailboxHandle)).toBe(false) + expect(db.getOrCreateMailboxDelivery(workerParams)).toBeUndefined() + expect(db.hasOutstandingRunDelivery(run.id)).toBe(true) + } + ) +}) diff --git a/src/main/runtime/orchestration/orchestration-derived-delivery.test.ts b/src/main/runtime/orchestration/orchestration-derived-delivery.test.ts new file mode 100644 index 00000000000..666c0aeae6f --- /dev/null +++ b/src/main/runtime/orchestration/orchestration-derived-delivery.test.ts @@ -0,0 +1,56 @@ +import { afterEach, describe, expect, it } from 'vitest' +import { OrchestrationDb } from './db' + +describe('delivery eligibility derived from messages', () => { + let db: OrchestrationDb + afterEach(() => db?.close()) + + function setup() { + db = new OrchestrationDb(':memory:') + const run = db.createRun({ + objective: 'Derived delivery', + coordinatorHandle: 'coord', + coordinatorPaneKey: 'tab:11111111-1111-4111-8111-111111111111' + }) + const params = { runId: run.id, consumerGeneration: run.consumer_generation } + const message = db.insertMessage({ + runId: run.id, + from: 'worker', + to: `run:${run.id}`, + subject: 'old' + }) + const first = db.getOrCreateRunDelivery(params)! + return { run, params, message, first } + } + + it.each(['read mutation', 'lifecycle suppression', 'direct SQL'])( + '%s changes eligibility without updating the batch', + (path) => { + const { run, params, message, first } = setup() + const before = db.getDeliveryRaw(first.delivery.id) + if (path === 'read mutation') { + db.markAsRead([message.id]) + } else if (path === 'lifecycle suppression') { + db.markAsReadAndDelivered([message.id]) + } else { + db.db.prepare('UPDATE messages SET read = 1 WHERE id = ?').run(message.id) + } + expect(db.getDeliveryRaw(first.delivery.id)).toEqual(before) + expect(db.hasOutstandingRunDelivery(run.id)).toBe(false) + const changes = db.db.prepare('SELECT total_changes() AS n').get() + expect(db.getOrCreateRunDelivery(params)).toBeUndefined() + expect(db.db.prepare('SELECT total_changes() AS n').get()).toEqual(changes) + expect(db.getDeliveryRaw(first.delivery.id)?.acknowledged_at).toBeNull() + } + ) + + it('records only an actual acknowledgement, including after all messages were suppressed', () => { + const { params, message, first } = setup() + db.markAsReadAndDelivered([message.id]) + expect(db.getDeliveryRaw(first.delivery.id)?.acknowledged_at).toBeNull() + const ack = { ...params, deliveryId: first.delivery.id } + expect(db.acknowledgeRunDelivery(ack).duplicate).toBe(false) + expect(db.getDeliveryRaw(first.delivery.id)?.acknowledged_at).not.toBeNull() + expect(db.acknowledgeRunDelivery(ack).duplicate).toBe(true) + }) +}) diff --git a/src/main/runtime/orchestration/orchestration-legacy-storage-test-fixture.ts b/src/main/runtime/orchestration/orchestration-legacy-storage-test-fixture.ts index 886f2383db5..42087d7e79a 100644 --- a/src/main/runtime/orchestration/orchestration-legacy-storage-test-fixture.ts +++ b/src/main/runtime/orchestration/orchestration-legacy-storage-test-fixture.ts @@ -3,6 +3,7 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import Database from '../../sqlite/sync-database' import { LEGACY_RUN_ID, OrchestrationDb } from './db' +import { dropDerivedDeliverySchema } from './db/schema/derived-delivery-test-fixture' import { createRootDispatch } from './db/root-dispatch-test-fixture' export type LegacyStorageCutoverFixture = { @@ -175,6 +176,7 @@ export function createLegacyStorageCutoverFixture(): { first.close() const raw = new Database(dbPath) + dropDerivedDeliverySchema(raw) const legacyDeliveryId = 'delivery_legacy_outstanding' raw .prepare( diff --git a/src/main/runtime/orchestration/orchestration-version-skew-migration.test.ts b/src/main/runtime/orchestration/orchestration-version-skew-migration.test.ts index f8fa7a5df48..a732729a1d5 100644 --- a/src/main/runtime/orchestration/orchestration-version-skew-migration.test.ts +++ b/src/main/runtime/orchestration/orchestration-version-skew-migration.test.ts @@ -6,6 +6,7 @@ import Database from '../../sqlite/sync-database' import { LEGACY_CONTRACT_VERSION, LEGACY_RUN_ID, OrchestrationDb } from './db' import { resolveOrchestrationMigrationStartVersion } from './orchestration-schema-version-skew' import { createRootDispatch } from './db/root-dispatch-test-fixture' +import { dropDerivedDeliverySchema } from './db/schema/derived-delivery-test-fixture' import { SCHEMA_VERSION } from './db/contract-constants' describe('OrchestrationDb version-skew migration', () => { @@ -267,6 +268,7 @@ describe('OrchestrationDb version-skew migration', () => { db = undefined const raw = new Database(dbPath) + dropDerivedDeliverySchema(raw) raw.exec(` DROP INDEX idx_deliveries_one_outstanding; ALTER TABLE deliveries DROP COLUMN mailbox_handle; @@ -303,6 +305,7 @@ describe('OrchestrationDb version-skew migration', () => { db = undefined const raw = new Database(dbPath) + dropDerivedDeliverySchema(raw) raw.exec(` DROP INDEX idx_deliveries_one_outstanding; ALTER TABLE deliveries DROP COLUMN mailbox_handle; @@ -374,15 +377,7 @@ describe('OrchestrationDb version-skew migration', () => { expect(deliveryIndexes.map(({ name }) => name)).toEqual( expect.arrayContaining(['idx_deliveries_one_outstanding', 'idx_deliveries_run_created']) ) - expect(() => - db!.db - .prepare( - `INSERT INTO deliveries ( - id, run_id, mailbox_handle, consumer_generation, message_ids - ) VALUES (?, ?, ?, ?, '[]')` - ) - .run('delivery_v34_duplicate', run.id, `run:${run.id}`, run.consumer_generation) - ).toThrow(/UNIQUE constraint failed/) + expect(db.hasOutstandingRunDelivery(run.id)).toBe(false) }) it('cleans additive lifecycle rows when a v30 writer resets tasks before re-upgrade', () => { @@ -489,6 +484,7 @@ describe('OrchestrationDb version-skew migration', () => { db = undefined const raw = new Database(dbPath) + dropDerivedDeliverySchema(raw) raw.exec(` DROP TABLE deliveries; CREATE TABLE deliveries ( @@ -567,6 +563,7 @@ describe('OrchestrationDb version-skew migration', () => { db = undefined const raw = new Database(dbPath) + dropDerivedDeliverySchema(raw) raw.exec(` DROP INDEX IF EXISTS idx_deliveries_one_outstanding; CREATE UNIQUE INDEX idx_deliveries_one_outstanding diff --git a/src/main/runtime/rpc/methods/files-base64-padding.test.ts b/src/main/runtime/rpc/methods/files-base64-padding.test.ts new file mode 100644 index 00000000000..03f3b73e786 --- /dev/null +++ b/src/main/runtime/rpc/methods/files-base64-padding.test.ts @@ -0,0 +1,58 @@ +import { describe, expect, it, vi } from 'vitest' +import type { OrcaRuntimeService } from '../../orca-runtime' +import { RpcDispatcher } from '../dispatcher' +import { FILE_MUTATION_METHODS } from './files-mutation-methods' + +describe.each([ + ['files.writeBase64', 'writeFileExplorerFileBase64'], + ['files.writeBase64Chunk', 'writeFileExplorerFileBase64Chunk'] +] as const)('%s base64 padding', (method, runtimeMethod) => { + it.each([ + ['A=', false], + ['AA=', false], + ['A==', false], + ['==', false], + ['AAAAA=', false], + ['AAAAAA=', false], + ['AAAAA==', false], + ['AAAA==', false], + ['AA==', true], + ['AAA=', true], + ['AAAA', true], + ['', true], + ['A', false], + ['AA=A', false], + ['AA', true], + ['AAA', true] + ])('validates %j before writing (accepted: %s)', async (contentBase64, accepted) => { + const write = vi.fn().mockResolvedValue({ ok: true }) + const runtime = { + getRuntimeId: () => 'test-runtime', + [runtimeMethod]: write + } as unknown as OrcaRuntimeService + const dispatcher = new RpcDispatcher({ runtime, methods: FILE_MUTATION_METHODS }) + + const response = await dispatcher.dispatch({ + id: 'padding', + authToken: 'tok', + method, + params: { + worktree: 'id:wt-1', + relativePath: 'upload.bin', + contentBase64, + append: true + } + }) + + expect(response).toMatchObject({ ok: accepted }) + expect(write).toHaveBeenCalledTimes(accepted ? 1 : 0) + if (accepted) { + expect(write).toHaveBeenCalledWith( + 'id:wt-1', + 'upload.bin', + contentBase64, + ...(method === 'files.writeBase64Chunk' ? [true] : []) + ) + } + }) +}) diff --git a/src/main/runtime/rpc/methods/files.ts b/src/main/runtime/rpc/methods/files.ts index 055c02b3265..29e2f7b071f 100644 --- a/src/main/runtime/rpc/methods/files.ts +++ b/src/main/runtime/rpc/methods/files.ts @@ -7,6 +7,7 @@ import { limitQuickOpenSearchReplyBySerializedBytes } from '../../../../shared/q import { FileOpen, WorktreeSelector } from './files-target-schemas' import { FILE_TERMINAL_ARTIFACT_METHODS } from './files-terminal-artifact-methods' import { + FilePathsExist, DocPreviewFileRead, FileListAll, FileOpenDiff, @@ -164,6 +165,12 @@ export const FILE_METHODS = [ params: WorktreeSelector, handler: async (params, { runtime }) => runtime.listRuntimeMarkdownDocuments(params.worktree) }), + defineMethod({ + name: 'files.pathsExist', + params: FilePathsExist, + handler: async (params, { runtime }) => + runtime.pathsExistRuntimeFiles(params.worktree, params.relativePaths) + }), defineMethod({ name: 'files.stat', params: FileTreePath, diff --git a/src/main/runtime/rpc/methods/orchestration/messaging/check-delivery-history.test.ts b/src/main/runtime/rpc/methods/orchestration/messaging/check-delivery-history.test.ts new file mode 100644 index 00000000000..75f69c06ee5 --- /dev/null +++ b/src/main/runtime/rpc/methods/orchestration/messaging/check-delivery-history.test.ts @@ -0,0 +1,46 @@ +import { afterEach, describe, expect, it } from 'vitest' +import { createOrchestrationRpcHarness } from '../rpc-test-harness' + +describe('Run delivery history', () => { + const h = createOrchestrationRpcHarness() + afterEach(() => h.cleanup()) + + it('does not label filtered history as an acknowledgeable delivery', async () => { + const { db, ctx, activeRunId } = h.setup() + const params = { terminal: 'term_coord', run: activeRunId, all: true } + db.insertMessage({ + from: 'worker', + to: `run:${activeRunId}`, + runId: activeRunId, + subject: 'waiting' + }) + expect(await h.call('orchestration.check', params, ctx)).toMatchObject({ + count: 1 + }) + expect(db.hasOutstandingRunDelivery(activeRunId!)).toBe(false) + const delivery = db.getOrCreateRunDelivery({ + runId: activeRunId!, + consumerGeneration: db.getRun(activeRunId!)!.consumer_generation + })! + db.insertMessage({ + from: 'worker', + to: `run:${activeRunId}`, + runId: activeRunId, + subject: 'later completion', + type: 'worker_done' + }) + const history = await h.call( + 'orchestration.check', + { + ...params, + format: true, + types: 'worker_done' + }, + ctx + ) + expect(history).toMatchObject({ count: 1, messages: [{ subject: 'later completion' }] }) + expect(history).not.toHaveProperty('deliveryId') + expect(db.hasOutstandingRunDelivery(activeRunId!)).toBe(true) + expect(db.getMessageById(delivery.messages[0].id)?.read).toBe(0) + }) +}) diff --git a/src/main/runtime/rpc/methods/orchestration/messaging/check-worker.ts b/src/main/runtime/rpc/methods/orchestration/messaging/check-worker.ts index 355a12be5c1..fc9fa6b04e9 100644 --- a/src/main/runtime/rpc/methods/orchestration/messaging/check-worker.ts +++ b/src/main/runtime/rpc/methods/orchestration/messaging/check-worker.ts @@ -172,6 +172,7 @@ export async function checkWorkerMailbox(args: { runId: deliveryRunId, mailboxHandle: address, consumerGeneration: workerMailbox.generation, + consumerSource: activeDispatch ? 'dispatch' : 'attachment', deliveryId: params.ack }) : undefined @@ -181,16 +182,12 @@ export async function checkWorkerMailbox(args: { const showAll = params.all === true || (params.unread === false && params.peek !== true) const readPeek = () => db.getUnreadMessages(address, typeFilter) const readDelivery = (wakeTypes?: MessageType[]) => { - // Why: re-read live, or a re-attach landing on an await above mints a Delivery at a generation - // the row has already left, which then fences the legitimate worker on every later check. - if (readCurrentGeneration() !== workerMailbox.generation) { - throw dispatchFenced() - } try { return db.getOrCreateMailboxDelivery({ runId: deliveryRunId, mailboxHandle: address, consumerGeneration: workerMailbox.generation, + consumerSource: activeDispatch ? 'dispatch' : 'attachment', wakeTypes }) } catch (error) { diff --git a/src/main/runtime/rpc/methods/skills.test.ts b/src/main/runtime/rpc/methods/skills.test.ts index 9bc5a647c82..097a948febf 100644 --- a/src/main/runtime/rpc/methods/skills.test.ts +++ b/src/main/runtime/rpc/methods/skills.test.ts @@ -106,6 +106,25 @@ describe('skills.discover RPC', () => { it('accepts a params payload from an older client that cannot send refresh', () => { expect(discoverMethod().params?.parse({ cwd: '/repo' })).toEqual({ cwd: '/repo' }) }) + + it('preserves portable filters through the server RPC boundary', async () => { + await discoverMethod().handler( + { names: ['orchestration'], sourceKinds: ['home'] }, + makeContext({}) + ) + + expect(vi.mocked(resolveSkillDiscoveryTarget)).toHaveBeenLastCalledWith( + expect.objectContaining({ names: ['orchestration'], sourceKinds: ['home'] }) + ) + }) + + it('accepts empty portable filters as an unbounded request', async () => { + await discoverMethod().handler({ names: [], sourceKinds: [] }, makeContext({})) + + expect(vi.mocked(resolveSkillDiscoveryTarget)).toHaveBeenLastCalledWith( + expect.objectContaining({ names: [], sourceKinds: [] }) + ) + }) }) describe('skills.install RPC', () => { diff --git a/src/main/runtime/rpc/methods/task-provider-identity.test.ts b/src/main/runtime/rpc/methods/task-provider-identity.test.ts new file mode 100644 index 00000000000..1cf6d54381c --- /dev/null +++ b/src/main/runtime/rpc/methods/task-provider-identity.test.ts @@ -0,0 +1,141 @@ +import { describe, expect, it } from 'vitest' +import { + AutomationUpdate, + TaskProviderIdentity, + TaskSourceContext +} from '../../../../shared/rpc-contract/automation-params' +import type { TaskProviderIdentity as ProviderIdentity } from '../../../../shared/task-source-context' + +const identities = [ + { provider: 'github', owner: 'Acme', repo: 'Orca', host: 'github.example.com' }, + { + provider: 'gitlab', + projectId: '123', + namespace: 'acme/team', + project: 'orca', + webUrl: 'https://gitlab.example.com/acme/team/orca' + }, + { + provider: 'linear', + workspaceId: 'workspace', + workspaceName: 'Acme', + teamId: 'team', + teamKey: 'ENG' + }, + { provider: 'jira', siteId: 'site', siteUrl: 'https://acme.atlassian.net', projectKey: 'ENG' } +] satisfies ProviderIdentity[] + +describe('task provider identity RPC validation', () => { + it.each(identities)('preserves valid $provider identities', (identity) => { + expect(TaskProviderIdentity.parse(identity)).toEqual(identity) + }) + + it.each(['owner', 'repo'])('requires the GitHub %s', (field) => { + const identity: Record = { ...identities[0] } + delete identity[field] + expect(TaskProviderIdentity.safeParse(identity).success).toBe(false) + expect(TaskProviderIdentity.safeParse({ ...identity, [field]: null }).success).toBe(false) + }) + + for (const identity of identities) { + for (const field of Object.keys(identity).filter((key) => key !== 'provider')) { + it.each([42, false, [], {}])( + `rejects non-string ${identity.provider}.${field}: %j`, + (value) => { + expect(TaskProviderIdentity.safeParse({ ...identity, [field]: value }).success).toBe( + false + ) + } + ) + } + } + + it.each(['gitlab', 'linear', 'jira'])('keeps %s fields optional and nullable', (provider) => { + expect(TaskProviderIdentity.parse({ provider })).toEqual({ provider }) + const full = identities.find((identity) => identity.provider === provider)! + const nullable = Object.fromEntries( + Object.keys(full).map((key) => [key, key === 'provider' ? provider : null]) + ) + expect(TaskProviderIdentity.parse(nullable)).toEqual(nullable) + }) + + it('preserves unknown fields and never infers GitHub from owner/repo', () => { + const identity = { provider: 'gitlab', owner: 'acme', repo: 'orca', futureField: 'value' } + expect(TaskProviderIdentity.parse(identity)).toEqual(identity) + }) + + it.each([{}, { provider: 'github' }, { provider: 'unknown' }, [], 'github', 1])( + 'rejects invalid identities: %j', + (identity) => { + expect(TaskProviderIdentity.safeParse(identity).success).toBe(false) + } + ) + + it('preserves absent and explicit-null identities in folder contexts on local and SSH hosts', () => { + expect(TaskProviderIdentity.parse(undefined)).toBeUndefined() + expect(TaskProviderIdentity.parse(null)).toBeNull() + for (const hostId of ['local', 'ssh:host']) { + const context = { kind: 'task-source', provider: 'github', projectId: 'folder', hostId } + expect(TaskSourceContext.parse(context)).not.toHaveProperty('providerIdentity') + expect(TaskSourceContext.parse({ ...context, providerIdentity: null })).toEqual({ + ...context, + providerIdentity: null + }) + } + }) + + it('validates identities in automation updates without collapsing absent and null patches', () => { + expect(AutomationUpdate.parse({ id: 'automation', updates: {} }).updates).not.toHaveProperty( + 'sourceContext' + ) + expect( + AutomationUpdate.parse({ id: 'automation', updates: { sourceContext: null } }).updates + .sourceContext + ).toBeNull() + expect( + AutomationUpdate.safeParse({ + id: 'automation', + updates: { + sourceContext: { + kind: 'task-source', + provider: 'github', + projectId: 'project', + hostId: 'local', + providerIdentity: { provider: 'github' } + } + } + }).success + ).toBe(false) + }) +}) + +describe('github identity blank fields', () => { + // The normalizer treats a blank owner or repo as no identity, so the schema must agree. + it.each(['', ' ', '\t'])('rejects a blank owner %j', (owner) => { + expect( + TaskProviderIdentity.safeParse({ provider: 'github', owner, repo: 'orca' }).success + ).toBe(false) + }) + + it.each(['', ' '])('rejects a blank repo %j', (repo) => { + expect( + TaskProviderIdentity.safeParse({ provider: 'github', owner: 'stablyai', repo }).success + ).toBe(false) + }) + + it('still accepts a populated identity', () => { + expect( + TaskProviderIdentity.safeParse({ provider: 'github', owner: 'stablyai', repo: 'orca' }) + .success + ).toBe(true) + }) + + it('leaves the parsed value untrimmed, so no wire bytes change', () => { + const parsed = TaskProviderIdentity.safeParse({ + provider: 'github', + owner: ' stablyai ', + repo: 'orca' + }) + expect(parsed.success && parsed.data?.owner).toBe(' stablyai ') + }) +}) diff --git a/src/main/runtime/runtime-client-settings-terminal-copy-projection.test.ts b/src/main/runtime/runtime-client-settings-terminal-copy-projection.test.ts new file mode 100644 index 00000000000..8a6fad5065c --- /dev/null +++ b/src/main/runtime/runtime-client-settings-terminal-copy-projection.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, it } from 'vitest' +import { RuntimeClientSettingsController } from './runtime-client-settings' +import { createGlobalSettingsFixture } from '../../shared/global-settings-test-fixture' +import type { GlobalSettings } from '../../shared/global-settings-types' + +// Why: `settings.get` is an explicit allowlist, not the whole settings object. +// Mobile's terminal Copy reads terminalCopyTrimsGutter from it (#19770), and a +// field missing here is indistinguishable on the client from an older host — +// so the opt-out would silently never arrive. +function projectionOf(settings: Partial) { + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: get() reads nothing but store.getSettings(); every other RuntimeStore member is unreachable from that path. + return new RuntimeClientSettingsController({ getSettings: () => settings } as never).get() +} + +function hostSettings(overrides: Partial): Partial { + return { ...createGlobalSettingsFixture({ workspaceDir: '/w' }), ...overrides } +} + +describe('RuntimeClientSettingsController terminal copy projection', () => { + it('publishes the gutter-trim opt-out to paired clients', () => { + expect( + projectionOf(hostSettings({ terminalCopyTrimsGutter: false })).terminalCopyTrimsGutter + ).toBe(false) + }) + + it('publishes the gutter-trim opt-in to paired clients', () => { + expect( + projectionOf(hostSettings({ terminalCopyTrimsGutter: true })).terminalCopyTrimsGutter + ).toBe(true) + }) + + it('reports on when the host has no persisted preference', () => { + const settings = hostSettings({}) + delete settings.terminalCopyTrimsGutter + expect(projectionOf(settings).terminalCopyTrimsGutter).toBe(true) + }) +}) diff --git a/src/main/runtime/runtime-client-settings.ts b/src/main/runtime/runtime-client-settings.ts index 900900700f3..4e36ee22024 100644 --- a/src/main/runtime/runtime-client-settings.ts +++ b/src/main/runtime/runtime-client-settings.ts @@ -27,6 +27,7 @@ export type RuntimeClientSettings = Pick< | 'agentDefaultArgs' | 'agentDefaultEnv' | 'agentStatusHooksEnabled' + | 'terminalCopyTrimsGutter' | 'defaultTaskSource' | 'defaultTaskViewPreset' | 'visibleTaskProviders' @@ -97,6 +98,9 @@ export class RuntimeClientSettingsController { agentDefaultArgs: settings.agentDefaultArgs ?? {}, agentDefaultEnv: settings.agentDefaultEnv ?? {}, agentStatusHooksEnabled: settings.agentStatusHooksEnabled !== false, + // Why projected: mobile's terminal Copy honours this, and a host predating + // the setting sends no key, which the client reads as on (#19770). + terminalCopyTrimsGutter: settings.terminalCopyTrimsGutter !== false, defaultTaskSource: settings.defaultTaskSource ?? 'github', defaultTaskViewPreset: settings.defaultTaskViewPreset ?? 'issues', visibleTaskProviders: settings.visibleTaskProviders ?? [...TASK_PROVIDERS], diff --git a/src/main/runtime/runtime-file-command-surface.ts b/src/main/runtime/runtime-file-command-surface.ts index cd891301175..554eed008a3 100644 --- a/src/main/runtime/runtime-file-command-surface.ts +++ b/src/main/runtime/runtime-file-command-surface.ts @@ -30,6 +30,7 @@ type RuntimeFileCommandName = | 'searchRuntimeFiles' | 'listRuntimeFiles' | 'listRuntimeMarkdownDocuments' + | 'pathsExistRuntimeFiles' | 'statRuntimeFile' export type RuntimeFileCommandSurface = Pick @@ -68,6 +69,7 @@ export function installRuntimeFileCommandSurface( searchRuntimeFiles: commands.searchRuntimeFiles.bind(commands), listRuntimeFiles: commands.listRuntimeFiles.bind(commands), listRuntimeMarkdownDocuments: commands.listRuntimeMarkdownDocuments.bind(commands), + pathsExistRuntimeFiles: commands.pathsExistRuntimeFiles.bind(commands), statRuntimeFile: commands.statRuntimeFile.bind(commands) } satisfies RuntimeFileCommandSurface) } diff --git a/src/main/runtime/runtime-file-commands-search-runtime-files.ts b/src/main/runtime/runtime-file-commands-search-runtime-files.ts index 5cd1f6246a8..fd79941c1ae 100644 --- a/src/main/runtime/runtime-file-commands-search-runtime-files.ts +++ b/src/main/runtime/runtime-file-commands-search-runtime-files.ts @@ -13,6 +13,11 @@ import { listMarkdownDocuments, markdownDocumentsFromRelativePaths } from '../ipc/markdown-documents' +import { + validatePathExistenceBatch, + type PathExistenceResult +} from '../../shared/path-existence-batch' +import { readRuntimeFilePathExistence } from './runtime-file-path-existence' import { stat } from 'node:fs/promises' import { resolveAuthorizedPath } from '../ipc/filesystem-auth' @@ -80,6 +85,15 @@ export class RuntimeFileCommandsWithSearchRuntimeFiles extends RuntimeFileComman return listMarkdownDocuments(target.worktree.path) } + async pathsExistRuntimeFiles( + worktreeSelector: string, + relativePaths: string[] + ): Promise { + validatePathExistenceBatch(relativePaths) + const targets = await this.resolveFileExplorerPaths(worktreeSelector, relativePaths) + return readRuntimeFilePathExistence(targets, () => this.host.requireStore()) + } + async statRuntimeFile( worktreeSelector: string, relativePath: string diff --git a/src/main/runtime/runtime-file-path-existence.test.ts b/src/main/runtime/runtime-file-path-existence.test.ts new file mode 100644 index 00000000000..d74c58bfdae --- /dev/null +++ b/src/main/runtime/runtime-file-path-existence.test.ts @@ -0,0 +1,97 @@ +import { afterEach, expect, it, vi } from 'vitest' +import { mkdtemp, writeFile, rm } from 'node:fs/promises' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { RuntimeFileCommands } from './orca-runtime-files' +import { RpcDispatcher } from './rpc/dispatcher' +import { FILE_METHODS } from './rpc/methods/files' +import { + registerSshFilesystemProvider, + unregisterSshFilesystemProvider +} from '../providers/ssh-filesystem-dispatch' +import { pathsExistOnRelay } from '../../relay/fs-path-existence' +import { statRelayPath } from '../../relay/fs-path-metadata-requests' +let root: string | undefined +const connection = 'batch-fixture-host' +afterEach(async () => { + unregisterSshFilesystemProvider(connection) + if (root) { + await rm(root, { recursive: true, force: true }) + } + root = undefined +}) +async function setup(legacy = false) { + root = await mkdtemp(join(tmpdir(), 'orca-runtime-batch-')) + const names = Array.from({ length: 8 }, (_, i) => `file-${i}.ts`) + await Promise.all(names.map((name) => writeFile(join(root!, name), 'fixture'))) + const provider = { + pathsExist: legacy + ? undefined + : vi.fn((paths: string[]) => pathsExistOnRelay({ filePaths: paths })), + stat: vi.fn((filePath: string) => statRelayPath({ filePath })) + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The registered fixture implements the stat and optional batch operations exercised here. + registerSshFilesystemProvider(connection, provider as never) + const resolveTarget = vi.fn(async () => ({ + worktree: { id: 'folder-1', path: root, kind: 'folder', repoId: 'folder-repo' }, + executionHostId: `ssh:${connection}` + })) + const host = { + getRuntimeId: () => 'runtime-fixture', + requireStore: vi.fn(() => { + throw new Error('Local store should not be read') + }), + resolveRuntimeFileTarget: resolveTarget + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The fixture supplies runtime identity, target resolution and the guarded store accessor used by these reads. + const commands = new RuntimeFileCommands(host as never) + const runtime = { + getRuntimeId: host.getRuntimeId, + pathsExistRuntimeFiles: commands.pathsExistRuntimeFiles.bind(commands), + statRuntimeFile: commands.statRuntimeFile.bind(commands) + } + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Dispatch is limited to the two file methods implemented by this fixture. + const dispatcher = new RpcDispatcher({ runtime: runtime as never, methods: FILE_METHODS }) + const dispatch = (relativePaths: string[]) => + dispatcher.dispatch({ + id: 'batch-1', + authToken: 'fixture', + method: 'files.pathsExist', + params: { worktree: 'id:folder-1', relativePaths } + }) + return { names, provider, resolveTarget, host, dispatch } +} +it('actual RPC dispatch resolves one folder owner and sends one provider batch for eight real files', async () => { + const f = await setup() + expect(await f.dispatch(f.names)).toMatchObject({ + ok: true, + result: f.names.map(() => ({ exists: true })) + }) + expect(f.resolveTarget).toHaveBeenCalledTimes(1) + expect(f.resolveTarget).toHaveBeenCalledWith('id:folder-1') + expect(f.provider.pathsExist).toHaveBeenCalledTimes(1) + expect(f.provider.stat).not.toHaveBeenCalled() + expect(f.host.requireStore).not.toHaveBeenCalled() + expect(await f.dispatch(['../escape'])).toMatchObject({ ok: false }) + expect(f.provider.pathsExist).toHaveBeenCalledTimes(1) +}) +it('legacy provider preserves all answers through scoped scalar stats', async () => { + const f = await setup(true) + expect(await f.dispatch([...f.names, 'missing'])).toMatchObject({ + ok: true, + result: [...f.names.map(() => ({ exists: true })), { exists: false }] + }) + expect(f.provider.stat).toHaveBeenCalledTimes(9) + expect(f.host.requireStore).not.toHaveBeenCalled() +}) +it('unavailable SSH never falls back to matching local files; oversized input never reaches provider', async () => { + const f = await setup() + unregisterSshFilesystemProvider(connection) + expect(await f.dispatch(f.names)).toMatchObject({ + ok: false, + error: { message: expect.stringContaining('Remote connection dropped') } + }) + expect(f.host.requireStore).not.toHaveBeenCalled() + expect(await f.dispatch(Array(129).fill('file-0.ts'))).toMatchObject({ ok: false }) + expect(f.provider.pathsExist).not.toHaveBeenCalled() +}) diff --git a/src/main/runtime/runtime-file-path-existence.ts b/src/main/runtime/runtime-file-path-existence.ts new file mode 100644 index 00000000000..197cf7ac814 --- /dev/null +++ b/src/main/runtime/runtime-file-path-existence.ts @@ -0,0 +1,39 @@ +import { stat } from 'node:fs/promises' +import { capturePathExistence, type PathExistenceResult } from '../../shared/path-existence-batch' +import { resolveAuthorizedPath } from '../ipc/filesystem-auth' +import { isENOENT } from '../ipc/filesystem-path-containment' +import type { RuntimeFileCommandHost } from './runtime-file-command-host' +import { + requireRuntimeFileProvider, + type RuntimeFileExplorerPath +} from './runtime-file-command-target' + +export async function readRuntimeFilePathExistence( + targets: readonly RuntimeFileExplorerPath[], + requireStore: RuntimeFileCommandHost['requireStore'] +): Promise { + if (targets.length === 0) { + return [] + } + const provider = requireRuntimeFileProvider(targets[0]) + if (provider?.pathsExist) { + return provider.pathsExist(targets.map((target) => target.path)) + } + return Promise.all( + targets.map((target) => + capturePathExistence(async () => { + try { + await (provider + ? provider.stat(target.path) + : stat(await resolveAuthorizedPath(target.path, requireStore()))) + return true + } catch (error) { + if (isENOENT(error)) { + return false + } + throw error + } + }) + ) + ) +} diff --git a/src/main/runtime/runtime-store-contract.ts b/src/main/runtime/runtime-store-contract.ts index f3f5d5a8f51..b1471ff8efe 100644 --- a/src/main/runtime/runtime-store-contract.ts +++ b/src/main/runtime/runtime-store-contract.ts @@ -87,6 +87,7 @@ export type RuntimeStore = { terminalWindowsShell?: GlobalSettings['terminalWindowsShell'] floatingTerminalEnabled?: GlobalSettings['floatingTerminalEnabled'] agentStatusHooksEnabled?: GlobalSettings['agentStatusHooksEnabled'] + terminalCopyTrimsGutter?: GlobalSettings['terminalCopyTrimsGutter'] experimentalNativeChat?: GlobalSettings['experimentalNativeChat'] openAgentTabsInChatByDefault?: GlobalSettings['openAgentTabsInChatByDefault'] experimentalStructuredNativeChat?: GlobalSettings['experimentalStructuredNativeChat'] diff --git a/src/main/runtime/structured-agent-session-runtime-exit.test.ts b/src/main/runtime/structured-agent-session-runtime-exit.test.ts index 5c6e43c2bc0..506a45ae821 100644 --- a/src/main/runtime/structured-agent-session-runtime-exit.test.ts +++ b/src/main/runtime/structured-agent-session-runtime-exit.test.ts @@ -201,6 +201,30 @@ describe('structured session runtime provider-exit wiring', () => { await new Promise((resolve) => setImmediate(resolve)) expect(connections).toHaveLength(1) + expect(host.deps.store.getRecord(SESSION)?.lease).toMatchObject({ + claimStatus: 'released', + ownerProcess: null, + handoffStage: null + }) + + const restarted = await ensureStructuredAgentSessionHost({ + stateDirectory: root, + hostId: 'local', + claimKeyId: 'key-1', + resolveWorkspacePath: async () => root!, + resolveClaudeAuthPolicy: () => ({ stripAuthEnv: true }), + resolveCodexCommand: () => 'codex', + resolveEnvironment: async () => ({ PATH: process.env.PATH }), + openCodexConnection: openConnection, + readProcessStartTime: async () => 1_700_000_000_000 + }) + await restarted.restoreReadableSessions() + const history = restarted.history({ sessionId: SESSION, direction: 'tail' }) + expect(history.ok && history.page.items.some((item) => item.body.kind === 'status')).toBe(false) + expect(restarted.deps.store.getRecord(SESSION)?.providerHandleChain.at(-1)?.handle).toEqual({ + provider: 'codex', + threadId: 'thread-runtime-close' + }) }) it('waits for an in-flight recovery before tearing down the runtime', async () => { @@ -286,4 +310,97 @@ describe('structured session runtime provider-exit wiring', () => { await stopping expect(stopped).toBe(true) }) + it('drains a final exit callback delivered by the adapter backstop and keeps the retry real', async () => { + // The first stop refuses, so host eviction cannot prove the child gone and aborts with the + // session still indexed. What finally stops it is `closeAll`, which delivers the exit + // callback AFTER host teardown has already run. + root = await mkdtemp(join(tmpdir(), 'orca-runtime-backstop-exit-')) + operations = 0 + const connections: { + connection: CodexAppServerConnection + handlers: CodexAppServerConnectionHandlers + }[] = [] + let closeAttempts = 0 + const openConnection: typeof openCodexAppServerConnection = async (_launch, handlers = {}) => { + const connection: CodexAppServerConnection = { + pid: 4321, + closed: false, + request: async (method, params) => { + if (method === 'thread/start') { + return { thread: { id: 'thread-runtime-backstop' } } + } + if (method === 'thread/resume') { + return { thread: { id: (params as { threadId: string }).threadId } } + } + if (method === 'turn/start') { + return { turn: { id: 'turn-backstop' } } + } + if (method === 'model/list') { + return { + data: [ + { + model: 'gpt-test', + displayName: 'GPT Test', + hidden: false, + supportedReasoningEfforts: [], + defaultReasoningEffort: null, + isDefault: true + } + ], + nextCursor: null + } + } + return {} + }, + notify: () => {}, + respond: () => {}, + respondWithError: () => {}, + close: async () => { + closeAttempts += 1 + if (closeAttempts === 1) { + return false + } + handlers.onExit?.(new Error('adapter backstop close')) + return true + } + } + connections.push({ connection, handlers }) + return connection + } + const host = await ensureStructuredAgentSessionHost({ + stateDirectory: root, + hostId: 'local', + claimKeyId: 'key-1', + resolveWorkspacePath: async () => root!, + resolveClaudeAuthPolicy: () => ({ stripAuthEnv: true }), + resolveCodexCommand: () => 'codex', + resolveEnvironment: async () => ({ PATH: process.env.PATH }), + openCodexConnection: openConnection, + readProcessStartTime: async () => 1_700_000_000_000 + }) + const attachParams = hostTestAttachParams(null, { providerHandle: undefined }) + attachParams.envelope.clientOperationId = operationId() + expect(await host.attach({ callerKey: 'runtime-test' }, attachParams)).toMatchObject({ + ok: true + }) + await host.hold(SESSION, 'desktop-chat:backstop') + + await expect(stopStructuredAgentSessionRuntime()).rejects.toThrow() + await new Promise((resolve) => setImmediate(resolve)) + + // The backstop, not host eviction, is what stopped the child. + expect(closeAttempts).toBeGreaterThanOrEqual(2) + // The callback it delivered neither reacquired nor wrote a technical row. + expect(connections).toHaveLength(1) + const history = host.history({ sessionId: SESSION, direction: 'tail' }) + expect(history.ok && history.page.items.some((item) => item.body.kind === 'status')).toBe(false) + + // The aborted eviction left the session reachable, so the next teardown is a real retry. + await stopStructuredAgentSessionRuntime() + expect(host.deps.store.getRecord(SESSION)?.lease).toMatchObject({ + claimStatus: 'released', + ownerProcess: null, + handoffStage: null + }) + }) }) diff --git a/src/main/runtime/structured-agent-session-runtime.ts b/src/main/runtime/structured-agent-session-runtime.ts index f7798b11db8..fbc13b58fca 100644 --- a/src/main/runtime/structured-agent-session-runtime.ts +++ b/src/main/runtime/structured-agent-session-runtime.ts @@ -171,13 +171,41 @@ async function tearDownRuntime(installed: InstalledRuntime): Promise { // Drain an in-flight recovery before stopping children; recovery may still // be writing lifecycle rows or acquiring a replacement child. await installed.waitForRecovery() + const failures: unknown[] = [] + // Host teardown runs FIRST, which inverts the older order. It is what stops this host's + // provider children now: it evicts each owned session through the adapter, and that eviction + // only releases the lease once `disposeSession` PROVES the child gone. Closing the adapter + // first would hand every one of those steps a vacuous receipt from an already-closed router, + // and would race the attach drain the host runs in the same teardown. + // + // Tail rows are protected by eviction's own per-session ordering — stop the child, drain what + // it already published, settle, then unbind the sink — not by which of the two teardowns runs + // first. `closeAll` is only a backstop for children eviction never took: an acquisition that + // failed before the host indexed it, or a session whose eviction was refused and left indexed. + // A row a child delivers during that backstop close is not captured, and was not captured + // under the old order either. The drain below keeps a late callback from outliving the runtime. try { - await installed.adapter.closeAll() - } finally { - // closeAll can itself deliver a final exit callback; observe that callback - // before flushing and releasing the host's journal resources. - await installed.waitForRecovery() await installed.host.flushAllStreamedEvents() + } catch (error) { + failures.push(error) + } + try { + // Backstop for children eviction never took: unindexed acquisitions and refused evictions. + await installed.adapter.closeAll() + } catch (error) { + failures.push(error) + } + // A backstop close can still deliver a final exit callback. + try { + await installed.waitForRecovery() + } catch (error) { + failures.push(error) + } + if (failures.length === 1) { + throw failures[0] + } + if (failures.length > 1) { + throw new AggregateError(failures, 'structured agent-session runtime teardown failed') } } diff --git a/src/main/skills/discovery-filter-sharing.test.ts b/src/main/skills/discovery-filter-sharing.test.ts new file mode 100644 index 00000000000..14f755d0100 --- /dev/null +++ b/src/main/skills/discovery-filter-sharing.test.ts @@ -0,0 +1,143 @@ +import { mkdir, mkdtemp, rm, symlink, writeFile } from 'node:fs/promises' +import type * as FsPromises from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { afterEach, expect, it, vi } from 'vitest' + +const observed = vi.hoisted(() => ({ opens: 0 })) +vi.mock('node:fs/promises', async (importOriginal) => { + const actual = await importOriginal() + return { + ...actual, + open: (...args: Parameters) => { + observed.opens += 1 + return actual.open(...args) + } + } +}) +import * as repair from './discovery' +import { SkillScanCoalescer, SkillScanShedError } from './skill-scan-coalescer' + +afterEach(() => { + repair.clearSkillRootScanCache() + vi.restoreAllMocks() + vi.unstubAllEnvs() +}) + +async function fixture(task: (root: string) => Promise): Promise { + const root = await mkdtemp(join(tmpdir(), 'orca-skill-name-repair-')) + vi.stubEnv('HERMES_HOME', '') + vi.stubEnv('LOCALAPPDATA', '') + try { + for (let index = 0; index < 48; index += 1) { + const dir = join(root, '.agents', 'skills', `skill-${index}`) + await mkdir(dir, { recursive: true }) + await writeFile(join(dir, 'SKILL.md'), `---\nname: skill-${index}\n---\n`) + } + await task(root) + } finally { + await rm(root, { recursive: true, force: true }) + } +} + +it('shares one root read across six concurrent name filters', async () => { + await fixture(async (root) => { + repair.clearSkillRootScanCache() + observed.opens = 0 + const checks = await Promise.all( + Array.from({ length: 6 }, (_, index) => + repair.discoverSkills({ + homeDir: root, + repos: [], + includeCwd: false, + names: [`skill-${index}`], + sourceKinds: ['home'] + }) + ) + ) + expect(checks.map((result) => result.skills.map((skill) => skill.name))).toEqual( + Array.from({ length: 6 }, (_, index) => [`skill-${index}`]) + ) + expect(observed.opens).toBe(48) + }) +}) + +it('reuses the raw snapshot for a new name and invalidates it on mutation', async () => { + await fixture(async (root) => { + const args = { homeDir: root, repos: [], includeCwd: false, sourceKinds: ['home' as const] } + observed.opens = 0 + await repair.discoverSkills({ ...args, names: ['skill-0'] }) + const next = await repair.discoverSkills({ ...args, names: ['skill-47'] }) + expect(next.skills.map((skill) => skill.name)).toEqual(['skill-47']) + expect(observed.opens).toBe(48) + await writeFile( + join(root, '.agents', 'skills', 'skill-47', 'SKILL.md'), + '---\nname: renamed\n---\n' + ) + repair.clearSkillRootScanCache() + const updated = await repair.discoverSkills({ ...args, names: ['renamed'] }) + expect(updated.skills.map((skill) => skill.name)).toEqual(['renamed']) + expect(observed.opens).toBe(96) + }) +}) + +it('retains a newly requested name when its previously observed root becomes unavailable', async () => { + await fixture(async (root) => { + const args = { homeDir: root, repos: [], includeCwd: false, sourceKinds: ['home' as const] } + await repair.discoverSkills({ ...args, names: ['skill-0'] }) + const original = SkillScanCoalescer.prototype.run + vi.spyOn(SkillScanCoalescer.prototype, 'run').mockImplementation( + function (this: SkillScanCoalescer, key, options, task) { + if ( + key === `home\0${join(root, '.agents', 'skills')}` || + key.startsWith(`home\0${join(root, '.agents', 'skills')}\0`) + ) { + return Promise.reject(new SkillScanShedError()) + } + return original.call(this, key, options, task) + } + ) + const next = await repair.discoverSkills({ ...args, names: ['skill-47'] }) + expect(next.skills.map((skill) => skill.name)).toEqual(['skill-47']) + expect(next.sources.find((source) => source.id === 'home-agents')?.skippedReason).toBe( + 'unavailable' + ) + }) +}) + +it('keeps simultaneous forced refreshes independent', async () => { + await fixture(async (root) => { + const args = { homeDir: root, repos: [], includeCwd: false, sourceKinds: ['home' as const] } + await repair.discoverSkills({ ...args, names: ['skill-0'] }) + observed.opens = 0 + const results = await Promise.all( + [0, 1].map((index) => + repair.discoverSkills({ ...args, names: [`skill-${index}`], refresh: true }) + ) + ) + expect(results.map((result) => result.skills[0]?.name)).toEqual(['skill-0', 'skill-1']) + expect(observed.opens).toBe(96) + }) +}) + +it('filters aliases before deduplication so excluded bundled roots cannot own home results', async () => { + await fixture(async (root) => { + const bundled = join(root, '.codex', 'skills', '.system', 'bundle') + const alias = join(root, '.agents', 'skills', 'bundle-alias') + await mkdir(bundled, { recursive: true }) + await writeFile(join(bundled, 'SKILL.md'), '---\nname: bundle\n---\n') + await symlink(bundled, alias, 'dir') + const result = await repair.discoverSkills({ + homeDir: root, + repos: [], + includeCwd: false, + names: ['bundle'], + sourceKinds: ['home'] + }) + expect(result.skills).toHaveLength(1) + expect(result.skills[0]).toMatchObject({ + sourceKind: 'home', + rootPath: join(root, '.agents', 'skills') + }) + }) +}) diff --git a/src/main/skills/discovery-source-filter-order.test.ts b/src/main/skills/discovery-source-filter-order.test.ts new file mode 100644 index 00000000000..991fa457853 --- /dev/null +++ b/src/main/skills/discovery-source-filter-order.test.ts @@ -0,0 +1,45 @@ +import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { describe, expect, it, vi } from 'vitest' +import type * as SkillMetadata from '../../shared/skill-metadata' + +const summarizeSkillMarkdown = vi.hoisted(() => vi.fn()) + +vi.mock('../../shared/skill-metadata', async (importOriginal) => { + const original = await importOriginal() + return { + ...original, + summarizeSkillMarkdown: (markdown: string) => { + summarizeSkillMarkdown(markdown) + return original.summarizeSkillMarkdown(markdown) + } + } +}) + +import { discoverSkills } from './discovery' + +describe('native skill source filtering', () => { + it('serves home and bundled filters from one raw root observation', async () => { + const root = await mkdtemp(join(tmpdir(), 'orca-skill-source-filter-')) + const homeSkill = join(root, '.codex', 'skills', 'home-skill') + const bundledSkill = join(root, '.codex', 'skills', '.system', 'bundled-skill') + await mkdir(homeSkill, { recursive: true }) + await mkdir(bundledSkill, { recursive: true }) + await writeFile(join(homeSkill, 'SKILL.md'), '# Home Skill\n') + await writeFile(join(bundledSkill, 'SKILL.md'), '# Bundled Skill\n') + + try { + const result = await discoverSkills({ homeDir: root, repos: [], sourceKinds: ['home'] }) + + expect(result.skills.map((skill) => skill.name)).toEqual(['Home Skill']) + expect(summarizeSkillMarkdown).toHaveBeenCalledTimes(2) + expect(summarizeSkillMarkdown).toHaveBeenCalledWith('# Home Skill\n') + const bundled = await discoverSkills({ homeDir: root, repos: [], sourceKinds: ['bundled'] }) + expect(bundled.skills.map((skill) => skill.name)).toEqual(['Bundled Skill']) + expect(summarizeSkillMarkdown).toHaveBeenCalledTimes(2) + } finally { + await rm(root, { recursive: true, force: true }) + } + }) +}) diff --git a/src/main/skills/discovery.test.ts b/src/main/skills/discovery.test.ts index 740c4af7cd0..7c6212a463b 100644 --- a/src/main/skills/discovery.test.ts +++ b/src/main/skills/discovery.test.ts @@ -212,6 +212,46 @@ describe('skill discovery', () => { ]) }) + it('filters discovery by requested directory name and source kind', async () => { + const root = await mkdtemp(join(tmpdir(), 'orca-skills-')) + const home = join(root, 'home') + const repo = join(root, 'repo') + const homeSkill = join(home, '.agents', 'skills', 'orchestration') + const repoSkill = join(repo, '.agents', 'skills', 'orchestration') + const unrelatedSkill = join(home, '.agents', 'skills', 'computer-use') + await mkdir(homeSkill, { recursive: true }) + await mkdir(repoSkill, { recursive: true }) + await mkdir(unrelatedSkill, { recursive: true }) + await writeFile(join(homeSkill, 'SKILL.md'), '---\nname: Agent Orchestration\n---\n') + await writeFile(join(repoSkill, 'SKILL.md'), '# orchestration') + await writeFile(join(unrelatedSkill, 'SKILL.md'), '# computer-use') + + const result = await discoverSkills({ + homeDir: home, + cwd: repo, + repos: [], + names: ['orchestration'], + sourceKinds: ['home'] + }) + + expect(result.skills).toMatchObject([ + { name: 'Agent Orchestration', sourceKind: 'home', directoryPath: homeSkill } + ]) + expect(result.sources.every((source) => source.sourceKind === 'home')).toBe(true) + + const unfiltered = await discoverSkills({ + homeDir: home, + cwd: repo, + repos: [], + sourceKinds: [] + }) + expect(unfiltered.skills.map((skill) => skill.name).sort()).toEqual([ + 'Agent Orchestration', + 'computer-use', + 'orchestration' + ]) + }) + it('discovers the enabled Claude plugin version applicable to the project cwd', async () => { const root = await mkdtemp(join(tmpdir(), 'orca-skills-')) const home = join(root, 'home') diff --git a/src/main/skills/discovery.ts b/src/main/skills/discovery.ts index 385ae99ca33..075261dce5d 100644 --- a/src/main/skills/discovery.ts +++ b/src/main/skills/discovery.ts @@ -6,7 +6,8 @@ import type { Repo } from '../../shared/repo-types' import type { DiscoveredSkill, SkillDiscoveryResult, - SkillDiscoverySource + SkillDiscoverySource, + SkillSourceKind } from '../../shared/skills' import { buildSkillDiscoverySources, @@ -17,6 +18,7 @@ import { stablePathId, type SkillScanRoot } from './skill-discovery-sources' +import { rootMayContainSourceKind } from './skill-discovery-source-filter' import { discoverClaudePluginSkillSources } from './claude-plugin-skill-sources' import { findSkillFiles } from './skill-root-file-walk' import { runSkillCandidateTasks } from './skill-candidate-concurrency' @@ -264,6 +266,8 @@ export async function discoverSkills(args: { includeCwd?: boolean providerRootOverrides?: SkillProviderRootOverrides refresh?: boolean + names?: string[] + sourceKinds?: SkillSourceKind[] }): Promise { const startedAt = Date.now() const homeDir = args.homeDir ?? homedir() @@ -272,10 +276,12 @@ export async function discoverSkills(args: { ...buildSkillDiscoverySources({ ...args, homeDir }), // Why: plugin discovery is native-chat data keyed to an explicit workspace. // Untargeted scans (Settings) keep their pre-picker inventory and cost. - ...(args.cwd && args.includeCwd !== false + ...(args.cwd && + args.includeCwd !== false && + (!args.sourceKinds?.length || args.sourceKinds.includes('plugin')) ? await discoverClaudePluginSkillSources({ homeDir, cwd: args.cwd }) : []) - ] + ].filter((root) => rootMayContainSourceKind(root, args.sourceKinds)) const scans = await Promise.all(roots.map((root) => scanRootShared(root, refresh))) const sources: SkillDiscoverySource[] = roots.map((root, index) => ({ ...root, @@ -287,9 +293,21 @@ export async function discoverSkills(args: { ? undefined : 'missing' })) + const normalizedNames = args.names?.map((name) => name.trim().toLowerCase()).filter(Boolean) + const expectedNames = normalizedNames?.length ? new Set(normalizedNames) : undefined const seen = new Map() for (const { value } of scans) { for (const skill of value.skills) { + if (args.sourceKinds?.length && !args.sourceKinds.includes(skill.sourceKind)) { + continue + } + if ( + expectedNames && + !expectedNames.has(skill.name.trim().toLowerCase()) && + !expectedNames.has(basename(skill.directoryPath).trim().toLowerCase()) + ) { + continue + } mergeScannedSkill(seen, skill) } } diff --git a/src/main/skills/skill-delete/roots.test.ts b/src/main/skills/skill-delete/roots.test.ts new file mode 100644 index 00000000000..572c99343b3 --- /dev/null +++ b/src/main/skills/skill-delete/roots.test.ts @@ -0,0 +1,30 @@ +import { describe, expect, it, vi } from 'vitest' + +vi.mock('../claude-plugin-skill-sources-wsl', () => ({ + discoverClaudePluginSkillSourcesInWsl: vi.fn().mockResolvedValue([]) +})) +import { discoverClaudePluginSkillSourcesInWsl } from '../claude-plugin-skill-sources-wsl' +import { buildSkillDeleteRootSet } from './roots' + +describe('WSL skill deletion root ownership', () => { + it('uses the guest home for an omitted cwd, preserving the prior resolved target', async () => { + const target = { + kind: 'wsl' as const, + distro: 'Ubuntu', + homeDir: '/home/alice', + cwd: undefined + } + const omitted = await buildSkillDeleteRootSet({ target, repos: [] }) + const explicit = await buildSkillDeleteRootSet({ + target: { ...target, cwd: target.homeDir }, + repos: [] + }) + expect(omitted.roots).toEqual(explicit.roots) + expect(omitted.roots.every((root) => root.path.startsWith('/home/alice/'))).toBe(true) + expect(discoverClaudePluginSkillSourcesInWsl).toHaveBeenCalledWith({ + distro: 'Ubuntu', + homeDir: '/home/alice', + cwd: '/home/alice' + }) + }) +}) diff --git a/src/main/skills/skill-delete/roots.ts b/src/main/skills/skill-delete/roots.ts index 1958ed91942..86d2b80bd17 100644 --- a/src/main/skills/skill-delete/roots.ts +++ b/src/main/skills/skill-delete/roots.ts @@ -33,7 +33,8 @@ export async function buildSkillDeleteRootSet(input: { homeDir?: string }): Promise { if (input.target.kind === 'wsl') { - const { distro, homeDir, cwd } = input.target + const { distro, homeDir } = input.target + const cwd = input.target.cwd ?? homeDir return { roots: [ ...buildSkillDiscoverySources({ diff --git a/src/main/skills/skill-discovery-source-filter.test.ts b/src/main/skills/skill-discovery-source-filter.test.ts new file mode 100644 index 00000000000..29d6ac6ca7e --- /dev/null +++ b/src/main/skills/skill-discovery-source-filter.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, it } from 'vitest' +import type { SkillScanRoot } from './skill-discovery-sources' +import { rootMayContainSourceKind } from './skill-discovery-source-filter' + +const homeRoot: SkillScanRoot = { + id: 'home', + owner: 'agents', + path: '/home/alice/.agents/skills', + label: 'Home', + sourceKind: 'home', + providers: ['agent-skills'] +} + +describe('rootMayContainSourceKind', () => { + it('treats an empty list as no filter', () => { + expect(rootMayContainSourceKind(homeRoot, undefined)).toBe(true) + expect(rootMayContainSourceKind(homeRoot, [])).toBe(true) + }) + + it('keeps home roots for bundled classification', () => { + expect(rootMayContainSourceKind(homeRoot, ['bundled'])).toBe(true) + expect(rootMayContainSourceKind(homeRoot, ['plugin'])).toBe(false) + }) +}) diff --git a/src/main/skills/skill-discovery-source-filter.ts b/src/main/skills/skill-discovery-source-filter.ts new file mode 100644 index 00000000000..ce76a518612 --- /dev/null +++ b/src/main/skills/skill-discovery-source-filter.ts @@ -0,0 +1,29 @@ +import type { SkillSourceKind } from '../../shared/skills' +import type { SkillScanRoot } from './skill-discovery-sources' + +export function skillScanSourceKinds( + sourceKinds: readonly SkillSourceKind[] | undefined +): SkillSourceKind[] | undefined { + if (!sourceKinds?.length) { + return undefined + } + const kinds = new Set(sourceKinds) + if (kinds.has('home') || kinds.has('bundled')) { + kinds.add('home') + kinds.add('bundled') + } + return [...kinds].sort() +} + +export function rootMayContainSourceKind( + root: SkillScanRoot, + sourceKinds: readonly SkillSourceKind[] | undefined +): boolean { + if (!sourceKinds?.length) { + return true + } + if (root.sourceKind === 'home') { + return sourceKinds.includes('home') || sourceKinds.includes('bundled') + } + return sourceKinds.includes(root.sourceKind) +} diff --git a/src/main/skills/skill-discovery-target.test.ts b/src/main/skills/skill-discovery-target.test.ts index 899acbb8477..8bea1cbcf50 100644 --- a/src/main/skills/skill-discovery-target.test.ts +++ b/src/main/skills/skill-discovery-target.test.ts @@ -18,9 +18,9 @@ vi.mock('./discovery', () => ({ })) vi.mock('./skill-discovery-wsl', () => ({ - discoverSkillsInWsl: vi.fn(async (args: unknown) => { + discoverSkillObservationInWsl: vi.fn(async (args: unknown) => { wslScans.push(args) - return emptyResult() + return { rows: [], sources: [], scannedAt: 1 } }) })) @@ -135,6 +135,22 @@ describe('discoverSkillsOnTarget', () => { expect(wslScans).toHaveLength(3) }) + it('distinguishes an absent WSL cwd from the literal undefined path', async () => { + await discoverSkillsOnTarget( + { kind: 'wsl', distro: 'Ubuntu', homeDir: '/home/dev', cwd: undefined }, + [] + ) + await discoverSkillsOnTarget( + { kind: 'wsl', distro: 'Ubuntu', homeDir: '/home/dev', cwd: 'undefined' }, + [] + ) + + expect(wslScans).toEqual([ + { distro: 'Ubuntu', homeDir: '/home/dev' }, + { distro: 'Ubuntu', homeDir: '/home/dev', cwd: 'undefined' } + ]) + }) + it('re-reads a WSL target when the caller refreshes', async () => { const target = { kind: 'wsl', diff --git a/src/main/skills/skill-discovery-target.ts b/src/main/skills/skill-discovery-target.ts index ea1ab8c410a..55c83cd94e5 100644 --- a/src/main/skills/skill-discovery-target.ts +++ b/src/main/skills/skill-discovery-target.ts @@ -1,10 +1,15 @@ +import { + projectWslSkillDiscovery, + type WslSkillDiscoveryObservation +} from './skill-discovery-wsl-observation' import type { Repo } from '../../shared/repo-types' import type { SkillDiscoveryResult, SkillDiscoveryTarget } from '../../shared/skills' import { getDefaultWslDistro, getWslHome, parseWslPath, toLinuxPath } from '../wsl' import { clearSkillRootScanCache, discoverSkills } from './discovery' -import { discoverSkillsInWsl } from './skill-discovery-wsl' +import { discoverSkillObservationInWsl } from './skill-discovery-wsl' import type { SkillProviderRootOverrides } from './skill-provider-destinations' import { stablePathId } from './skill-discovery-sources' +import { skillScanSourceKinds } from './skill-discovery-source-filter' import { getRepoExecutionHostId } from '../../shared/execution-host' import { isSkillRootUnavailableError, SkillScanCoalescer } from './skill-scan-coalescer' @@ -14,7 +19,10 @@ import { isSkillRootUnavailableError, SkillScanCoalescer } from './skill-scan-co const WSL_RESULT_TTL_MS = 10_000 const MAX_CACHED_SKILL_TARGETS = 32 -const targetScans = new SkillScanCoalescer(MAX_CACHED_SKILL_TARGETS) +type TargetScanObservation = + | { kind: 'native'; result: SkillDiscoveryResult } + | { kind: 'wsl'; observation: WslSkillDiscoveryObservation } +const targetScans = new SkillScanCoalescer(MAX_CACHED_SKILL_TARGETS) /** Drop every shared scan; used when a skill update run has rewritten disk. */ export function clearSkillDiscoveryCaches(): void { @@ -23,8 +31,20 @@ export function clearSkillDiscoveryCaches(): void { } export type ResolvedSkillDiscoveryTarget = - | { kind: 'native-host'; cwd: string | undefined } - | { kind: 'wsl'; distro: string; homeDir: string; cwd: string } + | { + kind: 'native-host' + cwd: string | undefined + names?: string[] + sourceKinds?: SkillDiscoveryTarget['sourceKinds'] + } + | { + kind: 'wsl' + distro: string + homeDir: string + cwd: string | undefined + names?: string[] + sourceKinds?: SkillDiscoveryTarget['sourceKinds'] + } export function resolveSkillDiscoveryTarget( target: SkillDiscoveryTarget | undefined @@ -49,7 +69,12 @@ export function resolveSkillDiscoveryTarget( throw new Error('No WSL distribution is available for skill discovery.') } if (!wslDistro) { - return { kind: 'native-host', cwd: target?.cwd?.trim() || undefined } + return { + kind: 'native-host', + cwd: target?.cwd?.trim() || undefined, + ...(target?.names ? { names: target.names } : {}), + ...(target?.sourceKinds ? { sourceKinds: target.sourceKinds } : {}) + } } if (process.platform !== 'win32') { throw new Error('WSL skill discovery is only available on Windows.') @@ -67,8 +92,15 @@ export function resolveSkillDiscoveryTarget( ) } const linuxHomeDir = toLinuxPath(homeDir) - const cwd = parsedCwd?.linuxPath ?? (requestedCwd ? toLinuxPath(requestedCwd) : linuxHomeDir) - return { kind: 'wsl', distro: wslDistro, homeDir: linuxHomeDir, cwd } + const cwd = parsedCwd?.linuxPath ?? (requestedCwd ? toLinuxPath(requestedCwd) : undefined) + return { + kind: 'wsl', + distro: wslDistro, + homeDir: linuxHomeDir, + cwd, + ...(target?.names ? { names: target.names } : {}), + ...(target?.sourceKinds ? { sourceKinds: target.sourceKinds } : {}) + } } // Why: repos widen the native root set, so two targets that differ only by the @@ -93,17 +125,28 @@ function scanKey( repos: readonly Repo[], providerRootOverrides: SkillProviderRootOverrides | undefined ): string { - const providerRoots = stablePathId( - Object.entries(providerRootOverrides ?? {}) - .sort(([left], [right]) => left.localeCompare(right)) - .map(([provider, root]) => `${provider}\0${root}`) - .join('\0') + const providerRoots = Object.entries(providerRootOverrides ?? {}).sort(([left], [right]) => + left.localeCompare(right) ) - const targetKey = - target.kind === 'wsl' - ? `wsl\0${target.distro}\0${target.homeDir}\0${target.cwd}` - : `native\0${target.cwd ?? ''}\0${target.cwd ? '' : repoDigest(repos)}` - return `${targetKey}\0${providerRoots}` + const names = target.names?.slice().sort() ?? null + const sourceKinds = target.sourceKinds?.slice().sort() ?? null + return target.kind === 'wsl' + ? JSON.stringify([ + 'wsl', + target.distro, + target.homeDir, + target.cwd ?? null, + providerRoots, + skillScanSourceKinds(target.sourceKinds) ?? null + ]) + : JSON.stringify([ + 'native', + target.cwd ?? null, + target.cwd ? null : repoDigest(repos), + providerRoots, + names, + sourceKinds + ]) } export async function discoverSkillsOnTarget( @@ -116,30 +159,41 @@ export async function discoverSkillsOnTarget( const outcome = await targetScans.run( scanKey(target, repos, options.providerRootOverrides), { ttlMs: target.kind === 'wsl' ? WSL_RESULT_TTL_MS : 0, refresh }, - async () => { + async (): Promise => { if (target.kind === 'wsl') { - return discoverSkillsInWsl({ - distro: target.distro, - homeDir: target.homeDir, - cwd: target.cwd, - providerRootOverrides: options.providerRootOverrides - }) + return { + kind: 'wsl', + observation: await discoverSkillObservationInWsl({ + distro: target.distro, + homeDir: target.homeDir, + ...(target.cwd ? { cwd: target.cwd } : {}), + sourceKinds: skillScanSourceKinds(target.sourceKinds), + providerRootOverrides: options.providerRootOverrides + }) + } } - return target.cwd + const result = await (target.cwd ? discoverSkills({ repos: [], cwd: target.cwd, refresh, + ...(target.names ? { names: target.names } : {}), + ...(target.sourceKinds ? { sourceKinds: target.sourceKinds } : {}), providerRootOverrides: options.providerRootOverrides }) : discoverSkills({ repos: [...repos], refresh, + ...(target.names ? { names: target.names } : {}), + ...(target.sourceKinds ? { sourceKinds: target.sourceKinds } : {}), providerRootOverrides: options.providerRootOverrides - }) + })) + return { kind: 'native', result } } ) - return outcome.value + return outcome.value.kind === 'wsl' + ? projectWslSkillDiscovery(outcome.value.observation, target.sourceKinds, target.names) + : outcome.value.result } catch (error) { if (!isSkillRootUnavailableError(error)) { throw error diff --git a/src/main/skills/skill-discovery-wsl-alias-sharing.test.ts b/src/main/skills/skill-discovery-wsl-alias-sharing.test.ts new file mode 100644 index 00000000000..79a7b4e9b43 --- /dev/null +++ b/src/main/skills/skill-discovery-wsl-alias-sharing.test.ts @@ -0,0 +1,145 @@ +import { beforeEach, expect, it, vi } from 'vitest' +const io = vi.hoisted(() => ({ run: vi.fn(), plugins: vi.fn(async () => []) })) +vi.mock('../wsl/wsl-runner', () => ({ runWslProcess: io.run })) +vi.mock('./claude-plugin-skill-sources-wsl', () => ({ + discoverClaudePluginSkillSourcesInWsl: io.plugins +})) +vi.mock('./discovery', () => ({ clearSkillRootScanCache: vi.fn(), discoverSkills: vi.fn() })) +import { clearSkillDiscoveryCaches, discoverSkillsOnTarget } from './skill-discovery-target' +import { + readWslSkillDiscoveryObservation, + projectWslSkillDiscovery +} from './skill-discovery-wsl-observation' +import type { SkillScanRoot } from './skill-discovery-sources' +const target = { kind: 'wsl' as const, distro: 'Ubuntu', homeDir: '/home/test', cwd: '/repo' } +const record = (...fields: string[]) => `${fields.join('\0')}\0` +const encoded = Buffer.from('---\nname: shared-frontmatter\ndescription: Fixture\n---\n').toString( + 'base64' +) +const common = '/opt/physical/SKILL.md' +const rows = [ + record('S', '0', '/home/test/.codex/skills/.system/bundle/SKILL.md', common, '1', encoded), + record('S', '0', '/home/test/.codex/skills/alias-a/SKILL.md', common, '1', encoded), + record('S', '1', '/home/test/.agents/skills/alias-b/SKILL.md', common, '1', encoded), + ...Array.from({ length: 6 }, (_, i) => + record( + 'S', + '0', + `/home/test/.codex/skills/skill-${i}/SKILL.md`, + `/physical/skill-${i}/SKILL.md`, + '1', + encoded + ) + ) +] +const output = record('R', '0', '1') + record('R', '1', '1') + rows.join('') +beforeEach(() => { + clearSkillDiscoveryCaches() + io.run.mockReset() + io.plugins.mockClear() + io.run.mockResolvedValue({ code: 0, timedOut: false, stdout: output, stderr: '' }) +}) +it('keeps both home aliases when a bundled canonical duplicate appears first', async () => { + const [a, b, bundle] = await Promise.all([ + discoverSkillsOnTarget({ ...target, names: ['alias-a'], sourceKinds: ['home'] }, []), + discoverSkillsOnTarget({ ...target, names: ['alias-b'], sourceKinds: ['home'] }, []), + discoverSkillsOnTarget({ ...target, names: ['bundle'], sourceKinds: ['bundled'] }, []) + ]) + expect(io.run).toHaveBeenCalledTimes(1) + expect(a.skills.map((s) => s.directoryPath)).toEqual(['/home/test/.codex/skills/alias-a']) + expect(b.skills.map((s) => s.directoryPath)).toEqual(['/home/test/.agents/skills/alias-b']) + expect(bundle.skills.map((s) => s.directoryPath)).toEqual([ + '/home/test/.codex/skills/.system/bundle' + ]) + expect(a.skills[0].providers).toEqual(['codex']) + expect(b.skills[0].providers).toEqual(['agent-skills']) + expect(a.skills[0].id).toBe(b.skills[0].id) + expect(a.skills[0].sourceKind).toBe('home') +}) +it('six distinct installed-name checks share one scan and retain all six answers', async () => { + const results = await Promise.all( + Array.from({ length: 6 }, (_, i) => + discoverSkillsOnTarget({ ...target, names: [`skill-${i}`], sourceKinds: ['home'] }, []) + ) + ) + expect(io.run).toHaveBeenCalledTimes(1) + expect(results.map((r) => r.skills[0]?.directoryPath)).toEqual( + Array.from({ length: 6 }, (_, i) => `/home/test/.codex/skills/skill-${i}`) + ) + expect(io.run.mock.calls[0][0].timeoutMs).toBe(10000) + expect(io.run.mock.calls[0][0].script).not.toContain('matches_requested_name') + expect(io.run.mock.calls[0][0].script).not.toContain("'/repo/") + expect(io.plugins).not.toHaveBeenCalled() +}) +it('cache projections do not contaminate later aliases or source metadata', async () => { + const first = await discoverSkillsOnTarget( + { ...target, names: ['alias-a'], sourceKinds: ['home'] }, + [] + ) + first.skills[0].providers.push('claude') + first.skills[0].rootPaths!.push('/poison') + first.sources[0].providers.push('claude') + const later = await discoverSkillsOnTarget( + { ...target, names: ['alias-a'], sourceKinds: ['home'] }, + [] + ) + expect(later.skills[0].providers).toEqual(['codex']) + expect(later.skills[0].rootPaths).toEqual(['/home/test/.codex/skills']) + expect(later.sources[0].providers).not.toContain('claude') + expect(io.run).toHaveBeenCalledTimes(1) +}) +it('refresh, cache clear, distro and broader root requirements are isolated', async () => { + const req = { ...target, names: ['alias-a'], sourceKinds: ['home' as const] } + await discoverSkillsOnTarget(req, []) + await discoverSkillsOnTarget({ ...req, names: ['alias-b'] }, []) + expect(io.run).toHaveBeenCalledTimes(1) + await discoverSkillsOnTarget(req, [], { refresh: true }) + clearSkillDiscoveryCaches() + await discoverSkillsOnTarget(req, []) + await discoverSkillsOnTarget({ ...req, distro: 'Other' }, []) + await discoverSkillsOnTarget({ ...target, names: ['alias-a'] }, []) + expect(io.run).toHaveBeenCalledTimes(5) + expect(io.plugins).toHaveBeenCalledTimes(1) +}) +it('deduplicates and merges only eligible alias roots, independently of row order', () => { + const roots: SkillScanRoot[] = [ + { + id: 'home', + label: 'Home', + path: '/home/test/.codex/skills', + sourceKind: 'home', + providers: ['codex'], + owner: 'codex' + }, + { + id: 'home2', + label: 'Home2', + path: '/home/test/.agents/skills', + sourceKind: 'home', + providers: ['agent-skills'], + owner: null + } + ] + for (const records of [rows, rows.toReversed()]) { + const obs = readWslSkillDiscoveryObservation(records.join(''), roots, 42) + const a = projectWslSkillDiscovery(obs, ['home'], ['alias-a']) + const b = projectWslSkillDiscovery(obs, ['home'], ['alias-b']) + expect(a.skills).toHaveLength(1) + expect(b.skills).toHaveLength(1) + expect(a.skills[0].providers).toEqual(['codex']) + expect(b.skills[0].providers).toEqual(['agent-skills']) + const both = projectWslSkillDiscovery(obs, ['home'], ['alias-a', 'alias-b']) + expect(both.skills).toHaveLength(1) + expect(new Set(both.skills[0].providers)).toEqual(new Set(['codex', 'agent-skills'])) + const all = projectWslSkillDiscovery(obs) + expect(all.skills).toHaveLength(7) + expect(all.scannedAt).toBe(42) + } +}) +it('does not cache failed scans as an empty successful observation', async () => { + io.run.mockResolvedValueOnce({ code: 1, timedOut: false, stdout: '', stderr: 'failure' }) + const req = { ...target, names: ['alias-a'], sourceKinds: ['home' as const] } + await expect(discoverSkillsOnTarget(req, [])).rejects.toThrow('skill-discovery-wsl-scan-failed') + expect((await discoverSkillsOnTarget(req, [])).skills).toHaveLength(1) + expect(io.run).toHaveBeenCalledTimes(2) +}) diff --git a/src/main/skills/skill-discovery-wsl-bash-filter.test.ts b/src/main/skills/skill-discovery-wsl-bash-filter.test.ts new file mode 100644 index 00000000000..95b35acdd50 --- /dev/null +++ b/src/main/skills/skill-discovery-wsl-bash-filter.test.ts @@ -0,0 +1,89 @@ +import { execFileSync } from 'node:child_process' +import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { describe, expect, it } from 'vitest' +import { buildWslSkillDiscoveryCommand, parseWslSkillDiscoveryOutput } from './skill-discovery-wsl' +import type { SkillScanRoot } from './skill-discovery-sources' + +async function writeSkill(root: string, directory: string, markdown: string): Promise { + const skillDirectory = join(root, directory) + await mkdir(skillDirectory, { recursive: true }) + await writeFile(join(skillDirectory, 'SKILL.md'), markdown) +} + +describe('generated WSL skill name filter', () => { + it.skipIf(process.platform !== 'linux')( + 'rejects only known scalar mismatches and passes uncertain names to TypeScript', + async () => { + const root = await mkdtemp(join(tmpdir(), 'orca-wsl-name-filter-')) + const scanRoot: SkillScanRoot = { + id: 'home', + owner: 'agents', + path: root, + label: 'Home', + sourceKind: 'home', + providers: ['agent-skills'] + } + for (const directory of [' orchestration', 'orchestration ', ' orchestration ']) { + await writeSkill(root, directory, '---\nname: unrelated\n---\n') + } + await writeSkill(root, 'scalar-match', '---\nname: orchestration\n---\n') + await writeSkill(root, 'scalar-mismatch', '---\nname: unrelated\n---\n') + await writeSkill(root, 'empty-quoted', '---\nname: ""\n---\n# orchestration\n') + await writeSkill(root, 'one-quote', '---\nname: "\n---\n# orchestration\n') + await writeSkill(root, 'block-name', '---\nname: >-\n orchestration\n---\n') + await writeSkill(root, 'bom-crlf', "\uFEFF---\r\nname: 'orchestration'\r\n---\r\n") + await writeSkill(root, 'unicode-space', '---\nname:\u3000orchestration\n---\n') + await writeSkill(root, 'missing-close', '---\nname: unrelated\n# orchestration\n') + await writeSkill(root, 'duplicate-match', '---\nname: unrelated\nname: orchestration\n---\n') + await writeSkill( + root, + 'duplicate-mismatch', + '---\nname: orchestration\nname: unrelated\n---\n' + ) + await writeSkill( + root, + 'beyond-limit', + `---\ndescription: |\n${' x\n'.repeat(70_000)}name: unrelated\n---\n# orchestration\n` + ) + await writeSkill( + root, + 'multibyte-beyond-limit', + `---\ndescription: ${'한'.repeat(90_000)}\nname: unrelated\n---\n# orchestration\n` + ) + + try { + const command = buildWslSkillDiscoveryCommand([scanRoot], ['orchestration']) + const output = execFileSync('/bin/bash', ['-c', command], { + encoding: 'utf8', + maxBuffer: 4 * 1024 * 1024 + }) + expect(output).not.toContain('scalar-mismatch') + expect(output).not.toContain('duplicate-mismatch') + expect(output).toContain('beyond-limit') + expect(output).toContain('multibyte-beyond-limit') + expect( + parseWslSkillDiscoveryOutput(output, [scanRoot], 42, ['home'], ['orchestration']) + .skills.map((skill) => skill.directoryPath.split('/').at(-1)) + .sort() + ).toEqual([ + ' orchestration', + ' orchestration ', + 'block-name', + 'bom-crlf', + 'duplicate-match', + 'empty-quoted', + 'missing-close', + 'one-quote', + 'orchestration ', + 'scalar-match', + 'unicode-space' + ]) + } finally { + await rm(root, { recursive: true, force: true }) + } + }, + 30_000 + ) +}) diff --git a/src/main/skills/skill-discovery-wsl-observation.ts b/src/main/skills/skill-discovery-wsl-observation.ts new file mode 100644 index 00000000000..92341d93678 --- /dev/null +++ b/src/main/skills/skill-discovery-wsl-observation.ts @@ -0,0 +1,165 @@ +import { posix as pathPosix } from 'node:path' +import { summarizeSkillMarkdown } from '../../shared/skill-metadata' +import type { + DiscoveredSkill, + SkillDiscoveryResult, + SkillDiscoverySource, + SkillSourceKind +} from '../../shared/skills' +import { + sortDiscoveredSkills, + sortSkillDiscoverySources, + sourceKindForSkill, + sourceLabelForSkill, + stablePathId, + type SkillScanRoot +} from './skill-discovery-sources' +import { rootMayContainSourceKind } from './skill-discovery-source-filter' + +export type WslSkillDiscoveryObservation = { + rows: { canonicalSkillFilePath: string; skill: DiscoveredSkill }[] + sources: SkillDiscoverySource[] + scannedAt: number +} + +function readProtocolField(fields: string[], index: number): string { + const value = fields[index] + if (value === undefined) { + throw new Error('WSL skill discovery returned an incomplete response.') + } + return value +} + +export function readWslSkillDiscoveryObservation( + output: string, + roots: readonly SkillScanRoot[], + scannedAt = Date.now() +): WslSkillDiscoveryObservation { + const fields = output.split('\0') + const rootExists = new Map() + const rows: WslSkillDiscoveryObservation['rows'] = [] + let index = 0 + while (index < fields.length && fields[index]) { + const recordKind = fields[index++] + const rootIndex = Number.parseInt(readProtocolField(fields, index++), 10) + const root = roots[rootIndex] + if (!root) { + throw new Error('WSL skill discovery returned an unknown source.') + } + if (recordKind === 'R') { + rootExists.set(rootIndex, readProtocolField(fields, index++) === '1') + continue + } + if (recordKind !== 'S') { + throw new Error('WSL skill discovery returned an invalid response.') + } + + const skillFilePath = readProtocolField(fields, index++) + const canonicalSkillFilePath = readProtocolField(fields, index++) + const updatedAtSeconds = Number.parseInt(readProtocolField(fields, index++), 10) + const markdown = Buffer.from(readProtocolField(fields, index++), 'base64').toString('utf8') + const directoryPath = pathPosix.dirname(skillFilePath) + const summary = summarizeSkillMarkdown(markdown) + const sourceKind = sourceKindForSkill(root, skillFilePath, pathPosix) + const directoryName = pathPosix.basename(directoryPath) + rows.push({ + canonicalSkillFilePath, + skill: { + id: stablePathId(canonicalSkillFilePath), + name: summary.name ?? directoryName, + description: summary.description, + // Copy: `root.providers` is shared across every skill/source from this + // root, so a later in-place merge must not mutate the aliased array. + providers: [...root.providers], + sourceKind, + sourceLabel: sourceLabelForSkill(root, sourceKind), + rootPath: root.path, + rootPaths: [root.path], + directoryPath, + skillFilePath, + installed: true, + updatedAt: Number.isFinite(updatedAtSeconds) ? updatedAtSeconds * 1000 : null + } + }) + } + + const sources: SkillDiscoverySource[] = roots.map((root, rootIndex) => { + const exists = rootExists.get(rootIndex) ?? false + return { + ...root, + providers: [...root.providers], + exists, + skippedReason: exists ? undefined : 'missing' + } + }) + return { + rows, + sources: sortSkillDiscoverySources(sources), + scannedAt + } +} + +export function projectWslSkillDiscovery( + observation: WslSkillDiscoveryObservation, + sourceKinds?: readonly SkillSourceKind[], + names?: readonly string[] +): SkillDiscoveryResult { + const normalizedNames = names?.map((name) => name.trim().toLowerCase()).filter(Boolean) + const expectedNames = normalizedNames?.length ? new Set(normalizedNames) : undefined + const skillsByCanonicalPath = new Map() + for (const { canonicalSkillFilePath, skill } of observation.rows) { + if (sourceKinds?.length && !sourceKinds.includes(skill.sourceKind)) { + continue + } + const directoryName = pathPosix.basename(skill.directoryPath) + if ( + expectedNames && + !expectedNames.has(skill.name.trim().toLowerCase()) && + !expectedNames.has(directoryName.trim().toLowerCase()) + ) { + continue + } + // Filter aliases before deduplication; each name/source may select a different row. + const existing = skillsByCanonicalPath.get(canonicalSkillFilePath) + if (existing) { + const existingRoots = (existing.rootPaths ??= [existing.rootPath]) + for (const rootPath of skill.rootPaths ?? [skill.rootPath]) { + if (!existingRoots.includes(rootPath)) { + existingRoots.push(rootPath) + } + } + for (const provider of skill.providers) { + if (!existing.providers.includes(provider)) { + existing.providers.push(provider) + } + } + continue + } + skillsByCanonicalPath.set(canonicalSkillFilePath, { + ...skill, + providers: [...skill.providers], + rootPaths: [...(skill.rootPaths ?? [skill.rootPath])] + }) + } + return { + skills: sortDiscoveredSkills([...skillsByCanonicalPath.values()]), + sources: observation.sources + .filter((source) => rootMayContainSourceKind(source, sourceKinds)) + .map((source) => ({ ...source, providers: [...source.providers] })), + scannedAt: observation.scannedAt + } +} + +export function parseWslSkillDiscoveryOutput( + output: string, + roots: readonly SkillScanRoot[], + scannedAt = Date.now(), + sourceKinds?: readonly SkillSourceKind[], + names?: readonly string[] +): SkillDiscoveryResult { + return projectWslSkillDiscovery( + readWslSkillDiscoveryObservation(output, roots, scannedAt), + sourceKinds, + names + ) +} diff --git a/src/main/skills/skill-discovery-wsl-plugins.test.ts b/src/main/skills/skill-discovery-wsl-plugins.test.ts index f3ee9024ff2..2e8df58f68f 100644 --- a/src/main/skills/skill-discovery-wsl-plugins.test.ts +++ b/src/main/skills/skill-discovery-wsl-plugins.test.ts @@ -7,6 +7,7 @@ const runWslProcessMock = vi.hoisted(() => vi.fn()) vi.mock('../wsl/wsl-runner', () => ({ runWslProcess: runWslProcessMock })) import { buildSkillDiscoverySources } from './skill-discovery-sources' +import { rootMayContainSourceKind } from './skill-discovery-source-filter' import { discoverSkillsInWsl } from './skill-discovery-wsl' function record(...fields: string[]): string { @@ -17,66 +18,131 @@ function wslResult(stdout: string): WslResult { return { environmentResolved: true, code: 0, stdout, stderr: '', timedOut: false } } +function recordedScript(index: number): string { + const script: unknown = runWslProcessMock.mock.calls[index]?.[0].script + if (typeof script !== 'string') { + throw new Error('Expected a generated WSL script') + } + return script +} + describe('WSL Claude plugin skill discovery', () => { beforeEach(() => runWslProcessMock.mockReset()) afterEach(() => vi.unstubAllEnvs()) - it('reads enabled plugin metadata and scans the selected install inside the distro', async () => { - const homeDir = '/home/alice' - const cwd = '/work/orca' - // Why: a Windows host's own Hermes location says nothing about the distro's, - // so neither variable may reach the posix scan script. - vi.stubEnv('HERMES_HOME', 'C:\\Users\\alice\\hermes') - vi.stubEnv('LOCALAPPDATA', 'C:\\Users\\alice\\AppData\\Local') - const pluginId = 'compound-engineering@compound-engineering-plugin' - const installPath = '/home/alice/.claude/plugins/cache/compound/3.14.3' - const installed = JSON.stringify({ - plugins: { - [pluginId]: [{ scope: 'project', projectPath: cwd, installPath }] - } + it('skips workspace roots and plugin metadata for home-only discovery without cwd', async () => { + runWslProcessMock.mockResolvedValueOnce(wslResult('')) + + const result = await discoverSkillsInWsl({ + distro: 'Ubuntu', + homeDir: '/home/alice', + sourceKinds: ['home'] }) - const settings = JSON.stringify({ enabledPlugins: { [pluginId]: true } }) - const metadataOutput = [ - record('F', '0', '1', Buffer.from(installed).toString('base64')), - record('F', '1', '1', Buffer.from(settings).toString('base64')), - record('F', '2', '0', ''), - record('F', '3', '0', '') - ].join('') - const baseRootCount = buildSkillDiscoverySources({ - homeDir, - cwd, + + expect(runWslProcessMock).toHaveBeenCalledTimes(1) + const scanScript = recordedScript(0) + expect(scanScript.match(/'\/home\/alice\/\.agents\/skills'/g)).toHaveLength(1) + expect(scanScript.match(/'\/home\/alice\/\.claude\/skills'/g)).toHaveLength(1) + const expectedRoots = buildSkillDiscoverySources({ + homeDir: '/home/alice', + cwd: undefined, repos: [], + includeCwd: false, pathApi: pathPosix - }).length - const skillPath = `${installPath}/skills/ce-plan/SKILL.md` - const markdown = Buffer.from('---\nname: ce-plan\ndescription: Plan work.\n---\n').toString( - 'base64' - ) - const scanOutput = [ - record('R', String(baseRootCount), '1'), - record('S', String(baseRootCount), skillPath, skillPath, '1700000000', markdown) - ].join('') - runWslProcessMock.mockResolvedValueOnce(wslResult(metadataOutput)) - runWslProcessMock.mockResolvedValueOnce(wslResult(scanOutput)) - - const result = await discoverSkillsInWsl({ distro: 'Ubuntu', homeDir, cwd }) - - expect(runWslProcessMock).toHaveBeenCalledTimes(2) - const scanScript = runWslProcessMock.mock.calls[1]?.[0].script as string - expect(scanScript).toContain('/home/alice/.hermes/skills') - expect(scanScript).not.toContain('AppData') - expect(scanScript).toContain(`${installPath}/skills`) - expect(result.skills).toEqual([ - expect.objectContaining({ - name: 'ce-plan', - sourceKind: 'plugin', - rootPath: `${installPath}/skills` - }) - ]) - expect(result.sources).toEqual( - expect.arrayContaining([ - expect.objectContaining({ path: `${installPath}/skills`, owner: 'claude', exists: true }) - ]) + }) + expect(result.sources).toHaveLength( + expectedRoots.filter((root) => rootMayContainSourceKind(root, ['home'])).length ) }) + + it('skips plugin metadata and unrelated roots for filtered home discovery', async () => { + runWslProcessMock.mockResolvedValueOnce(wslResult('')) + + const result = await discoverSkillsInWsl({ + distro: 'Ubuntu', + homeDir: '/home/alice', + cwd: '/work/orca', + names: ['orchestration'], + sourceKinds: ['home'] + }) + + expect(runWslProcessMock).toHaveBeenCalledTimes(1) + const scanScript = recordedScript(0) + expect(scanScript).not.toContain('/work/orca') + expect(scanScript).not.toContain("'/home/alice/.codex/plugins/cache'") + const expectedRoots = buildSkillDiscoverySources({ + homeDir: '/home/alice', + cwd: '/work/orca', + repos: [], + includeCwd: true, + pathApi: pathPosix + }).filter((root) => rootMayContainSourceKind(root, ['home'])) + expect(result.sources).toHaveLength(expectedRoots.length) + }) + + it.each([true, false])( + 'preserves enabled plugins with explicit workspace=%s', + async (explicitWorkspace) => { + const homeDir = '/home/alice' + const cwd = explicitWorkspace ? '/work/orca' : homeDir + // Why: a Windows host's own Hermes location says nothing about the distro's, + // so neither variable may reach the posix scan script. + vi.stubEnv('HERMES_HOME', 'C:\\Users\\alice\\hermes') + vi.stubEnv('LOCALAPPDATA', 'C:\\Users\\alice\\AppData\\Local') + const pluginId = 'compound-engineering@compound-engineering-plugin' + const installPath = '/home/alice/.claude/plugins/cache/compound/3.14.3' + const installed = JSON.stringify({ + plugins: { + [pluginId]: [{ scope: 'project', projectPath: cwd, installPath }] + } + }) + const settings = JSON.stringify({ enabledPlugins: { [pluginId]: true } }) + const metadataOutput = [ + record('F', '0', '1', Buffer.from(installed).toString('base64')), + record('F', '1', '1', Buffer.from(settings).toString('base64')), + record('F', '2', '0', ''), + record('F', '3', '0', '') + ].join('') + const baseRootCount = buildSkillDiscoverySources({ + homeDir, + cwd, + repos: [], + pathApi: pathPosix + }).length + const skillPath = `${installPath}/skills/ce-plan/SKILL.md` + const markdown = Buffer.from('---\nname: ce-plan\ndescription: Plan work.\n---\n').toString( + 'base64' + ) + const scanOutput = [ + record('R', String(baseRootCount), '1'), + record('S', String(baseRootCount), skillPath, skillPath, '1700000000', markdown) + ].join('') + runWslProcessMock.mockResolvedValueOnce(wslResult(metadataOutput)) + runWslProcessMock.mockResolvedValueOnce(wslResult(scanOutput)) + + const result = await discoverSkillsInWsl({ + distro: 'Ubuntu', + homeDir, + ...(explicitWorkspace ? { cwd } : {}) + }) + + expect(runWslProcessMock).toHaveBeenCalledTimes(2) + const scanScript = recordedScript(1) + expect(scanScript).toContain('/home/alice/.hermes/skills') + expect(scanScript).not.toContain('AppData') + expect(scanScript).toContain(`${installPath}/skills`) + expect(result.skills).toEqual([ + expect.objectContaining({ + name: 'ce-plan', + sourceKind: 'plugin', + rootPath: `${installPath}/skills` + }) + ]) + expect(result.sources).toEqual( + expect.arrayContaining([ + expect.objectContaining({ path: `${installPath}/skills`, owner: 'claude', exists: true }) + ]) + ) + } + ) }) diff --git a/src/main/skills/skill-discovery-wsl.test.ts b/src/main/skills/skill-discovery-wsl.test.ts index 93640698dd0..e0dd6cf8a2b 100644 --- a/src/main/skills/skill-discovery-wsl.test.ts +++ b/src/main/skills/skill-discovery-wsl.test.ts @@ -82,6 +82,88 @@ describe('WSL skill discovery', () => { expect(script).toContain(`'/work/alice'\\''s project/.agents/skills'`) }) + it('filters requested names before reading skill payloads', () => { + const script = buildWslSkillDiscoveryCommand([homeRoot], ['Orchestration', 'computer-use']) + + expect(script).toContain("'orchestration'|'computer-use') return 0") + expect(script).toContain('local normalized_name=${1,,}') + expect(script).toContain('metadata_name_known=0') + expect(script).toContain('IFS= read -r -n "$remaining" line || read_status=$?') + expect(script).toContain('[ "$line_length" -ge "$remaining" ] && return') + expect(script).toContain('[[ "$candidate_name" =~ $non_ascii_pattern ]] && continue') + expect(script).toContain("line=${line#$'\\xEF\\xBB\\xBF'}") + expect(script).toContain('if [ "$metadata_name_known" -eq 1 ]; then') + expect(script).toContain('done < "$1"') + expect(script).not.toContain("awk '") + expect(script).not.toContain("tr '[:upper:]'") + expect(script.indexOf('matches_requested_name "$metadata_name" || continue')).toBeLessThan( + script.indexOf('encoded_markdown=$(head') + ) + }) + + it('filters classified source kinds while parsing', () => { + const markdown = Buffer.from('---\nname: Bundled\n---\n').toString('base64') + const output = [ + record('R', '0', '1'), + record( + 'S', + '0', + '/home/alice/.codex/skills/.system/bundled/SKILL.md', + '/home/alice/.codex/skills/.system/bundled/SKILL.md', + '1700000000', + markdown + ) + ].join('') + + expect(parseWslSkillDiscoveryOutput(output, [homeRoot], 42, ['home']).skills).toEqual([]) + expect(parseWslSkillDiscoveryOutput(output, [homeRoot], 42, []).skills).toHaveLength(1) + expect(parseWslSkillDiscoveryOutput(output, [homeRoot], 42, [], [' ']).skills).toHaveLength(1) + }) + + it('keeps ASCII prefiltering for mixed-locale requested names', () => { + const script = buildWslSkillDiscoveryCommand([homeRoot], ['orchestration', 'hébergement']) + + expect(script).toContain("'orchestration') return 0") + expect(script).not.toContain('hébergement) return 0') + expect(script).toContain('is_ascii_name "$directory_name"') + }) + + it('uses the TypeScript summary parser for uncertain WSL name candidates', () => { + const blockName = Buffer.from('\uFEFF---\nname: >-\n Agent\n Orchestration\n---\n').toString( + 'base64' + ) + const headingName = Buffer.from('# Computer Use\n\nUse the computer.\n').toString('base64') + const output = [ + record('R', '0', '1'), + record( + 'S', + '0', + '/home/alice/.agents/skills/renamed-a/SKILL.md', + '/home/alice/.agents/skills/renamed-a/SKILL.md', + '1700000000', + blockName + ), + record( + 'S', + '0', + '/home/alice/.agents/skills/renamed-b/SKILL.md', + '/home/alice/.agents/skills/renamed-b/SKILL.md', + '1700000000', + headingName + ) + ].join('') + + expect( + parseWslSkillDiscoveryOutput( + output, + [homeRoot], + 42, + ['home'], + ['agent orchestration', 'computer use'] + ).skills.map((skill) => skill.name) + ).toEqual(['Agent Orchestration', 'Computer Use']) + }) + it('rejects malformed host responses instead of reporting an empty scan', () => { expect(() => parseWslSkillDiscoveryOutput(record('S', '9'), [homeRoot])).toThrow( 'unknown source' diff --git a/src/main/skills/skill-discovery-wsl.ts b/src/main/skills/skill-discovery-wsl.ts index eae829a893f..23524bff02f 100644 --- a/src/main/skills/skill-discovery-wsl.ts +++ b/src/main/skills/skill-discovery-wsl.ts @@ -1,21 +1,15 @@ +import { + readWslSkillDiscoveryObservation, + projectWslSkillDiscovery, + type WslSkillDiscoveryObservation +} from './skill-discovery-wsl-observation' +export { parseWslSkillDiscoveryOutput } from './skill-discovery-wsl-observation' import { posix as pathPosix } from 'node:path' -import { summarizeSkillMarkdown } from '../../shared/skill-metadata' -import type { - DiscoveredSkill, - SkillDiscoveryResult, - SkillDiscoverySource -} from '../../shared/skills' +import type { SkillDiscoveryResult, SkillSourceKind } from '../../shared/skills' import { quoteBashString } from '../wsl-bash-command' import { runWslProcess } from '../wsl/wsl-runner' -import { - buildSkillDiscoverySources, - sortDiscoveredSkills, - sortSkillDiscoverySources, - sourceKindForSkill, - sourceLabelForSkill, - stablePathId, - type SkillScanRoot -} from './skill-discovery-sources' +import { buildSkillDiscoverySources, type SkillScanRoot } from './skill-discovery-sources' +import { rootMayContainSourceKind } from './skill-discovery-source-filter' import { discoverClaudePluginSkillSourcesInWsl } from './claude-plugin-skill-sources-wsl' import type { SkillProviderRootOverrides } from './skill-provider-destinations' import { SKILL_STAGING_GLOB } from './skill-delete/staging-names' @@ -25,10 +19,95 @@ const MAX_MARKDOWN_BYTES = 256 * 1024 const WSL_SCAN_TIMEOUT_MS = 10_000 const WSL_SCAN_MAX_OUTPUT_BYTES = 128 * 1024 * 1024 -export function buildWslSkillDiscoveryCommand(roots: readonly SkillScanRoot[]): string { +export function buildWslSkillDiscoveryCommand( + roots: readonly SkillScanRoot[], + names?: readonly string[] +): string { + const normalizedNames = names?.map((name) => name.trim().toLowerCase()).filter(Boolean) + const nameFilterHelpers: string[] = [] + const nameFilterBody: string[] = [] + if (normalizedNames?.length) { + const asciiNames = [...new Set(normalizedNames.filter((name) => /^[\x20-\x7e]+$/.test(name)))] + const matchBody = asciiNames.length + ? [ + ' case "$normalized_name" in', + ` ${asciiNames.map(quoteBashString).join('|')}) return 0 ;;`, + ' *) return 1 ;;', + ' esac' + ] + : [' return 1'] + nameFilterHelpers.push( + 'is_ascii_name() {', + " local LC_ALL=C non_ascii_pattern='[^ -~]'", + ' if [[ "$1" =~ $non_ascii_pattern ]]; then return 1; fi', + ' return 0', + '}', + 'matches_requested_name() {', + ' local LC_ALL=C', + ' local normalized_name=${1,,}', + ' while [[ "$normalized_name" == \' \'* ]]; do normalized_name=${normalized_name#?}; done', + ' while [[ "$normalized_name" == *\' \' ]]; do normalized_name=${normalized_name%?}; done', + ...matchBody, + '}', + 'read_frontmatter_name() {', + ' metadata_name=', + ' metadata_name_known=0', + ` local LC_ALL=C line first_line=1 remaining=${MAX_MARKDOWN_BYTES}`, + " local read_status line_length candidate_name= candidate_name_known=0 non_ascii_pattern='[^ -~]'", + ' while [ "$remaining" -gt 0 ]; do', + ' line=', + ' read_status=0', + ' IFS= read -r -n "$remaining" line || read_status=$?', + ' line_length=${#line}', + ' [ "$line_length" -ge "$remaining" ] && return', + ' [ "$read_status" -eq 0 ] || return', + ' remaining=$((remaining - line_length - 1))', + " line=${line%$'\\r'}", + ' if [ "$first_line" -eq 1 ]; then', + ' first_line=0', + " line=${line#$'\\xEF\\xBB\\xBF'}", + ' [[ "$line" =~ ^---[[:space:]]*$ ]] || return', + ' continue', + ' fi', + ' if [[ "$line" =~ ^---[[:space:]]*$ ]]; then', + ' metadata_name=$candidate_name', + ' metadata_name_known=$candidate_name_known', + ' return', + ' fi', + ' if [[ "$line" =~ ^name:[[:space:]]*(.*)$ ]]; then', + ' candidate_name=${BASH_REMATCH[1]}', + ' candidate_name_known=0', + ' while [[ "$candidate_name" == [[:space:]]* ]]; do candidate_name=${candidate_name#?}; done', + ' while [[ "$candidate_name" == *[[:space:]] ]]; do candidate_name=${candidate_name%?}; done', + ' case "$candidate_name" in ""|"|"|"|-"|">"|">-") continue ;; esac', + ' local quote=${candidate_name:0:1}', + ` if [ "\${#candidate_name}" -eq 1 ] && { [ "$quote" = '"' ] || [ "$quote" = "'" ]; }; then continue; fi`, + ` if [ "\${#candidate_name}" -ge 2 ] && { [ "$quote" = '"' ] || [ "$quote" = "'" ]; } && [ "\${candidate_name: -1}" = "$quote" ]; then`, + ' candidate_name=${candidate_name:1:${#candidate_name}-2}', + ' fi', + ' while [[ "$candidate_name" == [[:space:]]* ]]; do candidate_name=${candidate_name#?}; done', + ' while [[ "$candidate_name" == *[[:space:]] ]]; do candidate_name=${candidate_name%?}; done', + ' [ -n "$candidate_name" ] || continue', + ' [[ "$candidate_name" =~ $non_ascii_pattern ]] && continue', + ' candidate_name_known=1', + ' fi', + ' done < "$1"', + '}' + ) + nameFilterBody.push( + ' directory_name=${directory_path##*/}', + ' if is_ascii_name "$directory_name" && ! matches_requested_name "$directory_name"; then', + ' read_frontmatter_name "$skill_file"', + ' if [ "$metadata_name_known" -eq 1 ]; then', + ' matches_requested_name "$metadata_name" || continue', + ' fi', + ' fi' + ) + } const lines = [ 'set -u', 'set -o pipefail', + ...nameFilterHelpers, 'scan_root() {', ' root_index=$1', ' root_path=$2', @@ -40,6 +119,8 @@ export function buildWslSkillDiscoveryCommand(roots: readonly SkillScanRoot[]): ` printf '%s\\0%s\\0%s\\0' R "$root_index" 1`, ` while IFS= read -r -d '' skill_file; do`, ` canonical_path=$(realpath -- "$skill_file" 2>/dev/null || printf '%s' "$skill_file")`, + ` directory_path=\${skill_file%/*}`, + ...nameFilterBody, ` updated_at=$(stat -c '%Y' -- "$skill_file" 2>/dev/null || true)`, ` encoded_markdown=$(head -c ${MAX_MARKDOWN_BYTES} -- "$skill_file" 2>/dev/null | base64 | tr -d '\\n') || continue`, ` printf '%s\\0%s\\0%s\\0%s\\0%s\\0' S "$root_index" "$skill_file" "$canonical_path" "$updated_at"`, @@ -77,104 +158,28 @@ async function executeWslSkillDiscovery(distro: string, script: string): Promise return result.stdout } -function readProtocolField(fields: string[], index: number): string { - const value = fields[index] - if (value === undefined) { - throw new Error('WSL skill discovery returned an incomplete response.') - } - return value -} - -export function parseWslSkillDiscoveryOutput( - output: string, - roots: readonly SkillScanRoot[], - scannedAt = Date.now() -): SkillDiscoveryResult { - const fields = output.split('\0') - const rootExists = new Map() - const skillsByCanonicalPath = new Map() - let index = 0 - while (index < fields.length && fields[index]) { - const recordKind = fields[index++] - const rootIndex = Number.parseInt(readProtocolField(fields, index++), 10) - const root = roots[rootIndex] - if (!root) { - throw new Error('WSL skill discovery returned an unknown source.') - } - if (recordKind === 'R') { - rootExists.set(rootIndex, readProtocolField(fields, index++) === '1') - continue - } - if (recordKind !== 'S') { - throw new Error('WSL skill discovery returned an invalid response.') - } - - const skillFilePath = readProtocolField(fields, index++) - const canonicalSkillFilePath = readProtocolField(fields, index++) - const updatedAtSeconds = Number.parseInt(readProtocolField(fields, index++), 10) - const markdown = Buffer.from(readProtocolField(fields, index++), 'base64').toString('utf8') - const existing = skillsByCanonicalPath.get(canonicalSkillFilePath) - if (existing) { - // Why: dedup keeps one row, but every contributing root must survive so - // per-agent visibility does not depend on root scan order. providers is - // per-agent visibility too, so union it rather than keeping only the first. - if (existing.rootPaths && !existing.rootPaths.includes(root.path)) { - existing.rootPaths.push(root.path) - } - // Reassign a fresh array — `providers` aliases the scan root's array, so - // pushing in place would mutate the root and sibling skills/sources. - const mergedProviders = [...existing.providers] - for (const provider of root.providers) { - if (!mergedProviders.includes(provider)) { - mergedProviders.push(provider) - } - } - existing.providers = mergedProviders - continue - } - const directoryPath = pathPosix.dirname(skillFilePath) - const summary = summarizeSkillMarkdown(markdown) - const sourceKind = sourceKindForSkill(root, skillFilePath, pathPosix) - skillsByCanonicalPath.set(canonicalSkillFilePath, { - id: stablePathId(canonicalSkillFilePath), - name: summary.name ?? pathPosix.basename(directoryPath), - description: summary.description, - // Copy: `root.providers` is shared across every skill/source from this - // root, so a later in-place merge must not mutate the aliased array. - providers: [...root.providers], - sourceKind, - sourceLabel: sourceLabelForSkill(root, sourceKind), - rootPath: root.path, - rootPaths: [root.path], - directoryPath, - skillFilePath, - installed: true, - updatedAt: Number.isFinite(updatedAtSeconds) ? updatedAtSeconds * 1000 : null - }) - } - - const sources: SkillDiscoverySource[] = roots.map((root, rootIndex) => { - const exists = rootExists.get(rootIndex) ?? false - return { - ...root, - providers: [...root.providers], - exists, - skippedReason: exists ? undefined : 'missing' - } - }) - return { - skills: sortDiscoveredSkills([...skillsByCanonicalPath.values()]), - sources: sortSkillDiscoverySources(sources), - scannedAt - } -} - -export async function discoverSkillsInWsl(args: { +type WslSkillDiscoveryArgs = { distro: string homeDir: string - cwd: string + cwd?: string + names?: string[] + sourceKinds?: SkillSourceKind[] providerRootOverrides?: SkillProviderRootOverrides -}): Promise { +} + +export async function discoverSkillsInWsl( + args: WslSkillDiscoveryArgs +): Promise { + return projectWslSkillDiscovery( + await discoverSkillObservationInWsl(args), + args.sourceKinds, + args.names + ) +} + +export async function discoverSkillObservationInWsl( + args: WslSkillDiscoveryArgs +): Promise { // Plugin roots are resolved (in JS) from metadata this first wsl.exe call // reads, then fed to the scan's own wsl.exe call below — two sequential // process boots. That is a deliberate one-time-per-pane cost (the renderer @@ -184,24 +189,31 @@ export async function discoverSkillsInWsl(args: { // Why: plugin-metadata enrichment is optional. A failed/timed-out read must // degrade to zero plugin roots (matching the native readMetadataFile path), // not abort the mandatory native/home/repo/bundled scan. + const cwd = args.cwd ?? args.homeDir let pluginRoots: SkillScanRoot[] = [] - try { - pluginRoots = await discoverClaudePluginSkillSourcesInWsl(args) - } catch { - pluginRoots = [] + if (!args.sourceKinds?.length || args.sourceKinds.includes('plugin')) { + try { + pluginRoots = await discoverClaudePluginSkillSourcesInWsl({ ...args, cwd }) + } catch { + pluginRoots = [] + } } const roots = [ ...buildSkillDiscoverySources({ homeDir: args.homeDir, - cwd: args.cwd, + cwd, repos: [], + includeCwd: true, pathApi: pathPosix, providerRootOverrides: args.providerRootOverrides }), ...pluginRoots - ] + ].filter((root) => rootMayContainSourceKind(root, args.sourceKinds)) // Why: UNC traversal applies Windows casing and symlink rules. The distro // must own enumeration, metadata reads, and canonical path identity. - const output = await executeWslSkillDiscovery(args.distro, buildWslSkillDiscoveryCommand(roots)) - return parseWslSkillDiscoveryOutput(output, roots) + const output = await executeWslSkillDiscovery( + args.distro, + buildWslSkillDiscoveryCommand(roots, args.names) + ) + return readWslSkillDiscoveryObservation(output, roots) } diff --git a/src/main/ssh/ssh-relay-deploy-incumbent-verdict.test.ts b/src/main/ssh/ssh-relay-deploy-incumbent-verdict.test.ts index f25eff1ad9d..aca050275b1 100644 --- a/src/main/ssh/ssh-relay-deploy-incumbent-verdict.test.ts +++ b/src/main/ssh/ssh-relay-deploy-incumbent-verdict.test.ts @@ -54,10 +54,16 @@ vi.mock('./ssh-connection-utils', () => ({ Object.assign(new Error('SSH operation was cancelled'), { name: 'AbortError' }) })) +vi.mock('./ssh-relay-superseded-endpoints', () => ({ + sweepSupersededRelayEndpoints: vi.fn().mockResolvedValue([]) +})) +import { sweepSupersededRelayEndpoints } from './ssh-relay-superseded-endpoints' +import { gcOldRelayVersions } from './ssh-relay-versioned-install' import { deployAndLaunchRelay } from './ssh-relay-deploy' import { execCommand, waitForSentinel } from './ssh-relay-deploy-helpers' import { RelayCredentialMismatchError } from './ssh-relay-credential-mismatch-error' import { + RelayProbeCleanupUnconfirmedError, isRelayEndpointHeldError, isRelayEndpointUnresponsiveError } from './ssh-relay-endpoint-incumbent' @@ -87,14 +93,14 @@ const LIVE_UNENUMERABLE_PROBE = [ 'ORCA-INCUMBENT-END' ].join('\n') -function queueAliveSocketThenProbe(): void { +function queueAliveSocketThenProbe(output = LIVE_UNENUMERABLE_PROBE): void { vi.mocked(execCommand) .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') .mockResolvedValueOnce('/home/user') .mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') .mockResolvedValueOnce('') // launch namespace marker .mockResolvedValueOnce('ALIVE') - .mockResolvedValueOnce(LIVE_UNENUMERABLE_PROBE) + .mockResolvedValueOnce(output) } function launchedDaemon(conn: SshConnection): boolean { @@ -109,6 +115,7 @@ function launchedDaemon(conn: SshConnection): boolean { describe('deployAndLaunchRelay honours the incumbent verdict', () => { beforeEach(() => { vi.clearAllMocks() + vi.mocked(sweepSupersededRelayEndpoints).mockReset().mockResolvedValue([]) vi.mocked(execCommand).mockReset().mockResolvedValue('__ORCA_REMOTE_PLATFORM__ Linux x86_64') vi.mocked(waitForSentinel).mockReset() vi.spyOn(console, 'warn').mockImplementation(() => {}) @@ -133,6 +140,21 @@ describe('deployAndLaunchRelay honours the incumbent verdict', () => { expect(launchedDaemon(conn)).toBe(false) }) + it('does not launch while the incumbent probe cleanup is unconfirmed', async () => { + const conn = makeMockConnection() + vi.mocked(waitForSentinel).mockRejectedValueOnce(new Error('Relay handshake timed out')) + queueAliveSocketThenProbe( + LIVE_UNENUMERABLE_PROBE.replace( + 'HOLDERS_SOURCE=unavailable', + 'HOLDERS_SOURCE=unavailable\nPROBE_CLEANUP=unconfirmed' + ) + ) + await expect(deployAndLaunchRelay(conn)).rejects.toBeInstanceOf( + RelayProbeCleanupUnconfirmedError + ) + expect(launchedDaemon(conn)).toBe(false) + }) + it('still launches fresh when the socket probe itself fails', async () => { const conn = makeMockConnection() vi.mocked(execCommand) @@ -151,4 +173,29 @@ describe('deployAndLaunchRelay honours the incumbent verdict', () => { await deployAndLaunchRelay(conn) expect(launchedDaemon(conn)).toBe(true) }) + it.each([ + { error: new Error('completed sweep read failure'), expectedGcCalls: 1 }, + { error: new RelayProbeCleanupUnconfirmedError(), expectedGcCalls: 0 } + ])( + 'runs background GC only after probe cleanup is settled: $error.name', + async ({ error, expectedGcCalls }) => { + vi.mocked(execCommand) + .mockResolvedValueOnce('__ORCA_REMOTE_PLATFORM__ Linux x86_64') + .mockResolvedValueOnce('/home/user') + .mockResolvedValueOnce('ORCA-NATIVE-DEPS-OK') + .mockResolvedValueOnce('') + .mockResolvedValueOnce('DEAD') + .mockResolvedValueOnce('READY') + vi.mocked(waitForSentinel).mockResolvedValueOnce({ + write: vi.fn(), + onData: vi.fn(), + onClose: vi.fn() + }) + vi.mocked(sweepSupersededRelayEndpoints).mockRejectedValueOnce(error) + await deployAndLaunchRelay(makeMockConnection()) + await vi.waitFor(() => expect(sweepSupersededRelayEndpoints).toHaveBeenCalledOnce()) + await new Promise((resolve) => setImmediate(resolve)) + expect(gcOldRelayVersions).toHaveBeenCalledTimes(expectedGcCalls) + } + ) }) diff --git a/src/main/ssh/ssh-relay-deploy.test.ts b/src/main/ssh/ssh-relay-deploy.test.ts index 933f41a7891..895f2d4b579 100644 --- a/src/main/ssh/ssh-relay-deploy.test.ts +++ b/src/main/ssh/ssh-relay-deploy.test.ts @@ -200,7 +200,9 @@ describe('deployAndLaunchRelay', () => { const commands = vi.mocked(conn.exec).mock.calls.map(([command]) => command) expect(commands).toHaveLength(1) - expect(commands.some((command) => command.includes('--detached'))).toBe(false) + expect( + commands.filter((command) => /--detached|\brm -f\b|\bkill\s/.test(command)) + ).toHaveLength(0) }) it('resolves the remote node path once per deploy', async () => { diff --git a/src/main/ssh/ssh-relay-deploy.ts b/src/main/ssh/ssh-relay-deploy.ts index d9de3a4dc0e..903d318e872 100644 --- a/src/main/ssh/ssh-relay-deploy.ts +++ b/src/main/ssh/ssh-relay-deploy.ts @@ -88,6 +88,7 @@ import { powerShellCommand, powerShellLiteral, powerShellNativeArg } from './ssh import { relaySocketNameForInstanceId } from './ssh-relay-instance-id' import { resolveRelayEndpointBeforeRelaunch } from './ssh-relay-endpoint-takeover' import { + RelayProbeCleanupUnconfirmedError, isRelayEndpointHeldError, isRelayEndpointUnresponsiveError } from './ssh-relay-endpoint-incumbent' @@ -623,7 +624,11 @@ async function deployAndLaunchRelayAttempt( nodePath: launched.nodePath }) ) - .catch(() => {}) + .catch((error) => { + if (error instanceof RelayProbeCleanupUnconfirmedError) { + throw error + } + }) .then(() => gcOldRelayVersions(conn, remoteHome, remoteRelayDir, hostPlatform, { windowsNodePath: launched.nodePath, @@ -1773,6 +1778,7 @@ async function launchRelay( // `test -S`. Swallowing a Held/Unresponsive verdict launches a fresh daemon over a live one — // the exact collision the probe exists to prevent (it lost the bind, but only by luck). if ( + err instanceof RelayProbeCleanupUnconfirmedError || isUnconfirmedSshCommandTermination(err) || isRelayEndpointHeldError(err) || isRelayEndpointUnresponsiveError(err) diff --git a/src/main/ssh/ssh-relay-endpoint-incumbent-shell.integration.test.ts b/src/main/ssh/ssh-relay-endpoint-incumbent-shell.integration.test.ts index a8975d0520b..ef2f4d62258 100644 --- a/src/main/ssh/ssh-relay-endpoint-incumbent-shell.integration.test.ts +++ b/src/main/ssh/ssh-relay-endpoint-incumbent-shell.integration.test.ts @@ -10,6 +10,7 @@ import { join } from 'node:path' import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest' import { isReapableRelayHusk, + mayLaunchOverRelayEndpoint, parseRelayEndpointIncumbentProbe, relayEndpointIncumbentProbeCommand, type RelayEndpointIncumbent @@ -211,10 +212,14 @@ posixOnly('relay endpoint probe against a real socket', () => { expect(incumbent.verdict).toBe(hasLsof ? 'exited' : 'unverifiable') }) - it('reports no listener for a path that was never bound', async () => { + it('permits guarded launch when lsof cannot stat a never-bound path', async () => { const incumbent = await probe(join(workDir, 'never-existed.sock')) expect(incumbent.socketPresent).toBe(false) - expect(incumbent.verdict).toBe(hasLsof ? 'exited' : 'unverifiable') + expect(incumbent.verdict).toBe('unverifiable') + expect(incumbent.holdersEnumerable).toBe(false) + expect(incumbent.holders).toEqual([]) + expect(mayLaunchOverRelayEndpoint(incumbent)).toBe(true) + expect(isReapableRelayHusk(incumbent)).toBe(false) }) }) diff --git a/src/main/ssh/ssh-relay-endpoint-incumbent.test.ts b/src/main/ssh/ssh-relay-endpoint-incumbent.test.ts index de4cc28d170..40d2c49f5d9 100644 --- a/src/main/ssh/ssh-relay-endpoint-incumbent.test.ts +++ b/src/main/ssh/ssh-relay-endpoint-incumbent.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it, vi } from 'vitest' +import { RELAY_LSOF_PROBE_JS } from '../../shared/child-process/posix-lsof-probe' const execCommand = vi.fn() vi.mock('./ssh-relay-deploy-helpers', () => ({ @@ -20,6 +21,9 @@ import { import type { SshConnection } from './ssh-connection' import { getRemoteHostPlatform } from './ssh-remote-platform' +// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: The mocked execCommand never dereferences the connection; the Windows path returns before using it. +const connection = {} as SshConnection + const SOCK = '/home/u/.orca-remote/relay-0.1.0+aaaa/relay-deadbeef.sock' const POSIX_HOST = getRemoteHostPlatform('linux-x64') const WINDOWS_HOST = getRemoteHostPlatform('win32-x64') @@ -128,26 +132,48 @@ describe('parseRelayEndpointIncumbentProbe', () => { }) describe('probeRelayEndpointIncumbent', () => { - it('never asserts death when the probe itself could not run', async () => { - execCommand.mockRejectedValueOnce(new Error('channel closed')) + it('keeps the whole probe alive long enough to return a bounded lsof result', async () => { + execCommand.mockResolvedValueOnce( + probeOutput(['PRESENT=yes', 'LISTEN=refused', 'HOLDERS_SOURCE=unavailable']) + ) + + await probeRelayEndpointIncumbent(connection, POSIX_HOST, '/usr/bin/node', SOCK) + + expect(execCommand).toHaveBeenCalledWith(expect.anything(), expect.any(String), { + wrapCommand: true, + signal: undefined + }) + }) + + it('keeps a confirmed timeout or rejection unverifiable and unenumerable', async () => { + execCommand.mockRejectedValueOnce( + Object.assign(new Error('lsof timed out after 5s'), { sshChannelCloseConfirmed: true }) + ) const incumbent = await probeRelayEndpointIncumbent( - {} as SshConnection, + connection, POSIX_HOST, '/usr/bin/node', SOCK ) expect(incumbent.verdict).toBe('unverifiable') + expect(incumbent.holdersEnumerable).toBe(false) expect(incumbent.holders).toEqual([]) }) + it('rethrows an unconfirmed termination instead of masking it as unverifiable', async () => { + const unconfirmed = Object.assign(new Error('remote channel close was not confirmed'), { + sshChannelCloseConfirmed: false + }) + execCommand.mockRejectedValueOnce(unconfirmed) + + await expect( + probeRelayEndpointIncumbent(connection, POSIX_HOST, '/usr/bin/node', SOCK) + ).rejects.toBe(unconfirmed) + }) + it('does not shell out on Windows hosts, where the endpoint is a named pipe', async () => { execCommand.mockClear() - const incumbent = await probeRelayEndpointIncumbent( - {} as SshConnection, - WINDOWS_HOST, - 'node.exe', - SOCK - ) + const incumbent = await probeRelayEndpointIncumbent(connection, WINDOWS_HOST, 'node.exe', SOCK) expect(execCommand).not.toHaveBeenCalled() expect(incumbent.verdict).toBe('unverifiable') }) @@ -155,15 +181,20 @@ describe('probeRelayEndpointIncumbent', () => { describe('relayEndpointIncumbentProbeCommand', () => { it('ANDs the lsof selectors so it cannot match unrelated unix-socket holders', () => { - expect(relayEndpointIncumbentProbeCommand('/usr/bin/node', SOCK)).toContain( - 'lsof -t -a -U "$sock"' - ) + expect(RELAY_LSOF_PROBE_JS).toContain("['-t', '-a', '-U', process.argv[1]]") }) - it('never mutates the host: no unlink, no signal', () => { + it('never unlinks the relay endpoint', () => { const command = relayEndpointIncumbentProbeCommand('/usr/bin/node', SOCK) expect(command).not.toMatch(/\brm\b/) - expect(command).not.toMatch(/\bkill\b/) + }) + + it('bounds only lsof and keeps the connect-probe output available', () => { + const command = relayEndpointIncumbentProbeCommand('/usr/bin/node', SOCK) + expect(RELAY_LSOF_PROBE_JS).toContain("spawn('lsof'") + expect(command).toContain('}, 5000)') + expect(command).toContain("printf 'HOLDERS_SOURCE=unavailable\\n'") + expect(command.indexOf("printf 'LISTEN=%s\\n'")).toBeLessThan(command.indexOf('child = spawn(')) }) }) diff --git a/src/main/ssh/ssh-relay-endpoint-incumbent.ts b/src/main/ssh/ssh-relay-endpoint-incumbent.ts index aa914d2a0ca..343f92cadec 100644 --- a/src/main/ssh/ssh-relay-endpoint-incumbent.ts +++ b/src/main/ssh/ssh-relay-endpoint-incumbent.ts @@ -16,8 +16,10 @@ * an enumeration that found no holder). A relay whose socket was already unlinked is * invisible to this probe by construction — that is what the superseded sweep is for. * - a probe that could not run, a host without `lsof`, or a connect that failed for any other - * reason is `unverifiable`. It never authorizes unlinking, rebinding over, or signalling. + * reason is `unverifiable`. It cannot authorize client cleanup; guarded launch still + * delegates socket takeover checks to the daemon. */ +import { RELAY_LSOF_PROBE_JS } from '../../shared/child-process/posix-lsof-probe' import type { SshConnection } from './ssh-connection' import { shellEscape } from './ssh-connection-utils' import { @@ -56,9 +58,9 @@ export type RelayEndpointIncumbent = { verdict: RelayEndpointVerdict evidence: RelayEndpointEvidence socketPresent: boolean - /** Pids proven to hold this exact socket. Empty when the host could not enumerate them. */ + /** Pids observed holding this socket, including partial enumeration results. */ holders: RelayEndpointHolder[] - /** False when no enumeration tool was available — an empty `holders` then proves nothing. */ + /** False when enumeration was incomplete — an empty `holders` then proves nothing. */ holdersEnumerable: boolean } @@ -78,6 +80,13 @@ const CONNECT_PROBE_JS = [ `setTimeout(function(){say("unknown")},${CONNECT_PROBE_TIMEOUT_MS})` ].join('') +export class RelayProbeCleanupUnconfirmedError extends Error { + readonly name = 'RelayProbeCleanupUnconfirmedError' + constructor() { + super('Remote relay probe cleanup is unverifiable; refusing to race a replacement launch') + } +} + /** * A POSIX probe that reports only what the host actually observed. Every field has an * explicit "could not tell" value; nothing is inferred from a missing tool. @@ -99,10 +108,22 @@ export function relayEndpointIncumbentProbeCommand(nodePath: string, sockPath: s 'fi', 'printf \'LISTEN=%s\\n\' "$listen"', 'if command -v lsof >/dev/null 2>&1; then', - " printf 'HOLDERS_SOURCE=lsof\\n'", - // Why -a: lsof ORs its selectors, so without it every unix-socket holder on the box - // would be reported as holding this path (#8762). - ' for pid in $(lsof -t -a -U "$sock" 2>/dev/null); do', + // Why -a: lsof ORs selectors without it and reports unrelated unix-socket holders (#8762). + ` lsof_result=$("$node" -e ${shellEscape(RELAY_LSOF_PROBE_JS)} "$sock" 2>/dev/null) || lsof_result=unavailable`, + ' case "$lsof_result" in', + ' cleanup-unconfirmed*)', + " printf 'PROBE_CLEANUP=unconfirmed\\n'", + " printf 'HOLDERS_SOURCE=unavailable\\n'", + ' ;;', + ' lsof*)', + " printf 'HOLDERS_SOURCE=lsof\\n'", + ' ;;', + ' *)', + " printf 'HOLDERS_SOURCE=unavailable\\n'", + ' ;;', + ' esac', + " pids=$(printf '%s\\n' \"$lsof_result\" | sed '1d')", + ' for pid in $pids; do', ' args=$(ps -o args= -p "$pid" 2>/dev/null | tr "\\n" " ")', ' match=no', ' case "$args" in *relay.js*"$sock"*) match=yes ;; esac', @@ -125,6 +146,9 @@ export function parseRelayEndpointIncumbentProbe( if (!lines.includes(PROBE_BEGIN) || !lines.includes(PROBE_END)) { return unverifiableEndpoint(sockPath) } + if (lines.includes('PROBE_CLEANUP=unconfirmed')) { + throw new RelayProbeCleanupUnconfirmedError() + } const socketPresent = lines.includes('PRESENT=yes') const listen = lines.find((line) => line.startsWith('LISTEN='))?.slice('LISTEN='.length) ?? '' const holdersEnumerable = lines.includes('HOLDERS_SOURCE=lsof') @@ -219,7 +243,10 @@ export async function probeRelayEndpointIncumbent( } catch (err) { // An exec whose channel never confirmed close may still be running remotely; the caller // must not race a detached launch against it. - if (isUnconfirmedSshCommandTermination(err)) { + if ( + err instanceof RelayProbeCleanupUnconfirmedError || + isUnconfirmedSshCommandTermination(err) + ) { throw err } // Any other unanswered probe observes nothing. It is never evidence of death. diff --git a/src/main/ssh/ssh-relay-endpoint-takeover.test.ts b/src/main/ssh/ssh-relay-endpoint-takeover.test.ts index 1462feed2bf..af0a8b4b452 100644 --- a/src/main/ssh/ssh-relay-endpoint-takeover.test.ts +++ b/src/main/ssh/ssh-relay-endpoint-takeover.test.ts @@ -54,7 +54,7 @@ describe('incumbent alive and refusing', () => { await expect(resolve(REFUSED)).rejects.toSatisfy(isRelayEndpointHeldError) // The whole point of #8585: the incumbent's socket must survive so it is not orphaned. expect(issuedCommands().some((command) => /\brm -f\b/.test(command))).toBe(false) - expect(issuedCommands().some((command) => /\bkill\b/.test(command))).toBe(false) + expect(issuedCommands().some((command) => /\bkill\s/.test(command))).toBe(false) }) it('names the incumbent pid and the Reset Relay escape hatch in the error', async () => { @@ -70,7 +70,7 @@ describe('incumbent alive and refusing', () => { probe(['PRESENT=yes', 'LISTEN=unknown', 'HOLDERS_SOURCE=unavailable']) ) await expect(resolve(REFUSED)).rejects.toSatisfy(isRelayEndpointHeldError) - expect(issuedCommands().some((command) => /\bkill\b/.test(command))).toBe(false) + expect(issuedCommands().some((command) => /\bkill\s/.test(command))).toBe(false) }) it('treats a version mismatch as live even where holders cannot be enumerated', async () => { @@ -123,7 +123,7 @@ describe('incumbent alive but silent', () => { await expect(outcome).rejects.toSatisfy(isRelayEndpointUnresponsiveError) await expect(outcome).rejects.not.toSatisfy(isRelayEndpointHeldError) expect(issuedCommands().some((command) => /\brm -f\b/.test(command))).toBe(false) - expect(issuedCommands().some((command) => /\bkill\b/.test(command))).toBe(false) + expect(issuedCommands().some((command) => /\bkill\s/.test(command))).toBe(false) }) it('stays retryable when a silent holder is enumerated with live work', async () => { @@ -159,6 +159,19 @@ describe('incumbent unverifiable', () => { execCommand.mockRejectedValueOnce(new Error('exec timeout')) await expect(resolve()).resolves.toMatchObject({ verdict: 'unverifiable' }) }) + + it('rethrows an unconfirmed probe termination without relaunching, unlinking, or killing', async () => { + const unconfirmed = Object.assign(new Error('remote channel close was not confirmed'), { + sshChannelCloseConfirmed: false + }) + execCommand.mockRejectedValueOnce(unconfirmed) + + await expect(resolve()).rejects.toBe(unconfirmed) + expect(issuedCommands()).toHaveLength(1) + expect(issuedCommands().some((command) => /--detached|\brm -f\b|\bkill\s/.test(command))).toBe( + false + ) + }) }) describe('reapEmptyRelayHuskCommand', () => { diff --git a/src/main/ssh/ssh-relay-incumbent-process.test.ts b/src/main/ssh/ssh-relay-incumbent-process.test.ts new file mode 100644 index 00000000000..425e3f5f279 --- /dev/null +++ b/src/main/ssh/ssh-relay-incumbent-process.test.ts @@ -0,0 +1,121 @@ +import { mkdtempSync, writeFileSync, rmSync, readFileSync } from 'node:fs' +import { join } from 'node:path' +import { tmpdir } from 'node:os' +import { createServer } from 'node:net' +import { describe, expect, it, vi } from 'vitest' +import { runProcess } from '../../shared/child-process/run-process' +vi.mock('./ssh-relay-deploy-helpers', () => ({ + execCommand: vi.fn(), + isUnconfirmedSshCommandTermination: () => false +})) +import { + relayEndpointIncumbentProbeCommand, + parseRelayEndpointIncumbentProbe, + mayLaunchOverRelayEndpoint, + isReapableRelayHusk +} from './ssh-relay-endpoint-incumbent' + +async function probe(script: string, listening = false) { + const dir = mkdtempSync(join(tmpdir(), 'orca-incumbent-')) + const socket = join(dir, 'socket with spaces.sock') + const server = createServer((s) => s.end()) + const pidFile = join(dir, 'probe.pid') + try { + writeFileSync(join(dir, 'lsof'), `#!/bin/sh\n${script}`, { mode: 0o755 }) + if (listening) { + await new Promise((resolve, reject) => { + server.once('error', reject) + server.listen(socket, resolve) + }) + } + const start = performance.now() + const result = await runProcess({ + program: '/bin/sh', + args: ['-c', relayEndpointIncumbentProbeCommand(process.execPath, socket)], + env: { ...process.env, PATH: `${dir}:${process.env.PATH}`, FIXTURE_PID: pidFile }, + timeoutMs: 12000, + detached: true, + terminationBarrier: true + }) + const verdict = parseRelayEndpointIncumbentProbe(socket, result.stdout) + let pidAlive: boolean | null = null + try { + const pid = Number(readFileSync(pidFile, 'utf8')) + const state = await runProcess({ + program: 'ps', + args: ['-o', 'state=', '-p', String(pid)], + timeoutMs: 2000 + }) + pidAlive = !( + (state.code === 1 && !state.stdout.trim()) || + (state.code === 0 && state.stdout.trim().startsWith('Z')) + ) + } catch {} + return { result, verdict, elapsedMs: performance.now() - start, pidAlive } + } finally { + if (listening) { + await new Promise((resolve) => server.close(() => resolve())) + } + try { + const pid = Number(readFileSync(pidFile, 'utf8')) + if (Number.isInteger(pid) && pid > 0) { + process.kill(pid, 'SIGKILL') + } + } catch {} + rmSync(dir, { recursive: true, force: true }) + } +} +describe.skipIf(process.platform === 'win32')('real generated incumbent probe', () => { + it('bounds hung lsof and preserves live connect evidence', async () => { + const p = await probe('echo $$ > "$FIXTURE_PID"\nexec sleep 60\n', true) + expect(p.result.timedOut).toBe(false) + expect(p.result.code).toBe(0) + expect(p.verdict).toMatchObject({ + verdict: 'live', + holdersEnumerable: false, + evidence: 'accepted-connection' + }) + expect(p.pidAlive).toBe(false) + expect(p.elapsedMs).toBeLessThan(10000) + }) + it('stops a hung lsof helper as well as its parent', async () => { + const p = await probe('sleep 60 &\necho $! > "$FIXTURE_PID"\nwait\n', true) + expect(p.result.timedOut).toBe(false) + expect(p.verdict).toMatchObject({ verdict: 'live', holdersEnumerable: false }) + expect(p.pidAlive).toBe(false) + expect(p.elapsedMs).toBeLessThan(10000) + }) + it('does not mistake diagnostic enumeration failure for proven absence', async () => { + const p = await probe('echo "lsof: access denied" >&2\nexit 1\n') + expect(p.verdict).toMatchObject({ verdict: 'unverifiable', holdersEnumerable: false }) + }) + it.each(['echo "lsof: partial results" >&2\nexit 0\n', 'exit 2\n', 'exec sleep 60\n'])( + 'preserves positive holders from incomplete enumeration: %s', + async (ending) => { + const p = await probe(`echo ${process.pid}\n${ending}`) + expect(p.verdict).toMatchObject({ + verdict: 'live', + evidence: 'holder-process', + holdersEnumerable: false + }) + expect(p.verdict.holders.map((holder) => holder.pid)).toContain(process.pid) + expect(mayLaunchOverRelayEndpoint(p.verdict)).toBe(false) + expect(isReapableRelayHusk(p.verdict)).toBe(false) + } + ) + it.each(['printf 123', 'echo malformed'])( + 'rejects incomplete or malformed PID records: %s', + async (script) => { + const p = await probe(script) + expect(p.verdict).toMatchObject({ + verdict: 'unverifiable', + holdersEnumerable: false, + holders: [] + }) + } + ) + it('preserves a completed empty enumeration', async () => { + const p = await probe('exit 1\n') + expect(p.verdict).toMatchObject({ verdict: 'exited', holdersEnumerable: true }) + }) +}) diff --git a/src/main/ssh/ssh-relay-session-managed-hooks.test.ts b/src/main/ssh/ssh-relay-session-managed-hooks.test.ts index 93723965f92..36d5adbf021 100644 --- a/src/main/ssh/ssh-relay-session-managed-hooks.test.ts +++ b/src/main/ssh/ssh-relay-session-managed-hooks.test.ts @@ -128,4 +128,34 @@ describe('SshRelaySession managed hooks', () => { muxRequestMock.mock.invocationCallOrder[managedIndex] ) }) + + it('forwards the execution-host Claude version to the remote installer', async () => { + muxRequestMock.mockImplementation(async (method: string) => { + if (method === 'preflight.detectAgents') { + return { + agents: ['claude'], + versions: { claude: '2.1.261 (Claude Code)' } + } + } + return method === AGENT_HOOK_INSTALL_MANAGED_HOOKS_METHOD + ? { installers: 1, errors: 0 } + : { ok: true } + }) + const { mockStore, mockPortForward, getMainWindow } = createMockDeps() + // oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: establish only reads these mocked connection members in this harness. + const connection = { + sftp: vi.fn(), + getHostKeyFingerprint: vi.fn(() => 'SHA256:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA') + } as unknown as SshConnection + const session = new SshRelaySession('target-1', getMainWindow, mockStore, mockPortForward) + + await session.establish(connection) + await vi.waitFor(() => + expect(muxRequestMock).toHaveBeenCalledWith(AGENT_HOOK_INSTALL_MANAGED_HOOKS_METHOD, { + hostKeyFingerprint: 'SHA256:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + agents: ['claude'], + claudeVersion: '2.1.261' + }) + ) + }) }) diff --git a/src/main/ssh/ssh-relay-session-reconnect-incarnation.test.ts b/src/main/ssh/ssh-relay-session-reconnect-incarnation.test.ts index 72873500bf1..6760a27821c 100644 --- a/src/main/ssh/ssh-relay-session-reconnect-incarnation.test.ts +++ b/src/main/ssh/ssh-relay-session-reconnect-incarnation.test.ts @@ -445,7 +445,8 @@ describe('SshRelaySession reconnect incarnation ordering', () => { leafId: INCARNATION_LEAF_ID, ptyId: APP_PTY_ID, incarnationId, - mayReviveRetiredSurface: false + mayReviveRetiredSurface: false, + origin: 'relay_reattach' }) expect(vi.mocked(mockStore.persistPtyBinding).mock.invocationCallOrder[0]).toBeLessThan( vi.mocked(mockStore.markSshRemotePtyLeasesAttachedAsync).mock.invocationCallOrder[0]! diff --git a/src/main/ssh/ssh-relay-session.ts b/src/main/ssh/ssh-relay-session.ts index cfbe72ca574..ef33f2ecadd 100644 --- a/src/main/ssh/ssh-relay-session.ts +++ b/src/main/ssh/ssh-relay-session.ts @@ -26,7 +26,7 @@ import { agentHookServer } from '../agent-hooks/server' import { isAgentStatusHooksEnabled } from '../agent-hooks/managed-agent-hook-controls' import { buildManagedHookDetectionCommands, - detectedManagedHookAgents + readManagedHookDetectionResult } from '../agent-hooks/managed-hook-detection-commands' import { AGENT_HOOK_INSTALL_MANAGED_HOOKS_METHOD, @@ -1378,17 +1378,20 @@ export class SshRelaySession { try { const store = this.store as { getSettings?: Store['getSettings'] } - const detected = (await mux.request('preflight.detectAgents', { - commands: buildManagedHookDetectionCommands(store.getSettings?.() ?? null, 'linux') - })) as { agents?: unknown } - const agents = detectedManagedHookAgents(detected?.agents) + const detected = readManagedHookDetectionResult( + await mux.request('preflight.detectAgents', { + commands: buildManagedHookDetectionCommands(store.getSettings?.() ?? null, 'linux') + }) + ) + const agents = detected.agents if (agents.length === 0 || (shouldContinue && !shouldContinue())) { return } const hostKeyFingerprint = this.requireReadyConnection().getHostKeyFingerprint?.() const params = { ...(hostKeyFingerprint ? { hostKeyFingerprint } : {}), - agents + agents, + ...(detected.claudeVersion ? { claudeVersion: detected.claudeVersion } : {}) } const result = (await mux.request(AGENT_HOOK_INSTALL_MANAGED_HOOKS_METHOD, params)) as { errors?: unknown @@ -1564,30 +1567,7 @@ export class SshRelaySession { if (method !== AGENT_HOOK_NOTIFICATION_METHOD) { return } - const envelope = params as { - paneKey?: unknown - launchToken?: unknown - tabId?: unknown - worktreeId?: unknown - env?: unknown - version?: unknown - hasExplicitPrompt?: unknown - promptInteractionKey?: unknown - hookEventName?: unknown - source?: unknown - providerPromptId?: unknown - compactTrigger?: unknown - toolUseId?: unknown - toolAgentId?: unknown - teammateName?: unknown - toolAgentType?: unknown - isReplay?: unknown - providerSession?: unknown - providerSessionOnly?: unknown - shedFields?: unknown - claudeRunningNonAgentTask?: unknown - payload?: unknown - } + const envelope = params if (typeof envelope.paneKey !== 'string') { return } @@ -1609,6 +1589,7 @@ export class SshRelaySession { typeof envelope.hookEventName === 'string' ? envelope.hookEventName : undefined, source: envelope.source, providerPromptId: envelope.providerPromptId, + grokPromptBoundary: envelope.grokPromptBoundary === true ? true : undefined, compactTrigger: envelope.compactTrigger, toolUseId: typeof envelope.toolUseId === 'string' ? envelope.toolUseId : undefined, toolAgentId: typeof envelope.toolAgentId === 'string' ? envelope.toolAgentId : undefined, @@ -2784,7 +2765,8 @@ export class SshRelaySession { ptyId: appPtyId, incarnationId, ...(mayCreate ? {} : { mayCreate: false }), - mayReviveRetiredSurface: false + mayReviveRetiredSurface: false, + origin: 'relay_reattach' }) if (bound === false) { // Topology absence alone is not authority to kill a process, but neither refusal may diff --git a/src/main/ssh/ssh-relay-superseded-endpoints.test.ts b/src/main/ssh/ssh-relay-superseded-endpoints.test.ts index 9168f4688bd..03f7e478905 100644 --- a/src/main/ssh/ssh-relay-superseded-endpoints.test.ts +++ b/src/main/ssh/ssh-relay-superseded-endpoints.test.ts @@ -7,7 +7,10 @@ vi.mock('./ssh-relay-deploy-helpers', () => ({ (error as { sshChannelCloseConfirmed?: boolean } | null)?.sshChannelCloseConfirmed === false })) -import { parseRelayEndpointIncumbentProbe } from './ssh-relay-endpoint-incumbent' +import { + RelayProbeCleanupUnconfirmedError, + parseRelayEndpointIncumbentProbe +} from './ssh-relay-endpoint-incumbent' import { classifySupersededRelay, supersededRelayEndpointListCommand, @@ -97,6 +100,23 @@ describe('classifySupersededRelay', () => { }) describe('sweepSupersededRelayEndpoints', () => { + it('stops the sweep before cleanup when probe group termination is unconfirmed', async () => { + execCommand + .mockResolvedValueOnce(OLD_SOCK) + .mockResolvedValueOnce( + probe([ + 'PRESENT=yes', + 'LISTEN=accepted', + 'HOLDERS_SOURCE=unavailable', + 'PROBE_CLEANUP=unconfirmed' + ]) + ) + await expect(sweepSupersededRelayEndpoints(CONN, HOST, SWEEP)).rejects.toBeInstanceOf( + RelayProbeCleanupUnconfirmedError + ) + expect(issuedCommands()).toHaveLength(2) + }) + it('leaves an upgrade-orphaned relay that still owns terminals running, untouched', async () => { execCommand .mockResolvedValueOnce(`${OLD_SOCK}\n`) @@ -106,7 +126,7 @@ describe('sweepSupersededRelayEndpoints', () => { const findings = await sweepSupersededRelayEndpoints(CONN, HOST, SWEEP) expect(findings).toHaveLength(1) expect(findings[0]).toMatchObject({ sockPath: OLD_SOCK, outcome: 'retained-live-work' }) - expect(issuedCommands().some((command) => /\bkill\b/.test(command))).toBe(false) + expect(issuedCommands().some((command) => /\bkill\s/.test(command))).toBe(false) expect(issuedCommands().some((command) => /\brm -f\b/.test(command))).toBe(false) }) diff --git a/src/preload/api/filesystem-api.ts b/src/preload/api/filesystem-api.ts index 0312bc87fd0..478f3040f72 100644 --- a/src/preload/api/filesystem-api.ts +++ b/src/preload/api/filesystem-api.ts @@ -1,3 +1,4 @@ +import type { PathExistenceResult } from '../../shared/path-existence-batch' import type { SearchOptions, SearchResult } from '../../shared/code-search-types' import type { DirEntry, @@ -111,6 +112,10 @@ export type FilesystemApi = { filePath: string connectionId?: string }) => Promise<{ size: number; isDirectory: boolean; mtime: number }> + pathsExist?: (args: { + filePaths: string[] + connectionId?: string + }) => Promise pathExists: (args: { filePath: string; connectionId?: string }) => Promise listFiles: (args: { rootPath: string diff --git a/src/preload/api/fs-bridge.ts b/src/preload/api/fs-bridge.ts index c67e9abd9e3..207b34d8519 100644 --- a/src/preload/api/fs-bridge.ts +++ b/src/preload/api/fs-bridge.ts @@ -1,3 +1,4 @@ +import type { PathExistenceResult } from '../../shared/path-existence-batch' import { ipcRenderer } from 'electron' import type { SshMutationExpectation } from '../../shared/ssh-types' import type { SearchResult } from '../../shared/code-search-types' @@ -116,6 +117,10 @@ export const fsApi = { connectionId?: string }): Promise<{ size: number; isDirectory: boolean; mtime: number }> => ipcRenderer.invoke('fs:stat', args), + pathsExist: (args: { + filePaths: string[] + connectionId?: string + }): Promise => ipcRenderer.invoke('fs:pathsExist', args), pathExists: (args: { filePath: string; connectionId?: string }): Promise => ipcRenderer.invoke('fs:pathExists', args), listFiles: (args: { diff --git a/src/preload/api/runtime-api.ts b/src/preload/api/runtime-api.ts index 7fdf229dd88..c39740b73a8 100644 --- a/src/preload/api/runtime-api.ts +++ b/src/preload/api/runtime-api.ts @@ -123,6 +123,7 @@ export type RuntimeApi = { params?: unknown timeoutMs?: number expectedEnvironmentPairingRevision?: number + expectedEnvironmentRuntimeId?: string }) => Promise> subscribe: ( args: { @@ -131,6 +132,7 @@ export type RuntimeApi = { params?: unknown timeoutMs?: number expectedEnvironmentPairingRevision?: number + expectedEnvironmentRuntimeId?: string }, callbacks: { onResponse: (response: RuntimeRpcResponse) => void diff --git a/src/preload/api/runtime-environments-bridge.ts b/src/preload/api/runtime-environments-bridge.ts index 63c31df52f8..f1da42f3bbd 100644 --- a/src/preload/api/runtime-environments-bridge.ts +++ b/src/preload/api/runtime-environments-bridge.ts @@ -88,6 +88,7 @@ export const runtimeEnvironmentsApi = { params?: unknown timeoutMs?: number expectedEnvironmentPairingRevision?: number + expectedEnvironmentRuntimeId?: string }): Promise> => ipcRenderer.invoke('runtimeEnvironments:call', args), subscribe: async ( args: { @@ -96,6 +97,7 @@ export const runtimeEnvironmentsApi = { params?: unknown timeoutMs?: number expectedEnvironmentPairingRevision?: number + expectedEnvironmentRuntimeId?: string }, callbacks: { onResponse: (response: RuntimeRpcResponse) => void diff --git a/src/preload/api/shell-api.ts b/src/preload/api/shell-api.ts index d466ac26163..49e811aeb65 100644 --- a/src/preload/api/shell-api.ts +++ b/src/preload/api/shell-api.ts @@ -19,6 +19,7 @@ export type ShellApi = { openUrl: (url: string) => Promise openFilePath: (path: string) => Promise openFileUri: (uri: string) => Promise + pathsExist?: (paths: string[]) => Promise pathExists: (path: string) => Promise pickAttachment: () => Promise pickImage: () => Promise diff --git a/src/preload/api/shell-bridge.ts b/src/preload/api/shell-bridge.ts index 21ccda3fd83..6cd250042a6 100644 --- a/src/preload/api/shell-bridge.ts +++ b/src/preload/api/shell-bridge.ts @@ -23,6 +23,8 @@ export const shellApi = { openFileUri: (uri: string): Promise => ipcRenderer.invoke('shell:openFileUri', uri), + pathsExist: (paths: string[]): Promise => + ipcRenderer.invoke('shell:pathsExist', paths), pathExists: (path: string): Promise => ipcRenderer.invoke('shell:pathExists', path), pickAttachment: (): Promise => ipcRenderer.invoke('shell:pickAttachment'), diff --git a/src/preload/preload-runtime-support.ts b/src/preload/preload-runtime-support.ts index 27ce7d77bc2..6a9462473c1 100644 --- a/src/preload/preload-runtime-support.ts +++ b/src/preload/preload-runtime-support.ts @@ -13,7 +13,8 @@ import { resolveNativeFileDropPath, type NativeDropResolution, type NativeFileDropPayload, - type NativeFileDropPathEntry + type NativeFileDropPathEntry, + type NativeFileDropRejectedPayload } from '../shared/native-file-drop' /** Joins the synchronous unload checkpoint with its durable renderer write. */ @@ -133,7 +134,18 @@ export function installNativeFileDropHandlers(): void { paths.push(filePath) } } - if (paths.length === 0 || resolution?.target === 'rejected') { + if (resolution?.target === 'rejected') { + return + } + if (paths.length === 0) { + // The OS offered file items we could read no path from (promised or + // virtual files). Report it — silence here is #15782. + ipcRenderer.send('terminal:file-dropped-from-preload', { + byteLength: 0, + pathCount: files.length, + reason: 'unresolved-paths', + target: 'rejected' + } satisfies NativeFileDropRejectedPayload) return } const payload = createNativeFileDropPayload(resolution, paths) diff --git a/src/preload/runtime-environment-subscriptions.ts b/src/preload/runtime-environment-subscriptions.ts index f9d46b467aa..9324c062047 100644 --- a/src/preload/runtime-environment-subscriptions.ts +++ b/src/preload/runtime-environment-subscriptions.ts @@ -5,6 +5,8 @@ type RuntimeEnvironmentSubscribeArgs = { method: string params?: unknown timeoutMs?: number + expectedEnvironmentPairingRevision?: number + expectedEnvironmentRuntimeId?: string } type RuntimeEnvironmentSubscriptionCallbacks = { diff --git a/src/relay/agent-hook-envelope-build.ts b/src/relay/agent-hook-envelope-build.ts index 14a7430f997..6b1b45432d8 100644 --- a/src/relay/agent-hook-envelope-build.ts +++ b/src/relay/agent-hook-envelope-build.ts @@ -25,6 +25,7 @@ export function buildRelayHookEnvelope( promptInteractionKey: event.promptInteractionKey, hookEventName: event.hookEventName, providerPromptId: event.providerPromptId, + grokPromptBoundary: event.grokPromptBoundary, compactTrigger: event.compactTrigger, toolUseId: event.toolUseId, toolAgentId: event.toolAgentId, diff --git a/src/relay/ai-vault-service-filesystem.ts b/src/relay/ai-vault-service-filesystem.ts index 9315b2e4b2f..fd5ff90a755 100644 --- a/src/relay/ai-vault-service-filesystem.ts +++ b/src/relay/ai-vault-service-filesystem.ts @@ -1,3 +1,4 @@ +import { readRelayTranscriptBytes } from './ai-vault-transcript-stream' import { lstat, readdir } from 'node:fs/promises' import type { RemoteSessionFilesystemProvider } from '../main/ai-vault/remote-session-scanner-types' import { readRelayFileContent } from './fs-handler-file-read' @@ -13,6 +14,7 @@ export function createRelayAiVaultFilesystemProvider(): RemoteSessionFilesystemP })) }, readFile: readRelayFileContent, + readTranscriptBytes: readRelayTranscriptBytes, async stat(filePath) { const stats = await lstat(filePath) return { diff --git a/src/relay/ai-vault-transcript-stream.ts b/src/relay/ai-vault-transcript-stream.ts new file mode 100644 index 00000000000..df040a166fa --- /dev/null +++ b/src/relay/ai-vault-transcript-stream.ts @@ -0,0 +1,34 @@ +import { open } from 'node:fs/promises' +import { throwIfAiVaultScanCancelled } from '../main/ai-vault/ai-vault-scan-cancellation' +import { BinarySessionTranscriptError } from '../main/ai-vault/remote-session-content-lines' +import { BINARY_PROBE_BYTES, isBinaryBuffer } from './fs-handler-utils' + +/** The same open handle supplies the probe and stream, including across renames. */ +export async function* readRelayTranscriptBytes( + path: string, + signal?: AbortSignal +): AsyncGenerator { + throwIfAiVaultScanCancelled(signal) + const handle = await open(path, 'r') + try { + const probe = Buffer.alloc(BINARY_PROBE_BYTES) + const { bytesRead } = await handle.read(probe, 0, probe.length, 0) + if (isBinaryBuffer(probe.subarray(0, bytesRead))) { + throw new BinarySessionTranscriptError() + } + const input = handle.createReadStream({ start: 0, autoClose: false, signal }) + try { + for await (const chunk of input) { + throwIfAiVaultScanCancelled(signal) + if (!Buffer.isBuffer(chunk)) { + throw new TypeError('Expected transcript byte buffer') + } + yield chunk + } + } finally { + input.destroy() + } + } finally { + await handle.close() + } +} diff --git a/src/relay/fs-handler-file-range-dispatch.test.ts b/src/relay/fs-handler-file-range-dispatch.test.ts index 3f1de4693a4..20f5d69dd21 100644 --- a/src/relay/fs-handler-file-range-dispatch.test.ts +++ b/src/relay/fs-handler-file-range-dispatch.test.ts @@ -149,7 +149,7 @@ describe('fs.getCapabilities', () => { // is additive. Dropping the pre-existing key would strand an older desktop's // quick-open probe on a host that still serves it. it('advertises ranged reads without dropping the existing capability', async () => { - await expect(underTest.call('fs.getCapabilities', {})).resolves.toEqual({ + await expect(underTest.call('fs.getCapabilities', {})).resolves.toMatchObject({ quickOpenSearchVersion: 1, rangedReadVersion: 1 }) diff --git a/src/relay/fs-handler.ts b/src/relay/fs-handler.ts index d20d0d073d6..6286c71941e 100644 --- a/src/relay/fs-handler.ts +++ b/src/relay/fs-handler.ts @@ -1,3 +1,4 @@ +import { pathsExistOnRelay } from './fs-path-existence' import { tmpdir } from 'node:os' import type { RelayDispatcher, RequestContext } from './dispatcher' import type { RelayContext } from './context' @@ -89,6 +90,7 @@ export class FsHandler { this.dispatcher.onRequest('fs.tempDir', () => this.tempDir()) this.dispatcher.onRequest('fs.writeFile', (p) => writeRelayFile(p)) this.dispatcher.onRequest('fs.writeTerminalArtifact', (p) => this.writeTerminalArtifact(p)) + this.dispatcher.onRequest('fs.pathsExist', pathsExistOnRelay) this.dispatcher.onRequest('fs.stat', (p) => statRelayPath(p)) this.dispatcher.onRequest('fs.lstat', (p) => lstatRelayPath(p)) this.dispatcher.onRequest('fs.deletePath', (p) => deleteRelayPath(p, this.watchRegistry)) @@ -102,7 +104,8 @@ export class FsHandler { this.dispatcher.onRequest('fs.search', (p) => this.search(p)) this.dispatcher.onRequest('fs.getCapabilities', async () => ({ quickOpenSearchVersion: 1, - rangedReadVersion: 1 + rangedReadVersion: 1, + pathExistenceBatchVersion: 1 })) this.dispatcher.onRequest('fs.listFiles', (p, c) => this.listFiles(p, c)) this.dispatcher.onRequest('fs.workspaceSpaceScan', (p, c) => this.workspaceSpaceScan(p, c)) diff --git a/src/relay/fs-path-existence.ts b/src/relay/fs-path-existence.ts new file mode 100644 index 00000000000..48ee51cda2b --- /dev/null +++ b/src/relay/fs-path-existence.ts @@ -0,0 +1,22 @@ +import { statRelayPath } from './fs-path-metadata-requests' +import { capturePathExistence, validatePathExistenceBatch } from '../shared/path-existence-batch' + +export async function pathsExistOnRelay(params: Record) { + const paths = params.filePaths + validatePathExistenceBatch(paths) + return Promise.all( + paths.map((filePath) => + capturePathExistence(async () => { + try { + await statRelayPath({ filePath }) + return true + } catch (error) { + if (error instanceof Error && 'code' in error && error.code === 'ENOENT') { + return false + } + throw error + } + }) + ) + ) +} diff --git a/src/relay/managed-hook-installer.test.ts b/src/relay/managed-hook-installer.test.ts index f33086e871f..aba8f51490d 100644 --- a/src/relay/managed-hook-installer.test.ts +++ b/src/relay/managed-hook-installer.test.ts @@ -94,4 +94,22 @@ describe('registerManagedHookInstaller', () => { 'invalid_managed_hook_agents' ) }) + + it('forwards only a parseable Claude execution-host version', async () => { + const installManagedHooks = vi.fn().mockResolvedValue({ installers: 1, errors: 0 }) + const handler = captureHandler(() => ({ installManagedHooks })) + + await handler({ agents: ['claude'], claudeVersion: '2.1.261 (Claude Code)' }, context()) + await handler({ agents: ['claude'], claudeVersion: 'unknown' }, context()) + + expect(installManagedHooks).toHaveBeenNthCalledWith(1, { + signal: undefined, + agents: ['claude'], + claudeVersion: '2.1.261' + }) + expect(installManagedHooks).toHaveBeenNthCalledWith(2, { + signal: undefined, + agents: ['claude'] + }) + }) }) diff --git a/src/relay/managed-hook-installer.ts b/src/relay/managed-hook-installer.ts index 4bb67da2460..bdd65a789f6 100644 --- a/src/relay/managed-hook-installer.ts +++ b/src/relay/managed-hook-installer.ts @@ -6,6 +6,7 @@ import { import type { RelayDispatcher, RequestContext } from './dispatcher' import type { AgentHookTarget } from '../shared/agent-hook-types' import { isManagedAgentHookTarget } from '../shared/managed-agent-hook-targets' +import { parseClaudeCliVersion } from '../main/claude/claude-session-end-hook-capability' export type ManagedHookInstallSummary = { installers: number @@ -17,6 +18,7 @@ export type ManagedHookRuntime = { signal?: AbortSignal hostKeyFingerprint?: string agents?: readonly AgentHookTarget[] + claudeVersion?: string }) => Promise } @@ -41,6 +43,12 @@ function readAgents(params: unknown): AgentHookTarget[] { return [...new Set(raw)] } +function readClaudeVersion(params: unknown): string | undefined { + const raw = + params !== null && typeof params === 'object' ? Reflect.get(params, 'claudeVersion') : null + return parseClaudeCliVersion(typeof raw === 'string' ? raw : null) ?? undefined +} + let managedHookRuntime: ManagedHookRuntime | null = null function loadManagedHookRuntime(): ManagedHookRuntime { @@ -62,10 +70,12 @@ export function registerManagedHookInstaller( context.signal?.throwIfAborted() const hostKeyFingerprint = readHostKeyFingerprint(params) const agents = readAgents(params) + const claudeVersion = readClaudeVersion(params) return await loadRuntime().installManagedHooks({ signal: context.signal, ...(hostKeyFingerprint ? { hostKeyFingerprint } : {}), - agents + agents, + ...(claudeVersion ? { claudeVersion } : {}) }) } ) diff --git a/src/relay/preflight-handler.test.ts b/src/relay/preflight-handler.test.ts index 06886180624..211c85bceb3 100644 --- a/src/relay/preflight-handler.test.ts +++ b/src/relay/preflight-handler.test.ts @@ -1,8 +1,9 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { buildPosixCommandPathLookupScript } from '../shared/posix-command-path-lookup' -const { execFileAsyncMock } = vi.hoisted(() => ({ - execFileAsyncMock: vi.fn() +const { execFileAsyncMock, runProcessMock } = vi.hoisted(() => ({ + execFileAsyncMock: vi.fn(), + runProcessMock: vi.fn() })) const { @@ -30,6 +31,7 @@ vi.mock('../main/wsl', () => ({ listWslDistrosAsync: listWslDistrosAsyncMock })) vi.mock('../main/git-bash', () => ({ isGitBashAvailable: isGitBashAvailableMock })) +vi.mock('../shared/child-process/run-process', () => ({ runProcess: runProcessMock })) import { buildCommandLookupSpec, @@ -65,6 +67,7 @@ function fishLookupArgs(command: string): string[] { beforeEach(() => { execFileAsyncMock.mockReset() + runProcessMock.mockReset() isPwshAvailableAsyncMock.mockReset() isWslAvailableAsyncMock.mockReset() listWslDistrosAsyncMock.mockReset() @@ -237,6 +240,43 @@ describe('hasAbsoluteCommandPath', () => { }) describe('PreflightHandler', () => { + it('reports a requested version from the resolved execution-host binary', async () => { + execFileAsyncMock.mockResolvedValue({ + stdout: '__ORCA_AGENT_PATH__/home/dev/.local/bin/claude\n' + }) + runProcessMock.mockResolvedValue({ + code: 0, + signal: null, + stdout: '2.1.261 (Claude Code)\n', + stderr: '', + timedOut: false + }) + const requestHandlers = new Map) => Promise>() + const dispatcher = { + onRequest: vi.fn( + (method: string, handler: (params: Record) => Promise) => { + requestHandlers.set(method, handler) + } + ) + } + new PreflightHandler(dispatcher as never) + + await expect( + requestHandlers.get('preflight.detectAgents')!({ + commands: [{ id: 'claude', cmd: 'claude', reportVersion: true }] + }) + ).resolves.toEqual({ + agents: ['claude'], + versions: { claude: '2.1.261 (Claude Code)' } + }) + expect(runProcessMock).toHaveBeenCalledWith( + expect.objectContaining({ + program: '/home/dev/.local/bin/claude', + args: ['--version'] + }) + ) + }) + it('honors required commands when reporting detected agents', async () => { execFileAsyncMock.mockImplementation(async (_file, args) => { const script = String(args[1]) diff --git a/src/relay/preflight-handler.ts b/src/relay/preflight-handler.ts index a703b26847e..b84166e76ba 100644 --- a/src/relay/preflight-handler.ts +++ b/src/relay/preflight-handler.ts @@ -8,6 +8,7 @@ import { isPwshAvailableAsync } from '../main/pwsh' import { isWslAvailableAsync, listWslDistrosAsync } from '../main/wsl' import { isGitBashAvailable } from '../main/git-bash' import { buildPosixCommandPathLookupScript } from '../shared/posix-command-path-lookup' +import { runProcess } from '../shared/child-process/run-process' const execFileAsync = promisify(execFile) @@ -28,6 +29,7 @@ type AgentDetectionRuntime = NodeJS.Platform | 'wsl' type AgentDetectionCommand = { id: string cmd: string + reportVersion?: true requiredCommands?: readonly string[] unsupportedRuntimes?: readonly AgentDetectionRuntime[] } @@ -54,7 +56,10 @@ export class PreflightHandler { // Why: the client sends the command list rather than importing TUI_AGENT_CONFIG // on the relay side. This keeps the relay bundle minimal and makes the protocol // self-describing — the relay doesn't need to know the agent catalog. - private async detectAgents(params: Record): Promise<{ agents: string[] }> { + private async detectAgents(params: Record): Promise<{ + agents: string[] + versions?: Record + }> { const commands = params.commands as AgentDetectionCommand[] if (!Array.isArray(commands)) { return { agents: [] } @@ -70,26 +75,40 @@ export class PreflightHandler { const results = await Promise.all( probeCommands.map(async (cmd) => ({ cmd, - installed: await this.isCommandOnPath(cmd) + executablePath: await resolveCommandPathForRelay(cmd) })) ) const foundCommands = new Set( - results.filter((result) => result.installed).map(({ cmd }) => cmd) + results.filter((result) => result.executablePath !== null).map(({ cmd }) => cmd) ) + const detectedCommands = commands.filter( + (command) => + !isDetectionUnsupportedInRuntime(command, process.platform) && + foundCommands.has(command.cmd) && + (command.requiredCommands ?? []).every((required) => foundCommands.has(required)) + ) + const versions: Record = {} + for (const command of detectedCommands) { + if ( + command.id !== 'claude' || + command.reportVersion !== true || + versions.claude !== undefined + ) { + continue + } + const executablePath = results.find((result) => result.cmd === command.cmd)?.executablePath + if (!executablePath) { + continue + } + const version = await probeCommandVersion(executablePath) + if (version) { + versions[command.id] = version + } + } return { - agents: [ - ...new Set( - commands - .filter( - (command) => - !isDetectionUnsupportedInRuntime(command, process.platform) && - foundCommands.has(command.cmd) && - (command.requiredCommands ?? []).every((required) => foundCommands.has(required)) - ) - .map(({ id }) => id) - ) - ] + agents: [...new Set(detectedCommands.map(({ id }) => id))], + ...(Object.keys(versions).length > 0 ? { versions } : {}) } } @@ -119,8 +138,33 @@ export class PreflightHandler { // startup files sourced. Ask the user's configured shell so agent dirs added // by zsh/bash/fish startup hooks match the remote terminal experience. // Windows has no POSIX shell on native OpenSSH hosts, so use where.exe there. - private async isCommandOnPath(command: string): Promise { - return isCommandOnPathForRelay(command) +} + +async function probeCommandVersion(executablePath: string): Promise { + try { + const env = buildRelayCommandEnv(process.env, process.platform) + const pathKey = process.platform === 'win32' && env.Path !== undefined ? 'Path' : 'PATH' + const executableDir = path.dirname(executablePath) + const inheritedPath = env[pathKey] + const result = await runProcess({ + program: executablePath, + args: ['--version'], + env: { + ...env, + [pathKey]: inheritedPath + ? `${executableDir}${path.delimiter}${inheritedPath}` + : executableDir + }, + timeoutMs: 5_000, + maxOutputBytes: 4_096 + }) + if (result.code !== 0) { + return null + } + const output = `${result.stdout}\n${result.stderr}`.trim() + return output.length > 0 ? output : null + } catch { + return null } } @@ -172,6 +216,13 @@ export async function isCommandOnPathForRelay( command: string, options: RelayCommandLookupOptions = {} ): Promise { + return (await resolveCommandPathForRelay(command, options)) !== null +} + +export async function resolveCommandPathForRelay( + command: string, + options: RelayCommandLookupOptions = {} +): Promise { const platform = options.platform ?? process.platform const env = options.env ?? process.env const specs = buildCommandLookupSpecs(command, platform, env, options.accountLoginShell) @@ -184,31 +235,39 @@ export async function isCommandOnPathForRelay( timeout: 5000, ...(spec.windowsHide ? { windowsHide: true } : {}) }) - if (hasAbsoluteCommandPath(stdout, platform)) { - return true + const resolvedPath = getAbsoluteCommandPath(stdout, platform) + if (resolvedPath) { + return resolvedPath } } catch { // Try the inherited-PATH fallback before reporting the agent missing. } } - return false + return null } export function hasAbsoluteCommandPath(output: string, platform: NodeJS.Platform): boolean { + return getAbsoluteCommandPath(output, platform) !== null +} + +function getAbsoluteCommandPath(output: string, platform: NodeJS.Platform): string | null { const pathOps = platform === 'win32' ? win32 : path - return output - .split(/\r?\n/) - .map((line) => line.trim()) - .some((line) => { - const resolvedPath = - platform === 'win32' - ? line - : line.startsWith(AGENT_PATH_PREFIX) - ? line.slice(AGENT_PATH_PREFIX.length) - : '' - return pathOps.isAbsolute(resolvedPath) - }) + return ( + output + .split(/\r?\n/) + .map((line) => line.trim()) + .map((line) => { + const resolvedPath = + platform === 'win32' + ? line + : line.startsWith(AGENT_PATH_PREFIX) + ? line.slice(AGENT_PATH_PREFIX.length) + : '' + return pathOps.isAbsolute(resolvedPath) ? resolvedPath : null + }) + .find((resolvedPath): resolvedPath is string => resolvedPath !== null) ?? null + ) } function buildPosixCommandLookupSpec(command: string, shell: string): CommandLookupSpec { diff --git a/src/renderer/src/attention/agent-attention-acknowledgement.ts b/src/renderer/src/attention/agent-attention-acknowledgement.ts new file mode 100644 index 00000000000..69d67860024 --- /dev/null +++ b/src/renderer/src/attention/agent-attention-acknowledgement.ts @@ -0,0 +1,151 @@ +import { + readAgentAttentionUnreadReason, + type AgentAttentionRemainder, + type ReadableAgentAttentionUnread +} from './agent-attention-contract' + +/** Subject-keyed turn bookkeeping the acknowledgement policy reads; no surface shape here. */ +export type AgentAttentionTurnRecords = { + liveTurns: Record + /** Turns kept after their session ended, so a finished agent can still be acknowledged. */ + retainedTurns: Record + acknowledgedTurnStartedAt: Record +} + +export type AgentAttentionAcknowledgementSink = { + acknowledgeSubjects: (subjectKeys: string[]) => void + clearWorkspaceUnread: (workspaceId: string) => void + clearGroupUnread: (groupId: string) => void + clearSubjectUnread: (subjectKey: string) => void +} + +export function readAgentAttentionTurnStartedAt( + records: Pick, + subjectKey: string +): number | null { + return ( + records.liveTurns[subjectKey]?.stateStartedAt ?? + records.retainedTurns[subjectKey]?.entry.stateStartedAt ?? + null + ) +} + +/** + * Subjects on the viewed surface whose current turn has not been acknowledged yet. + * + * Why compare stateStartedAt (not updatedAt): same-state pings must not re-trigger an ack, + * matching the is-unvisited rule the workspace card uses. + */ +export function computeAgentAcknowledgementTargets( + records: AgentAttentionTurnRecords, + subjectKey: string | null +): string[] { + if (subjectKey === null) { + return [] + } + const targets: string[] = [] + const acknowledgedAt = records.acknowledgedTurnStartedAt[subjectKey] ?? 0 + const liveTurn = records.liveTurns[subjectKey] + if (liveTurn && acknowledgedAt < liveTurn.stateStartedAt) { + targets.push(subjectKey) + } + const retainedTurn = records.retainedTurns[subjectKey] + if (retainedTurn && acknowledgedAt < retainedTurn.entry.stateStartedAt) { + targets.push(subjectKey) + } + return targets +} + +/** The viewed subject when it currently holds an unread attention marker. */ +export function resolveViewedUnreadSubjectKey( + unreadBySubjectKey: Record, + subjectKey: string | null +): string | null { + if (subjectKey === null) { + return null + } + return readAgentAttentionUnreadReason(unreadBySubjectKey[subjectKey]) === null ? null : subjectKey +} + +/** + * Manual mark-unread protections that no longer apply: the user moved to another subject, or + * the agent took a new turn. + * + * Why keep on null: persisted UI hydrates before the turn snapshot lands, so an active subject + * with no row yet is "not known", not "moved on"; wiping it would lose the user's mark-unread. + */ +export function computeLapsedManualUnreadProtections( + records: Pick & { + manuallyUnreadTurnStartedAt: Record + }, + activeSubjectKeys: ReadonlySet +): string[] { + const lapsed: string[] = [] + for (const [subjectKey, turnStartedAt] of Object.entries(records.manuallyUnreadTurnStartedAt)) { + if (!activeSubjectKeys.has(subjectKey)) { + lapsed.push(subjectKey) + continue + } + const currentTurn = readAgentAttentionTurnStartedAt(records, subjectKey) + if (currentTurn !== null && currentTurn !== turnStartedAt) { + lapsed.push(subjectKey) + } + } + return lapsed +} + +/** + * Workspace unread is coarse, so a hidden sibling still wanting attention keeps it lit even + * while the user acknowledges the subject in front of them. + */ +export function shouldClearWorkspaceAttention( + remainder: AgentAttentionRemainder, + args: { viewedGroupId: string; clearedSubjectKeys: ReadonlySet } +): boolean { + if (!remainder.hasSurfaces) { + return true + } + for (const subjectKey of remainder.unreadSubjectKeys) { + if (!args.clearedSubjectKeys.has(subjectKey)) { + return false + } + } + for (const groupId of remainder.unreadGroupIds) { + if (groupId !== args.viewedGroupId) { + return false + } + } + return true +} + +export function applyAgentAttentionAcknowledgement( + sink: AgentAttentionAcknowledgementSink, + args: { + /** Null when a hidden sibling still owns the workspace's attention. */ + workspaceIdToClear: string | null + viewedGroupId: string + subjectKeys: string[] + viewedUnreadSubjectKey?: string | null + } +): void { + const subjectKeysToClear = new Set(args.subjectKeys) + if (args.viewedUnreadSubjectKey) { + subjectKeysToClear.add(args.viewedUnreadSubjectKey) + } + + if (args.subjectKeys.length === 0 && subjectKeysToClear.size === 0) { + return + } + + if (args.subjectKeys.length > 0) { + sink.acknowledgeSubjects(args.subjectKeys) + } + if (args.workspaceIdToClear !== null) { + // Why: the selected agent is now visible, so drop the Dock-driving workspace unread. + sink.clearWorkspaceUnread(args.workspaceIdToClear) + } + sink.clearGroupUnread(args.viewedGroupId) + for (const subjectKey of subjectKeysToClear) { + sink.clearSubjectUnread(subjectKey) + } +} diff --git a/src/renderer/src/attention/agent-attention-contract.ts b/src/renderer/src/attention/agent-attention-contract.ts new file mode 100644 index 00000000000..644691a2b3d --- /dev/null +++ b/src/renderer/src/attention/agent-attention-contract.ts @@ -0,0 +1,85 @@ +/** + * Provider-neutral agent attention boundary. + * + * Nothing in this folder may import a PTY, terminal leaf or terminal layout module: a + * surface adapter answers every question about where a subject lives and who can see it, + * so a non-terminal agent surface can supply its own adapter without touching the policy. + */ + +/** Why an unread marker exists. `legacy` is a marker written before reasons were recorded. */ +export type AgentAttentionUnreadReason = + | 'agent-completion' + | 'terminal-bell' + | 'manual-mark-unread' + | 'legacy' + +/** Stored marker shape: a classified reason, or the pre-reason boolean still on live state. */ +export type StoredAgentAttentionUnread = AgentAttentionUnreadReason | true + +/** What a reader may find, including a marker some other writer cleared to `false`. */ +export type ReadableAgentAttentionUnread = AgentAttentionUnreadReason | boolean | undefined + +/** Reads a marker without guessing its origin: an unclassified boolean reports as `legacy`. */ +export function readAgentAttentionUnreadReason( + marker: ReadableAgentAttentionUnread +): AgentAttentionUnreadReason | null { + if (marker === undefined || marker === false) { + return null + } + return marker === true ? 'legacy' : marker +} + +/** A workspace-scoped attention subject; `surfaceKey` addresses one surface inside it. */ +export type AgentAttentionSubject = { + workspaceId: string + surfaceKey?: string | undefined +} + +/** A subject that names a concrete surface, so the adapter can resolve its container. */ +export type AgentAttentionSurfaceSubject = { + workspaceId: string + surfaceKey: string +} + +/** What the boundary knows about the subject still being alive when it admits an event. */ +export type AgentAttentionLiveness = { + hasLiveSession: boolean + hasFreshActivityEvidence: boolean +} + +/** Whether a surface key still addresses the surface that produced the event. */ +export type AgentAttentionSurfaceAdmission = + | { admitted: true; groupId: string } + | { admitted: false; cause: 'unknown-surface' | 'superseded-surface' } + +/** Attention still held elsewhere in a workspace, as the owning surface sees it. */ +export type AgentAttentionRemainder = { + /** False when the workspace owns no surfaces at all, so nothing can hold its unread. */ + hasSurfaces: boolean + unreadSubjectKeys: readonly string[] + unreadGroupIds: readonly string[] +} + +/** + * The surface-shaped half of the boundary. One implementation per agent surface kind; + * the terminal implementation is the only holder of the PTY/leaf/layout predicates. + */ +export type AgentAttentionSurface = { + /** Is there still a running session behind this subject? */ + hasLiveSession: (subject: AgentAttentionSubject) => boolean + /** Resolve the surface to its current container, rejecting a stale or reused address. */ + admitSurface: ( + subject: AgentAttentionSurfaceSubject, + liveness: AgentAttentionLiveness + ) => AgentAttentionSurfaceAdmission + /** Is this exact surface the one the user is looking at right now? */ + isSurfaceViewed: (subject: AgentAttentionSurfaceSubject) => boolean + /** Fallback for events with no surface key: is the workspace itself on screen? */ + isWorkspaceViewed: (workspaceId: string) => boolean + /** In-app selection only — true even when the window is in the background. */ + isWorkspaceActive: (workspaceId: string) => boolean + /** The subject on screen inside a container, if the container shows one. */ + resolveViewedSubjectKey: (groupId: string) => string | null + /** Attention held by the workspace's other surfaces, for sibling protection. */ + collectWorkspaceAttentionRemainder: (workspaceId: string) => AgentAttentionRemainder +} diff --git a/src/renderer/src/attention/agent-attention-policy.test.ts b/src/renderer/src/attention/agent-attention-policy.test.ts new file mode 100644 index 00000000000..ac21cdd58cb --- /dev/null +++ b/src/renderer/src/attention/agent-attention-policy.test.ts @@ -0,0 +1,181 @@ +import { describe, expect, it, vi } from 'vitest' +import type { AgentAttentionSurface } from './agent-attention-contract' +import { + applyAgentAttention, + resolveAgentAttention, + type AgentAttentionRequest, + type AgentAttentionSink +} from './agent-attention-policy' + +const WORKSPACE = 'wt-1' +const SUBJECT = 'tab-1:leaf-1' +const GROUP = 'tab-1' + +function makeSurface(overrides: Partial = {}): AgentAttentionSurface { + return { + hasLiveSession: () => true, + admitSurface: () => ({ admitted: true, groupId: GROUP }), + isSurfaceViewed: () => false, + isWorkspaceViewed: () => false, + isWorkspaceActive: () => false, + resolveViewedSubjectKey: () => null, + collectWorkspaceAttentionRemainder: () => ({ + hasSurfaces: true, + unreadSubjectKeys: [], + unreadGroupIds: [] + }), + ...overrides + } +} + +function completion(overrides: Partial = {}): AgentAttentionRequest { + return { + subject: { workspaceId: WORKSPACE, surfaceKey: SUBJECT }, + reason: 'agent-completion', + settlesTurn: true, + hasFreshActivityEvidence: false, + groupAttentionEnabled: false, + ...overrides + } +} + +function makeSink(): AgentAttentionSink & { calls: string[] } { + const calls: string[] = [] + return { + calls, + unread: { + markWorkspaceUnread: (workspaceId) => calls.push(`workspace:${workspaceId}`), + markSubjectUnread: (key, reason) => calls.push(`subject:${key}:${reason}`), + markGroupUnread: (key, reason) => calls.push(`group:${key}:${reason}`), + markSurfaceUnread: (key, reason) => calls.push(`surface:${key}:${reason}`) + }, + requestDelivery: (request) => calls.push(`deliver:${request.workspaceId}:${request.subjectKey}`) + } +} + +describe('resolveAgentAttention', () => { + it('rejects a subject with no live session and no fresh activity evidence', () => { + const decision = resolveAgentAttention( + completion(), + makeSurface({ hasLiveSession: () => false }) + ) + expect(decision).toEqual({ admitted: false, cause: 'no-live-session' }) + }) + + it('admits a dead surface when fresh activity evidence stands in for liveness', () => { + const admitSurface = vi.fn(() => ({ admitted: true, groupId: GROUP }) as const) + const decision = resolveAgentAttention( + completion({ hasFreshActivityEvidence: true }), + makeSurface({ hasLiveSession: () => false, admitSurface }) + ) + expect(decision.admitted).toBe(true) + // The surface must be told which evidence admitted the event so it can pick its gate. + expect(admitSurface).toHaveBeenCalledWith( + { workspaceId: WORKSPACE, surfaceKey: SUBJECT }, + { hasLiveSession: false, hasFreshActivityEvidence: true } + ) + }) + + it('rejects a superseded surface outright — no unread and no delivery', () => { + const decision = resolveAgentAttention( + completion(), + makeSurface({ admitSurface: () => ({ admitted: false, cause: 'superseded-surface' }) }) + ) + expect(decision).toEqual({ admitted: false, cause: 'superseded-surface' }) + + const sink = makeSink() + applyAgentAttention(decision, sink) + expect(sink.calls).toEqual([]) + }) + + it('rejects a surface key that resolves to no container', () => { + const decision = resolveAgentAttention( + completion(), + makeSurface({ admitSurface: () => ({ admitted: false, cause: 'unknown-surface' }) }) + ) + expect(decision).toEqual({ admitted: false, cause: 'unknown-surface' }) + }) + + it('admits a viewed surface for delivery but earns it no unread', () => { + const decision = resolveAgentAttention( + completion(), + makeSurface({ isSurfaceViewed: () => true }) + ) + expect(decision).toMatchObject({ admitted: true, unread: null }) + + const sink = makeSink() + applyAgentAttention(decision, sink) + expect(sink.calls).toEqual([`deliver:${WORKSPACE}:${SUBJECT}`]) + }) + + it('carries the unread reason into every store write', () => { + const decision = resolveAgentAttention( + completion({ groupAttentionEnabled: true }), + makeSurface() + ) + const sink = makeSink() + applyAgentAttention(decision, sink) + expect(sink.calls).toEqual([ + `workspace:${WORKSPACE}`, + `subject:${SUBJECT}:agent-completion`, + `group:${GROUP}:agent-completion`, + `surface:${SUBJECT}:agent-completion`, + `deliver:${WORKSPACE}:${SUBJECT}` + ]) + }) + + it('keeps container attention behind its presentation flag', () => { + const sink = makeSink() + applyAgentAttention(resolveAgentAttention(completion(), makeSurface()), sink) + expect(sink.calls).toEqual([ + `workspace:${WORKSPACE}`, + `subject:${SUBJECT}:agent-completion`, + `deliver:${WORKSPACE}:${SUBJECT}` + ]) + }) + + it('falls back to workspace visibility when the event names no surface', () => { + const isWorkspaceViewed = vi.fn(() => true) + const admitSurface = vi.fn() + const decision = resolveAgentAttention( + completion({ subject: { workspaceId: WORKSPACE } }), + makeSurface({ isWorkspaceViewed, admitSurface }) + ) + expect(decision).toMatchObject({ admitted: true, unread: null }) + expect(isWorkspaceViewed).toHaveBeenCalledWith(WORKSPACE) + // No surface key means there is no address to validate. + expect(admitSurface).not.toHaveBeenCalled() + }) + + it('delivers a bell without validating the surface address or writing unread', () => { + const admitSurface = vi.fn() + const isSurfaceViewed = vi.fn() + const decision = resolveAgentAttention( + completion({ reason: 'terminal-bell', settlesTurn: false }), + makeSurface({ admitSurface, isSurfaceViewed }) + ) + expect(decision).toMatchObject({ admitted: true, unread: null }) + expect(admitSurface).not.toHaveBeenCalled() + expect(isSurfaceViewed).not.toHaveBeenCalled() + + const sink = makeSink() + applyAgentAttention(decision, sink) + expect(sink.calls).toEqual([`deliver:${WORKSPACE}:${SUBJECT}`]) + }) + + it('reports in-app workspace selection to the delivery owner', () => { + const decision = resolveAgentAttention( + completion(), + makeSurface({ isWorkspaceActive: (workspaceId) => workspaceId === WORKSPACE }) + ) + expect(decision).toMatchObject({ admitted: true, delivery: { workspaceIsActive: true } }) + }) + + it('writes unread before requesting delivery so a suppressed banner still leaves a marker', () => { + const sink = makeSink() + applyAgentAttention(resolveAgentAttention(completion(), makeSurface()), sink) + expect(sink.calls.indexOf(`workspace:${WORKSPACE}`)).toBeLessThan( + sink.calls.indexOf(`deliver:${WORKSPACE}:${SUBJECT}`) + ) + }) +}) diff --git a/src/renderer/src/attention/agent-attention-policy.ts b/src/renderer/src/attention/agent-attention-policy.ts new file mode 100644 index 00000000000..7a075e50f6c --- /dev/null +++ b/src/renderer/src/attention/agent-attention-policy.ts @@ -0,0 +1,143 @@ +import type { + AgentAttentionSubject, + AgentAttentionSurface, + AgentAttentionUnreadReason +} from './agent-attention-contract' + +export type AgentAttentionRequest = { + subject: AgentAttentionSubject + reason: AgentAttentionUnreadReason + /** + * A settled turn owns the subject's attention, so its address is validated and unread is + * decided. A bare surface signal (a bell) only has to prove the subject is still alive. + */ + settlesTurn: boolean + /** Out-of-band proof the subject just produced work, used when no live session is visible. */ + hasFreshActivityEvidence: boolean + /** Presentation policy: also raise the container/surface attention markers. */ + groupAttentionEnabled: boolean +} + +export type AgentAttentionUnreadWrite = { + workspaceId: string + subjectKey: string | null + groupId: string | null + reason: AgentAttentionUnreadReason + groupAttentionEnabled: boolean +} + +export type AgentAttentionDeliveryRequest = { + workspaceId: string + subjectKey: string | null + /** Carried so the delivery owner can apply its own suppress-while-focused policy. */ + workspaceIsActive: boolean +} + +export type AgentAttentionDecision = + | { admitted: false; cause: 'no-live-session' | 'unknown-surface' | 'superseded-surface' } + | { + admitted: true + unread: AgentAttentionUnreadWrite | null + delivery: AgentAttentionDeliveryRequest + } + +export type AgentAttentionUnreadSink = { + /** Workspace unread is a persisted boolean shared with remote clients; it carries no reason. */ + markWorkspaceUnread: (workspaceId: string) => void + markSubjectUnread: (subjectKey: string, reason: AgentAttentionUnreadReason) => void + markGroupUnread: (groupId: string, reason: AgentAttentionUnreadReason) => void + markSurfaceUnread: (subjectKey: string, reason: AgentAttentionUnreadReason) => void +} + +export type AgentAttentionSink = { + unread: AgentAttentionUnreadSink + requestDelivery: (request: AgentAttentionDeliveryRequest) => void +} + +/** + * Decides what an attention event earns, asking the surface adapter for every fact. + * + * Admission and visibility are deliberately separate gates: a superseded surface is rejected + * outright (no unread, no delivery), while a surface the user is watching is admitted and + * delivered but earns no unread. + */ +export function resolveAgentAttention( + request: AgentAttentionRequest, + surface: AgentAttentionSurface +): AgentAttentionDecision { + const { workspaceId } = request.subject + const subjectKey = request.subject.surfaceKey ?? null + const hasLiveSession = surface.hasLiveSession(request.subject) + if (!hasLiveSession && !request.hasFreshActivityEvidence) { + return { admitted: false, cause: 'no-live-session' } + } + + let groupId: string | null = null + if (request.settlesTurn && subjectKey !== null) { + const admission = surface.admitSurface( + { workspaceId, surfaceKey: subjectKey }, + { hasLiveSession, hasFreshActivityEvidence: request.hasFreshActivityEvidence } + ) + if (!admission.admitted) { + return { admitted: false, cause: admission.cause } + } + groupId = admission.groupId + } + + const delivery: AgentAttentionDeliveryRequest = { + workspaceId, + subjectKey, + workspaceIsActive: surface.isWorkspaceActive(workspaceId) + } + if (!request.settlesTurn) { + return { admitted: true, unread: null, delivery } + } + + const viewed = + subjectKey === null + ? surface.isWorkspaceViewed(workspaceId) + : surface.isSurfaceViewed({ workspaceId, surfaceKey: subjectKey }) + return { + admitted: true, + unread: viewed + ? null + : { + workspaceId, + subjectKey, + groupId, + reason: request.reason, + groupAttentionEnabled: request.groupAttentionEnabled + }, + delivery + } +} + +export function applyAgentAttentionUnread( + write: AgentAttentionUnreadWrite, + sink: AgentAttentionUnreadSink +): void { + sink.markWorkspaceUnread(write.workspaceId) + if (write.subjectKey !== null) { + // Why: focus-return auto-ack needs an agent-specific marker; the generic surface marker + // below also covers bells and is gated behind the experimental attention setting. + sink.markSubjectUnread(write.subjectKey, write.reason) + } + if (write.groupAttentionEnabled && write.groupId !== null && write.subjectKey !== null) { + sink.markGroupUnread(write.groupId, write.reason) + sink.markSurfaceUnread(write.subjectKey, write.reason) + } +} + +/** Unread is written before delivery so a suppressed banner still leaves the marker behind. */ +export function applyAgentAttention( + decision: AgentAttentionDecision, + sink: AgentAttentionSink +): void { + if (!decision.admitted) { + return + } + if (decision.unread !== null) { + applyAgentAttentionUnread(decision.unread, sink.unread) + } + sink.requestDelivery(decision.delivery) +} diff --git a/src/renderer/src/components/UnexpectedSignoutCard.tsx b/src/renderer/src/components/UnexpectedSignoutCard.tsx index ee0e8949ec3..b11c8dfb2ed 100644 --- a/src/renderer/src/components/UnexpectedSignoutCard.tsx +++ b/src/renderer/src/components/UnexpectedSignoutCard.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react' +import { useEffect, useState } from 'react' import { BookOpen, ChevronDown, CircleUserRound, Files, Smartphone, X } from 'lucide-react' import { useAppStore } from '../store' import { translate } from '@/i18n/i18n' @@ -55,7 +55,7 @@ export function UnexpectedSignoutCard(): React.JSX.Element | null { const [expanded, setExpanded] = useState(false) const [preview] = useState(readPreviewFlag) const [previewDismissed, setPreviewDismissed] = useState(false) - const reconnectingProfile = useRef(null) + const [appearance, setAppearance] = useState<'unseen' | 'visible' | 'closed'>('unseen') useEffect(() => { let cancelled = false @@ -101,47 +101,29 @@ export function UnexpectedSignoutCard(): React.JSX.Element | null { } }, []) - const dismissedVersion = - appVersion && dismissedVersions.includes(appVersion) ? appVersion : persistedDismissedVersion + const dismissedVersion = dismissedVersions[0] ?? persistedDismissedVersion const eligible = shouldShowUnexpectedSignoutCard({ authStatus, persistedUIReady, appVersion, - dismissedVersion + dismissedVersion: appearance === 'visible' ? null : dismissedVersion }) + const visible = preview + ? persistedUIReady && !previewDismissed + : authRefreshReady && appearance !== 'closed' && eligible - const visible = preview ? persistedUIReady && !previewDismissed : authRefreshReady && eligible - - // Observe recovery independently of visibility and asynchronous version/hydration reads. + // Record the first appearance without closing the card currently being read. useEffect(() => { - if (preview || !authRefreshReady) { + if (preview) { return } - if (authStatus?.state === 'reconnect-required' && authStatus.configured && authStatus.cloud) { - reconnectingProfile.current = authStatus.activeProfileId - } else if (authStatus?.state === 'connected') { - if ( - reconnectingProfile.current === authStatus.activeProfileId && - persistedUIReady && - appVersion - ) { - reconnectingProfile.current = null - if (dismissedVersion !== appVersion) { - dismissForVersion(appVersion) - } - } - } else { - reconnectingProfile.current = null + if (visible && appearance === 'unseen' && appVersion) { + setAppearance('visible') + dismissForVersion(appVersion) + } else if (!visible && appearance === 'visible') { + setAppearance('closed') } - }, [ - preview, - authRefreshReady, - authStatus, - persistedUIReady, - appVersion, - dismissedVersion, - dismissForVersion - ]) + }, [preview, visible, appearance, appVersion, dismissForVersion]) if (!visible) { return null @@ -153,8 +135,8 @@ export function UnexpectedSignoutCard(): React.JSX.Element | null { const handleDismiss = (): void => { if (preview) { setPreviewDismissed(true) - } else if (appVersion) { - dismissForVersion(appVersion) + } else { + setAppearance('closed') } } diff --git a/src/renderer/src/components/dashboard-popout/AgentTerminalPreview.tsx b/src/renderer/src/components/dashboard-popout/AgentTerminalPreview.tsx index ec05a7105a5..f0360d2b795 100644 --- a/src/renderer/src/components/dashboard-popout/AgentTerminalPreview.tsx +++ b/src/renderer/src/components/dashboard-popout/AgentTerminalPreview.tsx @@ -26,6 +26,7 @@ import { createPreviewGridClaim } from './preview-grid-claim' import { createPreviewBoxFit } from './preview-terminal-box-fit' import { installPreviewTerminalAppMenuClipboard } from './preview-terminal-app-menu-clipboard' import { installPreviewTerminalRightClickPaste } from './preview-terminal-right-click-paste' +import { installTerminalNativeCopyGutterTrim } from '@/components/terminal-pane/terminal-native-copy-gutter' import { isWindowsUserAgent } from '@/components/terminal-pane/pane-helpers' import type { TerminalPreviewDataPayload } from '../../../../shared/terminal-preview' @@ -107,6 +108,7 @@ export function AgentTerminalPreview({ let userInputDisposable: { dispose: () => void } | null = null let imeBridge: PreviewImeBridge | null = null let disposeKeyHandler: (() => void) | null = null + let disposeNativeCopyGutterTrim: (() => void) | null = null let disposeTerminalCompatibility: (() => void) | null = null // Why: mirrors the pane's tracker — the policy needs the flags the TUI // negotiated, and this preview parses the same output stream the pane does. @@ -215,6 +217,13 @@ export function AgentTerminalPreview({ }) } + const installNativeCopyGutterTrim = (): void => { + if (!terminal) { + return + } + disposeNativeCopyGutterTrim = installTerminalNativeCopyGutterTrim(terminal).dispose + } + const installTerminalCompatibility = (): void => { if (!terminal) { return @@ -273,6 +282,7 @@ export function AgentTerminalPreview({ } terminalRef.current = terminal installTerminalCompatibility() + installNativeCopyGutterTrim() installInputRouting() installImeNativeTextBridge() installKeyHandler() @@ -340,6 +350,8 @@ export function AgentTerminalPreview({ disposeTerminalCompatibility = null disposeKeyHandler?.() disposeKeyHandler = null + disposeNativeCopyGutterTrim?.() + disposeNativeCopyGutterTrim = null terminal?.dispose() terminal = null terminalRef.current = null @@ -395,6 +407,7 @@ export function AgentTerminalPreview({ disposeImeNativeTextBridge() disposeTerminalCompatibility?.() disposeKeyHandler?.() + disposeNativeCopyGutterTrim?.() void window.api.terminalPreview.unsubscribe(ptyId) terminal?.dispose() terminalRef.current = null diff --git a/src/renderer/src/components/dashboard-popout/preview-terminal-key-handler.ts b/src/renderer/src/components/dashboard-popout/preview-terminal-key-handler.ts index 29a6b80688d..1b263144a53 100644 --- a/src/renderer/src/components/dashboard-popout/preview-terminal-key-handler.ts +++ b/src/renderer/src/components/dashboard-popout/preview-terminal-key-handler.ts @@ -13,6 +13,7 @@ import { resolvePreviewShortcutAction, type PreviewShortcutContext } from './preview-terminal-shortcuts' +import { readTerminalClipboardSelection } from '@/components/terminal-pane/terminal-clipboard-selection-text' /** * Installs the preview terminal's ONE custom key handler (xterm allows a single @@ -109,7 +110,7 @@ export function installPreviewTerminalKeyHandler(args: { nativeOnlyShortcutTracker.prepareKeyDown(event) const keybindings = useAppStore.getState().keybindings if (keybindingMatchesAction('terminal.copySelection', event, platform, keybindings)) { - const selection = terminal.getSelection() + const selection = readTerminalClipboardSelection(terminal) if ( !selection && platform !== 'darwin' && diff --git a/src/renderer/src/components/editor/combined-diff/CombinedDiffViewer.tsx b/src/renderer/src/components/editor/combined-diff/CombinedDiffViewer.tsx index 82e7ece6cfb..449f89cb70f 100644 --- a/src/renderer/src/components/editor/combined-diff/CombinedDiffViewer.tsx +++ b/src/renderer/src/components/editor/combined-diff/CombinedDiffViewer.tsx @@ -348,6 +348,7 @@ export default function CombinedDiffViewer({ ({ + executionHostId: 'local' +})) + +vi.mock('@/store', () => ({ useAppStore: { getState: () => ({}) } })) +vi.mock('@/lib/worktree-runtime-owner', () => ({ + getExecutionHostIdForWorktree: () => testState.executionHostId +})) + +const { CombinedDiffFileTreeRow } = await import('./combined-diff-file-tree-row') +const { readWorkspaceFileDragSource } = await import('@/lib/workspace-file-drag') + +globalThis.IS_REACT_ACT_ENVIRONMENT = true + +const roots: Root[] = [] +afterEach(() => { + roots.splice(0).forEach((root) => act(() => root.unmount())) + document.body.replaceChildren() + testState.executionHostId = 'local' +}) + +function renderRow(sourceWorkspaceId?: string): HTMLDivElement { + const container = document.createElement('div') + document.body.appendChild(container) + const root = createRoot(container) + roots.push(root) + act(() => { + root.render( + {}} + onNavigate={() => {}} + /> + ) + }) + return container +} + +function dragRow(container: HTMLDivElement): DataTransfer { + const transfer = new DataTransfer() + const event = new Event('dragstart', { bubbles: true, cancelable: true }) + Object.defineProperty(event, 'dataTransfer', { value: transfer }) + act(() => { + container.querySelector('[draggable="true"]')?.dispatchEvent(event) + }) + return transfer +} + +describe('combined diff rows stamp their drag source', () => { + // The tab's entry list is a snapshot, but the paths it drags belong to the + // workspace as it is owned now — the same answer the source-control rows give. + it('stamps the live owner of the workspace the diff belongs to', () => { + testState.executionHostId = 'runtime:env-1' + expect(readWorkspaceFileDragSource(dragRow(renderRow('wt-1')))).toEqual({ + executionHostId: 'runtime:env-1', + workspaceId: 'wt-1' + }) + }) + + it('leaves the drag unstamped when the owner or the workspace is unknown', () => { + expect(readWorkspaceFileDragSource(dragRow(renderRow(undefined)))).toBeNull() + testState.executionHostId = 'runtime:unresolved-owner' + expect(readWorkspaceFileDragSource(dragRow(renderRow('wt-1')))).toBeNull() + }) +}) diff --git a/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-row.tsx b/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-row.tsx index dfb417e2518..fe6d5644db1 100644 --- a/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-row.tsx +++ b/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-row.tsx @@ -6,6 +6,7 @@ import { getFileTypeIcon } from '@/lib/file-type-icons' import { basename, dirname, joinPath } from '@/lib/path' import { cn } from '@/lib/utils' import { WORKSPACE_FILE_PATH_MIME } from '@/lib/workspace-file-drag' +import { writeWorkspaceFileDragSourceForWorkspace } from '@/lib/workspace-file-drag-source' import type { GitBranchChangeEntry } from '../../../../../../shared/git-diff-compare-types' import type { GitFileStatus, @@ -35,6 +36,7 @@ export const CombinedDiffFileTreeRow = memo(function CombinedDiffFileTreeRow({ node, mode, worktreePath, + sourceWorkspaceId, activeSectionKey, sectionIndexByKey, isCollapsed, @@ -45,6 +47,7 @@ export const CombinedDiffFileTreeRow = memo(function CombinedDiffFileTreeRow({ node: CombinedDiffTreeNode mode: CombinedDiffFileTreeMode worktreePath: string + sourceWorkspaceId?: string activeSectionKey: string | null sectionIndexByKey: ReadonlyMap isCollapsed: boolean @@ -62,6 +65,9 @@ export const CombinedDiffFileTreeRow = memo(function CombinedDiffFileTreeRow({ draggable onDragStart={(event) => { event.dataTransfer.setData(WORKSPACE_FILE_PATH_MIME, joinPath(worktreePath, node.path)) + if (sourceWorkspaceId) { + writeWorkspaceFileDragSourceForWorkspace(event.dataTransfer, sourceWorkspaceId) + } event.dataTransfer.effectAllowed = 'copy' }} > @@ -117,6 +123,9 @@ export const CombinedDiffFileTreeRow = memo(function CombinedDiffFileTreeRow({ WORKSPACE_FILE_PATH_MIME, joinPath(worktreePath, node.entry.path) ) + if (sourceWorkspaceId) { + writeWorkspaceFileDragSourceForWorkspace(event.dataTransfer, sourceWorkspaceId) + } event.dataTransfer.effectAllowed = 'copy' }} onClick={() => onNavigate(node.entry)} diff --git a/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-rows.tsx b/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-rows.tsx index 229f9561ac0..3b5abc6113c 100644 --- a/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-rows.tsx +++ b/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree-rows.tsx @@ -19,6 +19,7 @@ export function CombinedDiffFileTreeRows({ rows, mode, worktreePath, + sourceWorkspaceId, activeSectionKey, sectionIndexByKey, collapsedDirectoryKeys, @@ -30,6 +31,7 @@ export function CombinedDiffFileTreeRows({ rows: readonly CombinedDiffTreeNode[] mode: CombinedDiffFileTreeMode worktreePath: string + sourceWorkspaceId?: string activeSectionKey: string | null sectionIndexByKey: ReadonlyMap collapsedDirectoryKeys: ReadonlySet @@ -50,6 +52,7 @@ export function CombinedDiffFileTreeRows({ node={node} mode={mode} worktreePath={worktreePath} + sourceWorkspaceId={sourceWorkspaceId} activeSectionKey={activeSectionKey} sectionIndexByKey={sectionIndexByKey} isCollapsed={collapsedDirectoryKeys.has(node.key)} diff --git a/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree.tsx b/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree.tsx index 304aca3d19c..6c19b55d527 100644 --- a/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree.tsx +++ b/src/renderer/src/components/editor/combined-diff/browse-files/combined-diff-file-tree.tsx @@ -36,6 +36,7 @@ const EMPTY_TREE_ROWS: CombinedDiffTreeNode[] = [] export function CombinedDiffFileTree({ mode, worktreePath, + sourceWorkspaceId, entries, sectionIndexByKey, activeSectionKey, @@ -46,6 +47,7 @@ export function CombinedDiffFileTree({ }: { mode: CombinedDiffFileTreeMode worktreePath: string + sourceWorkspaceId?: string entries: readonly CombinedDiffFileTreeEntry[] sectionIndexByKey: ReadonlyMap activeSectionKey: string | null @@ -200,6 +202,7 @@ export function CombinedDiffFileTree({ const sharedRowProps = { mode, worktreePath, + sourceWorkspaceId, activeSectionKey, sectionIndexByKey, collapsedDirectoryKeys, diff --git a/src/renderer/src/components/native-chat/NativeChatComposer.tsx b/src/renderer/src/components/native-chat/NativeChatComposer.tsx index 4833f89fc94..fb0d533a36e 100644 --- a/src/renderer/src/components/native-chat/NativeChatComposer.tsx +++ b/src/renderer/src/components/native-chat/NativeChatComposer.tsx @@ -33,6 +33,7 @@ import { useNativeChatPtyComposerSend } from './use-native-chat-pty-composer-sen import { useNativeChatStructuredComposerSend } from './use-native-chat-structured-composer-send' import { useImeEnterGestureOwnership } from '@/lib/ime-composition-keyboard-event' import { useNativeChatComposerAppMenuSelection } from './use-native-chat-composer-app-menu-selection' +import { useNativeChatWorkspaceFileDrop } from './use-native-chat-workspace-file-drop' export type { NativeChatComposerHandle, @@ -173,6 +174,14 @@ const NativeChatComposerPane = forwardRef attachment.pending) diff --git a/src/renderer/src/components/native-chat/NativeChatPaneFileDropSurface.tsx b/src/renderer/src/components/native-chat/NativeChatPaneFileDropSurface.tsx new file mode 100644 index 00000000000..93c862b618f --- /dev/null +++ b/src/renderer/src/components/native-chat/NativeChatPaneFileDropSurface.tsx @@ -0,0 +1,120 @@ +import { createContext, useContext, useLayoutEffect, useMemo, useRef, useState } from 'react' +import { Paperclip } from 'lucide-react' +import { translate } from '@/i18n/i18n' +import { NATIVE_FILE_DROP_TARGET } from '../../../../shared/native-file-drop' +import { + makeNativeChatPaneFileDropHandlers, + type NativeChatPaneDropClaim +} from './native-chat-pane-file-drop' + +/** A mounted composer's live drop claim. The getter is what the surface reads at + * event time, so a guarded composer answers for the drag in front of it. */ +export type NativeChatPaneDropRegistration = { + getClaim: () => NativeChatPaneDropClaim + scopeKey: string +} + +type RegisterPaneDropClaim = (registration: NativeChatPaneDropRegistration) => () => void + +const NativeChatPaneFileDropContext = createContext(null) + +/** + * Publishes the composer's drop claim to the pane around it, so the whole chat + * pane — not just the input box — is the target a file can be dropped on. + */ +export function useNativeChatPaneFileDropClaim(claim: NativeChatPaneDropClaim): void { + const register = useContext(NativeChatPaneFileDropContext) + const claimRef = useRef(claim) + useLayoutEffect(() => { + claimRef.current = claim + }) + const { scopeKey, disabled } = claim + const registration = useMemo( + () => ({ getClaim: () => claimRef.current, scopeKey }), + [scopeKey] + ) + // A guard transition ends the current hover before the next paint. + useLayoutEffect(() => register?.(registration), [disabled, register, registration]) +} + +export function NativeChatPaneFileDropSurface({ + className, + children +}: { + className: string + children: React.ReactNode +}): React.JSX.Element { + const [registration, setRegistration] = useState(null) + const [isDragActive, setIsDragActive] = useState(false) + const register = useMemo( + () => (next) => { + setRegistration(next) + return () => { + setRegistration((current) => (current === next ? null : current)) + setIsDragActive(false) + } + }, + [] + ) + const handlers = useMemo( + () => + makeNativeChatPaneFileDropHandlers({ + getClaim: () => registration?.getClaim() ?? null, + setDragActive: setIsDragActive + }), + [registration] + ) + // Subscribe before hover renders: preload can consume a drop before that commit. + useLayoutEffect(() => { + if (!registration) { + return + } + const clear = (): void => setIsDragActive(false) + document.addEventListener('drop', clear, true) + document.addEventListener('dragend', clear, true) + return () => { + document.removeEventListener('drop', clear, true) + document.removeEventListener('dragend', clear, true) + } + }, [registration]) + + return ( + +
+ {children} + {isDragActive ? : null} +
+ + ) +} + +function NativeChatPaneFileDropOverlay(): React.JSX.Element { + return ( +
+
+ + + + + {translate('components.native-chat.drop.title', 'Drop to attach to this chat')} + + + {translate( + 'components.native-chat.drop.subtitle', + 'Files are added to your message as paths the agent can read.' + )} + +
+
+ ) +} diff --git a/src/renderer/src/components/native-chat/NativeChatSessionOptionPickers.test.tsx b/src/renderer/src/components/native-chat/NativeChatSessionOptionPickers.test.tsx index fb9292517e3..cb777f910f2 100644 --- a/src/renderer/src/components/native-chat/NativeChatSessionOptionPickers.test.tsx +++ b/src/renderer/src/components/native-chat/NativeChatSessionOptionPickers.test.tsx @@ -69,12 +69,21 @@ vi.mock('@/components/ui/dropdown-menu', () => { ), DropdownMenuLabel: ({ children }: { children: React.ReactNode }) =>
{children}
, DropdownMenuSeparator: () =>
, + // Forwards role/aria-* and hands onSelect an event: the switch rows set both, + // and preventDefault is how a toggle keeps the menu open. DropdownMenuItem: ({ children, disabled, - onSelect - }: React.ButtonHTMLAttributes & { onSelect?: () => void }) => ( - ), @@ -83,14 +92,17 @@ vi.mock('@/components/ui/dropdown-menu', () => { DropdownMenuRadioGroup: ({ children, value, - onValueChange + onValueChange, + 'aria-label': ariaLabel }: { children: React.ReactNode value?: string onValueChange?: (value: string) => void + 'aria-label'?: string }) => (
@@ -171,23 +183,29 @@ function model(overrides: Partial = {}): SessionOptionD } } +const EFFORT_CHOICES = [ + { value: 'low', label: 'Low' }, + { value: 'high', label: 'High' } +] + const effort: SessionOptionDescriptor = { id: 'effort', label: 'Effort', category: 'thought_level', - kind: { - type: 'select', - currentValue: 'high', - choices: [ - { value: 'low', label: 'Low' }, - { value: 'high', label: 'High' } - ] - }, + kind: { type: 'select', currentValue: 'high', choices: EFFORT_CHOICES }, valueSource: 'applied', transport: 'catalog', settable: true } +/** A select with nothing picked. Only a select can be in this shape: it renders + * "nothing selected" truthfully, which is why the boolean kind requires a value. */ +const unknownEffort: SessionOptionDescriptor = { + ...effort, + kind: { type: 'select', choices: EFFORT_CHOICES }, + valueSource: 'unknown' +} + const fast: SessionOptionDescriptor = { id: 'fastMode', label: 'Fast mode', @@ -295,10 +313,7 @@ describe('NativeChatSessionOptionPickers', () => { render( ) @@ -331,7 +346,7 @@ describe('NativeChatSessionOptionPickers', () => { kind: { type: 'select', choices: [] }, valueSource: 'unknown' }), - { ...effort, kind: { ...effort.kind, currentValue: undefined }, valueSource: 'unknown' } + unknownEffort ]} isWorking={false} /> @@ -437,7 +452,7 @@ describe('NativeChatSessionOptionPickers', () => { model(), { ...fast, - kind: { type: 'boolean' }, + kind: { type: 'boolean', currentValue: false }, valueSource: 'unknown', action: { type: 'toggle-command' } } @@ -453,7 +468,7 @@ describe('NativeChatSessionOptionPickers', () => { expect(setOption).not.toHaveBeenCalled() }) - it('uses On/Off radios for known boolean options without inventing a selection', async () => { + it('uses one switch row for a boolean option without inventing a selection', async () => { const setOption = vi.fn().mockResolvedValue({ snapshot: [] }) const liveSurface = { ...surface, setOption } const { rerender } = render( @@ -472,13 +487,17 @@ describe('NativeChatSessionOptionPickers', () => { /> ) expect(screen.queryByText('Toggle fast mode')).toBeNull() - const onRadio = screen.getByRole('radio', { name: 'On' }) - expect(onRadio.getAttribute('data-state')).toBe('checked') - expect(onRadio.getAttribute('aria-checked')).toBe('true') - const fastGroup = onRadio.parentElement - expect(fastGroup?.getAttribute('data-radio-value')).toBe('on') - expect(fastGroup?.getAttribute('data-on-value-change')).toBe('1') - screen.getByRole('radio', { name: 'Off' }).click() + // One control, not an On/Off pair, and the row carries the label itself. + expect(screen.queryByRole('radio', { name: 'On' })).toBeNull() + expect(screen.queryByRole('radio', { name: 'Off' })).toBeNull() + const fastSwitch = screen.getByRole('switch', { name: 'Fast mode' }) + expect(fastSwitch.getAttribute('aria-checked')).toBe('true') + expect( + fastSwitch.querySelector('[data-slot="switch-indicator"]')?.getAttribute('data-state') + ).toBe('checked') + // The label is not duplicated by a separate group header. + expect(screen.getAllByText('Fast mode')).toHaveLength(1) + fastSwitch.click() await waitFor(() => expect(setOption).toHaveBeenCalledWith('fastMode', false)) setOption.mockClear() @@ -491,7 +510,9 @@ describe('NativeChatSessionOptionPickers', () => { id: 'thinking', label: 'Thinking', category: 'mode', - kind: { type: 'boolean' }, + // What the producer now emits for an unreported `thinking`: the + // catalog default, with provenance still saying nothing confirmed it. + kind: { type: 'boolean', currentValue: true }, valueSource: 'unknown', transport: 'catalog', settable: true @@ -500,14 +521,66 @@ describe('NativeChatSessionOptionPickers', () => { isWorking={false} /> ) - // Unknown composed boolean: hint + radios present, nothing pre-selected. - expect(screen.getByText('Current value unknown — pick On or Off')).not.toBeNull() - const thinkingGroup = screen.getByRole('radio', { name: 'On' }).parentElement - expect(thinkingGroup?.getAttribute('data-radio-value')).toBe('') - screen.getByRole('radio', { name: 'Off' }).click() + // The producer resolves the value, so the row renders it instead of a caption + // apologising for a switch that had already collapsed to off. + expect(screen.queryByText('Current value unknown')).toBeNull() + const thinkingSwitch = screen.getByRole('switch', { name: 'Thinking' }) + expect(thinkingSwitch.getAttribute('aria-checked')).toBe('true') + thinkingSwitch.click() await waitFor(() => expect(setOption).toHaveBeenCalledWith('thinking', false)) }) + // Both arms: `default` and `unreported` make opposite claims, and only + // `unreported` is reachable in the structured lane, so one arm proves nothing. + it.each([ + { + name: 'a live unreported boolean is never labelled a default', + valueSource: 'unknown', + transport: 'agent-session', + shown: 'Not reported', + hidden: 'Default' + }, + { + name: 'a draft catalog default says so', + valueSource: 'default', + transport: 'catalog', + shown: 'Default', + hidden: 'Not reported' + } + ] as const)('$name', ({ valueSource, transport, shown, hidden }) => { + render( + + ) + expect(screen.getAllByText(shown).length).toBeGreaterThan(0) + expect(screen.queryByText(hidden)).toBeNull() + // The marker qualifies the value; it must not become part of the control's name. + const control = screen.getByRole('switch', { name: 'Fast mode' }) + // ...but it must still reach assistive tech: hiding it would leave screen + // reader users unable to tell a default from an unreported value at all. + const describedBy = control.getAttribute('aria-describedby') ?? '' + expect(describedBy).not.toBe('') + expect(document.getElementById(describedBy)?.textContent).toBe(shown) + }) + + it('drops the marker once something has picked the value', () => { + render( + + ) + expect(screen.queryByText('Default')).toBeNull() + expect(screen.queryByText('Not reported')).toBeNull() + }) + it('tooltips a dispatched option pill with the category alone', () => { render( ) } - // Why: absolute On/Off only when we have tracked truth. Unknown composed - // booleans leave the group unselected so empty radios are not a selection. + // Why one switch row and not On/Off: the option is binary, so a single control + // carries it. The row owns the label, which is why the caller drops its header. + // The value always renders; the marker is what keeps an unpicked one from + // reading as confirmed, since the switch itself cannot say "nobody said". if (descriptor.kind.type === 'boolean') { - const selected = - descriptor.kind.currentValue === true - ? 'on' - : descriptor.kind.currentValue === false - ? 'off' - : undefined + const checked = descriptor.kind.currentValue + const label = nativeChatSessionOptionLabel(descriptor) + const marker = sessionOptionValueMarker(descriptor) + const markerId = `session-option-marker-${descriptor.id}` return ( - <> - {selected === undefined ? ( - - {translate( - 'components.native-chat.composer.valueUnknown', - 'Current value unknown — pick On or Off' - )} - - ) : null} - setValue(next === 'on')}> - - {translate('components.native-chat.composer.optionValue.on', 'On')} - - - {translate('components.native-chat.composer.optionValue.off', 'Off')} - - - + { + event.preventDefault() + setValue(!checked) + }} + className="justify-between gap-2" + > + {label} + + {marker ? ( + + {marker === 'default' + ? translate('components.native-chat.composer.valueIsDefault', 'Default') + : translate('components.native-chat.composer.valueNotReported', 'Not reported')} + + ) : null} + + + ) } return ( setValue(value)} > @@ -282,7 +295,11 @@ function NativeChatSessionOptionPickersInner({ return (
{index > 0 ? : null} - {nativeChatSessionOptionLabel(descriptor)} + {descriptor.kind.type === 'boolean' && !descriptor.action ? null : ( + + {nativeChatSessionOptionLabel(descriptor)} + + )} {reason && !descriptor.settable ? ( {reason} ) : null} diff --git a/src/renderer/src/components/native-chat/NativeChatView.tsx b/src/renderer/src/components/native-chat/NativeChatView.tsx index 15c04823542..d17de41a854 100644 --- a/src/renderer/src/components/native-chat/NativeChatView.tsx +++ b/src/renderer/src/components/native-chat/NativeChatView.tsx @@ -3,15 +3,21 @@ import { NativeChatStructuredSession } from './NativeChatStructuredSession' import { NativeChatResolvedView } from './NativeChatResolvedView' import { useNativeChatStatusEntry } from './use-native-chat-status-entry' import type { NativeChatViewProps } from './native-chat-view-types' +import { NativeChatPaneFileDropSurface } from './NativeChatPaneFileDropSurface' export type { NativeChatViewProps } from './native-chat-view-types' /** Resolves an agent terminal into its native conversation and composer UI. */ export default function NativeChatView(props: NativeChatViewProps): React.JSX.Element { - if (props.mode === 'structured') { - return - } - return + return ( + + {props.mode === 'structured' ? ( + + ) : ( + + )} + + ) } function NativeChatBridgeView({ diff --git a/src/renderer/src/components/native-chat/native-chat-attachment-upload.test.ts b/src/renderer/src/components/native-chat/native-chat-attachment-upload.test.ts index e90b7edcb44..c477f343ca2 100644 --- a/src/renderer/src/components/native-chat/native-chat-attachment-upload.test.ts +++ b/src/renderer/src/components/native-chat/native-chat-attachment-upload.test.ts @@ -140,6 +140,18 @@ describe('resolveNativeChatAttachmentOwner', () => { }) }) + it('reports not-ready instead of throwing when the SSH generation is gone', () => { + expect( + resolveNativeChatAttachmentOwner( + state({ + repos: [{ id: 'repo', connectionId: 'conn-1' }] as never, + sshConnectionStates: new Map() + }), + 'tab-1' + ) + ).toEqual({ kind: 'not-ready' }) + }) + it('reports not-ready when an SSH worktree has no known path yet', () => { expect( resolveNativeChatAttachmentOwner( diff --git a/src/renderer/src/components/native-chat/native-chat-attachment-upload.ts b/src/renderer/src/components/native-chat/native-chat-attachment-upload.ts index 8157a5190ff..b7564ba7d9c 100644 --- a/src/renderer/src/components/native-chat/native-chat-attachment-upload.ts +++ b/src/renderer/src/components/native-chat/native-chat-attachment-upload.ts @@ -82,11 +82,17 @@ export function resolveNativeChatAttachmentOwnerForWorktree( if (!worktreePath) { return { kind: 'not-ready' } } - return { - kind: 'ssh', - connectionId, - worktreePath, - ...captureDirectSshMutationExpectation(state, connectionId) + try { + return { + kind: 'ssh', + connectionId, + worktreePath, + ...captureDirectSshMutationExpectation(state, connectionId) + } + } catch { + // The connection's generation is gone (disconnect mid-attach). That is an + // unknown owner, not a reason to throw out of the drop/IME handler. + return { kind: 'not-ready' } } } @@ -97,6 +103,20 @@ export function nativeChatWorktreeNotReadyNotice(): string { ) } +export function nativeChatAttachmentOwnerChangedNotice(): string { + return translate( + 'components.native-chat.composer.attachmentOwnerChanged', + 'This workspace changed hosts while attaching — drop the files again.' + ) +} + +export function nativeChatAttachmentUnreadableNotice(): string { + return translate( + 'components.native-chat.composer.attachmentUnreadable', + "Couldn't read the dropped files." + ) +} + export function nativeChatLocalAttachmentUnsupportedNotice(): string { return translate( 'components.native-chat.composer.localAttachmentUnsupported', diff --git a/src/renderer/src/components/native-chat/native-chat-composer-drop-scope.test.tsx b/src/renderer/src/components/native-chat/native-chat-composer-drop-scope.test.tsx index e535a59fad0..c7c7dec050c 100644 --- a/src/renderer/src/components/native-chat/native-chat-composer-drop-scope.test.tsx +++ b/src/renderer/src/components/native-chat/native-chat-composer-drop-scope.test.tsx @@ -3,7 +3,10 @@ import { EventEmitter } from 'node:events' import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' import { act, cleanup, render, screen } from '@testing-library/react' -import { useRef } from 'react' +import { useRef, useState } from 'react' +import type * as AttachmentUploadModule from './native-chat-attachment-upload' +import type { NativeChatComposerInput } from './native-chat-composer-input' +import { NativeChatPromptEditor } from './NativeChatPromptEditor' import { useNativeChatExternalAttachments } from './use-native-chat-external-attachments' import { NativeChatImageAttachmentPreview } from './NativeChatImageAttachmentPreview' import { resetLocalImageSrcStateForTests } from '../editor/useLocalImageSrc' @@ -30,7 +33,9 @@ const intake = vi.hoisted(() => ({ upload: vi.fn() })) vi.mock('@/store', () => ({ useAppStore: { getState: () => ({}) } })) -vi.mock('./native-chat-attachment-upload', () => ({ +// Keeps the real notice strings so the silent-failure guards assert what users see. +vi.mock('./native-chat-attachment-upload', async (importOriginal) => ({ + ...(await importOriginal()), resolveNativeChatAttachmentOwner: () => intake.owner, uploadNativeChatAttachmentPaths: intake.upload })) @@ -49,7 +54,8 @@ import { // Uses the production drop listener, subscriber fan-out, attachment hook, and scope cache. function ComposerProbe({ pane, hidden = false }: { pane: string; hidden?: boolean }) { - const textareaRef = useRef(null) + const textareaRef = useRef(null) + const [notice, setNotice] = useState(null) const attachments = useNativeChatComposerAttachments({ attachmentScopeKey: pane, allowWithoutTarget: true, @@ -60,22 +66,28 @@ function ComposerProbe({ pane, hidden = false }: { pane: string; hidden?: boolea textareaRef, setCaret: () => {}, setDraft: () => {}, - setNotice: () => {} + setNotice }) const { attachExternalPaths } = useNativeChatExternalAttachments({ terminalTabId: pane, disabled: false, attachResolvedPaths: attachments.attachResolvedPaths, - setNotice: () => {} + setNotice }) useNativeChatFileAttachmentActions(pane, attachExternalPaths) return (