Merge main while retaining SQL chat readers
@@ -29,7 +29,6 @@ on:
|
||||
- 'src/main/codex-usage/scanner-incremental-append.test.ts'
|
||||
- 'src/main/usage/jsonl-file-reader.test.ts'
|
||||
- 'src/main/usage/jsonl-file-snapshot.test.ts'
|
||||
- 'src/renderer/src/lib/pane-manager/pane-terminal-output-scheduler-queue-retention.test.ts'
|
||||
- 'src/main/claude-usage/scanner-incremental-append.test.ts'
|
||||
- 'src/main/claude-usage/store-checkpoint-persistence.test.ts'
|
||||
|
||||
|
||||
@@ -512,6 +512,10 @@ jobs:
|
||||
if: needs.code_paths.outputs.static_analysis == 'true'
|
||||
run: bun config/scripts/localization/source-extraction/audit-localization-coverage.mjs --check
|
||||
|
||||
- name: Verify startup and worktree localization coverage
|
||||
if: needs.code_paths.outputs.static_analysis == 'true'
|
||||
run: bun run verify:startup-worktree-localization-coverage
|
||||
|
||||
- name: Verify mobile localization
|
||||
if: needs.code_paths.outputs.static_analysis == 'true'
|
||||
run: bun config/scripts/localization/catalog-validation/verify-mobile-localization.mjs
|
||||
|
||||
@@ -121,6 +121,9 @@ validation-screenshots/
|
||||
test-results/
|
||||
playwright-report/
|
||||
|
||||
# Claude Code settings are machine-local.
|
||||
**/.claude/settings.local.json
|
||||
|
||||
# Agent skills are installed per machine.
|
||||
/.claude/skills/
|
||||
/.agents/skills/
|
||||
|
||||
@@ -292,11 +292,9 @@ Pair with your desktop app to monitor and steer your agents from your phone.
|
||||
|
||||
- **Discord:** Join the community on **[Discord](https://discord.gg/fzjDKHxv8Q)**.
|
||||
- **Twitter / X:** Follow **[@orca_build](https://x.com/orca_build)** for updates and announcements.
|
||||
- **WeChat:** Scan to join an Orca community WeChat group. If one group is full, join another.
|
||||
- **WeChat:** Scan to join an Orca community WeChat group.
|
||||
|
||||
<img src="docs/assets/wechat-qr-group14.jpg" alt="WeChat QR code for the Orca community" width="160" />
|
||||
<img src="docs/assets/wechat-qr-group15.jpg" alt="WeChat QR code for the Orca community" width="160" />
|
||||
<img src="docs/assets/wechat-qr-group16.jpg" alt="WeChat QR code for the Orca community" width="160" />
|
||||
<img src="docs/assets/wechat-qr.jpg" alt="WeChat QR code for the Orca community" width="160" />
|
||||
|
||||
- **Feedback & Ideas:** We ship fast. Missing something? [Request a new feature](https://github.com/stablyai/orca/issues).
|
||||
- **Privacy:** See the [privacy & telemetry docs](https://www.onorca.dev/docs/telemetry) for what anonymous usage data Orca collects and how to opt out.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Later run-all.ts checks against the same host: rebind, orphan grace, silence,
|
||||
// forced resets and pre-upgrade refusals.
|
||||
// forced resets.
|
||||
import WebSocket from 'ws'
|
||||
import { GRACE_MS, ORIGIN, PING_MS, PORT, SILENCE_MS, makeControl, openPhone, record, sleep, waitFor, type Ctx, type Control } from './run-all-harness'
|
||||
|
||||
@@ -89,12 +89,4 @@ export async function runLifecycleChecks(ctx: Ctx, main: Control, mainAck: Ack):
|
||||
back.client.closeNow()
|
||||
}
|
||||
|
||||
// Bad JWT -> 401 before upgrade; malformed host id -> 429.
|
||||
{
|
||||
const bad = new WebSocket(`ws://127.0.0.1:${PORT}/v1/host/control`, { headers: { authorization: 'Bearer nope' } })
|
||||
const status = await new Promise<number>((res) => bad.on('unexpected-response', (_q, r) => res(r.statusCode ?? 0)))
|
||||
const badHost = new WebSocket(`ws://127.0.0.1:${PORT}/v1/connect/short`)
|
||||
const s2 = await new Promise<number>((res) => badHost.on('unexpected-response', (_q, r) => res(r.statusCode ?? 0)))
|
||||
record('R11/R5 ES256 JWKS rejects bad token (401); malformed host id 429', status === 401 && s2 === 429, `${status},${s2}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,11 +100,6 @@ async function runTests(ctx: Ctx): Promise<void> {
|
||||
const mainAck = await main.client.connect()
|
||||
const transport = main.bindTransport(mainAck.generation)
|
||||
|
||||
// Alarm-driven app ping, answered by the shipped client's pong handler.
|
||||
await sleep(PING_MS * 3 + 300)
|
||||
record('R2/R5 alarm-driven JSON ping parsed by shipped client, pong keeps control alive',
|
||||
main.events.pings >= 2 && main.client.isLive(), `pings=${main.events.pings} live=${main.client.isLive()}`)
|
||||
|
||||
// Phone connect -> conn-open (strict, shipped parser) -> host data -> relay-hello (shipped parser).
|
||||
const phone = openPhone(ctx)
|
||||
const helloOk = await waitFor(() => phone.hello !== null, 5000)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
id: claude-chat-entrypoint-callers
|
||||
snapshots:
|
||||
"import { withOrcaClaudeChatEntrypoint as stamp } from './claude-chat-entrypoint'":
|
||||
labels:
|
||||
- source: withOrcaClaudeChatEntrypoint
|
||||
style: primary
|
||||
start: 9
|
||||
end: 37
|
||||
'withOrcaClaudeChatEntrypoint(env, platform)':
|
||||
labels:
|
||||
- source: withOrcaClaudeChatEntrypoint
|
||||
style: primary
|
||||
start: 0
|
||||
end: 28
|
||||
@@ -0,0 +1,20 @@
|
||||
id: claude-chat-entrypoint-owner
|
||||
snapshots:
|
||||
"const env = { CLAUDE_CODE_ENTRYPOINT: 'orca' }":
|
||||
labels:
|
||||
- source: CLAUDE_CODE_ENTRYPOINT
|
||||
style: primary
|
||||
start: 14
|
||||
end: 36
|
||||
const identity = 'sdk-cli':
|
||||
labels:
|
||||
- source: sdk-cli
|
||||
style: primary
|
||||
start: 18
|
||||
end: 25
|
||||
"env['claude_code_entrypoint'] = 'other'":
|
||||
labels:
|
||||
- source: claude_code_entrypoint
|
||||
style: primary
|
||||
start: 5
|
||||
end: 27
|
||||
@@ -0,0 +1,14 @@
|
||||
id: claude-entrypoint-key-owner
|
||||
snapshots:
|
||||
"env[CLAUDE_ENTRYPOINT_ENV] = 'orca'":
|
||||
labels:
|
||||
- source: CLAUDE_ENTRYPOINT_ENV
|
||||
style: primary
|
||||
start: 4
|
||||
end: 25
|
||||
"import { CLAUDE_ENTRYPOINT_ENV as key } from './claude-chat-entrypoint'":
|
||||
labels:
|
||||
- source: CLAUDE_ENTRYPOINT_ENV
|
||||
style: primary
|
||||
start: 9
|
||||
end: 30
|
||||
@@ -0,0 +1,6 @@
|
||||
id: claude-chat-entrypoint-callers
|
||||
valid:
|
||||
- 'stripInheritedClaudeSessionEnv(env)'
|
||||
invalid:
|
||||
- 'withOrcaClaudeChatEntrypoint(env, platform)'
|
||||
- "import { withOrcaClaudeChatEntrypoint as stamp } from './claude-chat-entrypoint'"
|
||||
@@ -0,0 +1,8 @@
|
||||
id: claude-chat-entrypoint-owner
|
||||
valid:
|
||||
- 'const env = withOrcaClaudeChatEntrypoint(configured, platform)'
|
||||
- "const binary = 'orca'"
|
||||
invalid:
|
||||
- "const env = { CLAUDE_CODE_ENTRYPOINT: 'orca' }"
|
||||
- "env['claude_code_entrypoint'] = 'other'"
|
||||
- "const identity = 'sdk-cli'"
|
||||
@@ -0,0 +1,6 @@
|
||||
id: claude-entrypoint-key-owner
|
||||
valid:
|
||||
- "const binary = 'orca'"
|
||||
invalid:
|
||||
- "env[CLAUDE_ENTRYPOINT_ENV] = 'orca'"
|
||||
- "import { CLAUDE_ENTRYPOINT_ENV as key } from './claude-chat-entrypoint'"
|
||||
@@ -0,0 +1,117 @@
|
||||
id: claude-chat-entrypoint-owner
|
||||
language: typescript
|
||||
severity: error
|
||||
message: Keep the Claude identity literal in claude-chat-entrypoint.ts.
|
||||
files: ['src/**']
|
||||
ignores:
|
||||
- '**/*.test.*'
|
||||
- '**/*.test-fixtures.*'
|
||||
- '**/__fixtures__/**'
|
||||
- 'src/shared/agent-launch/startup/claude-chat-entrypoint.ts'
|
||||
rule:
|
||||
all:
|
||||
- any:
|
||||
- kind: string_fragment
|
||||
- kind: property_identifier
|
||||
- kind: identifier
|
||||
- regex: '(?i)^(CLAUDE_CODE_ENTRYPOINT|sdk-cli)$'
|
||||
---
|
||||
id: claude-chat-entrypoint-owner-tsx
|
||||
language: tsx
|
||||
severity: error
|
||||
message: Keep the Claude identity literal in claude-chat-entrypoint.ts.
|
||||
files: ['src/**']
|
||||
ignores:
|
||||
- '**/*.test.*'
|
||||
- '**/*.test-fixtures.*'
|
||||
- '**/__fixtures__/**'
|
||||
- 'src/shared/agent-launch/startup/claude-chat-entrypoint.ts'
|
||||
rule:
|
||||
all:
|
||||
- any:
|
||||
- kind: string_fragment
|
||||
- kind: property_identifier
|
||||
- kind: identifier
|
||||
- regex: '(?i)^(CLAUDE_CODE_ENTRYPOINT|sdk-cli)$'
|
||||
---
|
||||
id: claude-chat-entrypoint-callers
|
||||
language: typescript
|
||||
severity: error
|
||||
message: Only structured native chat and its own probes may apply the chat identity.
|
||||
files: ['src/**']
|
||||
ignores:
|
||||
- '**/*.test.*'
|
||||
- '**/*.test-fixtures.*'
|
||||
- '**/__fixtures__/**'
|
||||
- 'src/shared/agent-launch/startup/claude-chat-entrypoint.ts'
|
||||
- 'src/main/claude/claude-stream-json-connection.ts'
|
||||
- 'src/main/claude/claude-agent-sdk-process-spawn.ts'
|
||||
- 'src/main/claude/structured/launch/claude-structured-child-env.ts'
|
||||
- 'src/main/claude/claude-model-catalog-probe.ts'
|
||||
rule:
|
||||
all:
|
||||
- any:
|
||||
- kind: string_fragment
|
||||
- kind: property_identifier
|
||||
- kind: identifier
|
||||
- regex: '^withOrcaClaudeChatEntrypoint$'
|
||||
---
|
||||
id: claude-chat-entrypoint-callers-tsx
|
||||
language: tsx
|
||||
severity: error
|
||||
message: Only structured native chat and its own probes may apply the chat identity.
|
||||
files: ['src/**']
|
||||
ignores:
|
||||
- '**/*.test.*'
|
||||
- '**/*.test-fixtures.*'
|
||||
- '**/__fixtures__/**'
|
||||
- 'src/shared/agent-launch/startup/claude-chat-entrypoint.ts'
|
||||
- 'src/main/claude/claude-stream-json-connection.ts'
|
||||
- 'src/main/claude/claude-agent-sdk-process-spawn.ts'
|
||||
- 'src/main/claude/structured/launch/claude-structured-child-env.ts'
|
||||
- 'src/main/claude/claude-model-catalog-probe.ts'
|
||||
rule:
|
||||
all:
|
||||
- any:
|
||||
- kind: string_fragment
|
||||
- kind: property_identifier
|
||||
- kind: identifier
|
||||
- regex: '^withOrcaClaudeChatEntrypoint$'
|
||||
---
|
||||
id: claude-entrypoint-key-owner
|
||||
language: typescript
|
||||
severity: error
|
||||
message: Only the chat identity owner and inherited-session isolation may access this key directly.
|
||||
files: ['src/**']
|
||||
ignores:
|
||||
- '**/*.test.*'
|
||||
- '**/*.test-fixtures.*'
|
||||
- '**/__fixtures__/**'
|
||||
- 'src/shared/agent-launch/startup/claude-chat-entrypoint.ts'
|
||||
- 'src/shared/agent-launch/startup/claude-parent-session-env.ts'
|
||||
rule:
|
||||
all:
|
||||
- any:
|
||||
- kind: string_fragment
|
||||
- kind: property_identifier
|
||||
- kind: identifier
|
||||
- regex: '^CLAUDE_ENTRYPOINT_ENV$'
|
||||
---
|
||||
id: claude-entrypoint-key-owner-tsx
|
||||
language: tsx
|
||||
severity: error
|
||||
message: Only the chat identity owner and inherited-session isolation may access this key directly.
|
||||
files: ['src/**']
|
||||
ignores:
|
||||
- '**/*.test.*'
|
||||
- '**/*.test-fixtures.*'
|
||||
- '**/__fixtures__/**'
|
||||
- 'src/shared/agent-launch/startup/claude-chat-entrypoint.ts'
|
||||
- 'src/shared/agent-launch/startup/claude-parent-session-env.ts'
|
||||
rule:
|
||||
all:
|
||||
- any:
|
||||
- kind: string_fragment
|
||||
- kind: property_identifier
|
||||
- kind: identifier
|
||||
- regex: '^CLAUDE_ENTRYPOINT_ENV$'
|
||||
@@ -30,8 +30,6 @@
|
||||
3 test-no-in-test-import-actual:src/renderer/src/components/terminal-pane/snapshots/remote-snapshot-alt-screen-host-chain.test.ts
|
||||
1 test-no-in-test-import-actual:src/renderer/src/hooks/useIpcEvents-agent-status-pane-teardown.test.ts
|
||||
1 test-no-in-test-import-actual:src/renderer/src/hooks/useIpcEvents-agent-status-snapshot-hydration.test.ts
|
||||
1 test-no-in-test-import-actual:src/renderer/src/hooks/useIpcEvents-rate-limit-hydration.test.ts
|
||||
1 test-no-in-test-import-actual:src/renderer/src/lib/agent-session/launch/new-tab/agent-launch-caller-routing.test.ts
|
||||
1 test-no-polling-loop:src/main/browser/cookies/browser-cookie-import-concurrency.test.ts
|
||||
1 test-no-polling-loop:src/main/claude/claude-stop-ack-race.test.ts
|
||||
1 test-no-polling-loop:src/main/claude/claude-stream-json-connection.test.ts
|
||||
@@ -256,7 +254,6 @@
|
||||
1 test-no-real-time-wait:src/main/windows/windows-process-tree-command-line-patch.test.ts
|
||||
2 test-no-real-time-wait:src/main/windows/windows-pty-job.win32.test.ts
|
||||
1 test-no-real-time-wait:src/main/worker-thread-child-process/worker-thread-child-process.test.ts
|
||||
1 test-no-real-time-wait:src/main/workspaces/creation/preparation/worktree-create-preparation-cancellation.test.ts
|
||||
1 test-no-real-time-wait:src/main/workspaces/removal/local-worktree-removal-recovery-live.test.ts
|
||||
2 test-no-real-time-wait:src/main/wsl/execution/wsl-command-loop.test.ts
|
||||
2 test-no-real-time-wait:src/main/wsl/orcad/wsl-orcad-real-distro-lane.test.ts
|
||||
@@ -272,7 +269,6 @@
|
||||
1 test-no-real-time-wait:src/renderer/src/components/terminal-pane/viewport/terminal-fit-restore.test.ts
|
||||
1 test-no-real-time-wait:src/renderer/src/hooks/runtime-project-refresh-scheduler.test.ts
|
||||
1 test-no-real-time-wait:src/renderer/src/lib/agent-session/resume/cli-fork/native-chat-cli-fork-preparation.test.ts
|
||||
1 test-no-real-time-wait:src/renderer/src/lib/orca-yaml-trust-prompt-slot-eviction.test.ts
|
||||
2 test-no-real-time-wait:src/renderer/src/store/slices/workspace-cleanup/workspace-cleanup-removal-preflight.test.ts
|
||||
2 test-no-real-time-wait:src/shared/__tests__/process-host/windows-tree-kill-late-taskkill.win32.test.ts
|
||||
1 test-no-real-time-wait:src/shared/darwin-process-table-capture.test.ts
|
||||
@@ -637,7 +633,7 @@
|
||||
1 test-no-wall-clock:src/renderer/src/components/native-chat/session/structured/delivery/NativeChatMessageList.unsent-message.test.tsx
|
||||
3 test-no-wall-clock:src/renderer/src/components/native-chat/surfaces/integration/NativeChatMessageList.test.tsx
|
||||
2 test-no-wall-clock:src/renderer/src/components/native-chat/tools/tasks/NativeChatStructuredSessionStatus.test.tsx
|
||||
3 test-no-wall-clock:src/renderer/src/components/sidebar/workspace-card/review/use-workspace-reference-details.test.tsx
|
||||
1 test-no-wall-clock:src/renderer/src/components/sidebar/workspace-card/review/use-workspace-reference-details.test.tsx
|
||||
1 test-no-wall-clock:src/renderer/src/components/sidebar/worktree-list/listing/WorktreeList.lineage-agent-expansion-coupling.test.tsx
|
||||
2 test-no-wall-clock:src/renderer/src/components/task-page/jira/task-page-jira-cache-selectors.test.ts
|
||||
2 test-no-wall-clock:src/renderer/src/components/terminal-pane/pty-connection/emulation/fish-color-scheme-child-stdin.node-pty.test.ts
|
||||
@@ -647,13 +643,11 @@
|
||||
1 test-no-wall-clock:src/renderer/src/components/worktree-jump/WorktreeJumpPalette.recent-tabs.behavior.test.tsx
|
||||
4 test-no-wall-clock:src/renderer/src/components/worktree-jump/WorktreeJumpPalette.recent-tabs.test.tsx
|
||||
2 test-no-wall-clock:src/renderer/src/hooks/ipc-events/agent-status-terminal-title-tab-write.test.ts
|
||||
1 test-no-wall-clock:src/renderer/src/hooks/useIpcEvents-agent-status-hook-titles.test.ts
|
||||
1 test-no-wall-clock:src/renderer/src/lib/paired-runtime-closed-tab-resume.test.ts
|
||||
2 test-no-wall-clock:src/renderer/src/lib/use-tab-agent-observed-signal-dispatch.test.tsx
|
||||
2 test-no-wall-clock:src/renderer/src/lib/wake-sleeping-agents-live-unmounted-pane.test.ts
|
||||
1 test-no-wall-clock:src/renderer/src/lib/workspace/ownership/workspace-terminal-host-authority.test.ts
|
||||
1 test-no-wall-clock:src/renderer/src/lib/workspace/activation/worktree-activation-emptied-workspace-reseed.test.ts
|
||||
2 test-no-wall-clock:src/renderer/src/runtime/native-chat/tab-retirement/structured-agent-session-tab-retirement.test.ts
|
||||
2 test-no-wall-clock:src/renderer/src/store/github/pull-requests/github-pr-branch-linked-pr-divergence.test.ts
|
||||
6 test-no-wall-clock:src/renderer/src/store/slices/jira/jira.test.ts
|
||||
5 test-no-wall-clock:src/renderer/src/store/slices/worktrees/metadata/worktree-meta-hosted-review.test.ts
|
||||
@@ -677,7 +671,6 @@
|
||||
2 test-no-wall-clock:tests/e2e/cross-version-wire/release-source-retention.unit.test.ts
|
||||
1 test-no-wall-clock:tests/e2e/host-cold-park-remote-subscriber.unit.test.ts
|
||||
2 test-no-wall-clock:tests/e2e/omp-child-session-recovery.unit.test.ts
|
||||
1 test-no-wall-clock:tests/e2e/structured-session-tab-close-regressions.unit.test.ts
|
||||
2 test-timeout-needs-reason:mobile/src/terminal/document/native-document-bundle.test.ts
|
||||
1 test-timeout-needs-reason:mobile/src/test-support/rpc-recording/family-recordings.test.ts
|
||||
1 test-timeout-needs-reason:mobile/src/test-support/rpc-recording/mutants/family-mutants.test.ts
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
1 src/renderer/src/components/activity/use-agent-pane-thread-store-data.ts
|
||||
1 src/renderer/src/components/activity/use-agent-pane-threads.ts
|
||||
4 src/renderer/src/components/agent/AgentSettingsDialog.tsx
|
||||
1 src/renderer/src/components/automations/automation-host-client.ts
|
||||
1 src/renderer/src/components/automations/hosts/automation-host-client.ts
|
||||
1 src/renderer/src/components/automations/automations-page-fixtures.ts
|
||||
1 src/renderer/src/components/automations/use-automations-page-controller.ts
|
||||
1 src/renderer/src/components/automations/use-automations-page-destination-form.ts
|
||||
1 src/renderer/src/components/automations/authoring/use-automations-page-destination-form.ts
|
||||
1 src/renderer/src/components/browser-pane/ReopenBrowserPageOnServerButton.tsx
|
||||
1 src/renderer/src/components/browser-pane/browser-reopen-on-server.ts
|
||||
1 src/renderer/src/components/browser-pane/stream-remote/use-remote-browser-page-stream.ts
|
||||
@@ -204,11 +204,11 @@
|
||||
1 src/renderer/src/hooks/ipc-events/runtime-environment-subscription-selection.ts
|
||||
1 src/renderer/src/hooks/ipc-events/settings-sidebar-ipc-bridge.ts
|
||||
1 src/renderer/src/hooks/ipc-events/terminal-request-ipc-bridge.ts
|
||||
1 src/renderer/src/hooks/use-active-skill-discovery-runtime-target.ts
|
||||
1 src/renderer/src/hooks/skills/discovery/use-active-skill-discovery-runtime-target.ts
|
||||
2 src/renderer/src/hooks/use-integration-provider-status-refresh.ts
|
||||
1 src/renderer/src/hooks/useActiveProjectSkillRuntime.ts
|
||||
1 src/renderer/src/hooks/skills/runtime/useActiveProjectSkillRuntime.ts
|
||||
1 src/renderer/src/hooks/useEditorExternalWatch.ts
|
||||
1 src/renderer/src/hooks/useInstalledAgentSkills.ts
|
||||
1 src/renderer/src/hooks/skills/discovery/useInstalledAgentSkills.ts
|
||||
1 src/renderer/src/hooks/useIpcEvents.ts
|
||||
4 src/renderer/src/hooks/useIssueMetadata.ts
|
||||
2 src/renderer/src/hooks/useLinearIssuePublication.ts
|
||||
@@ -230,11 +230,11 @@
|
||||
1 src/renderer/src/lib/workspace/ownership/runtime-session-mirror-owners.ts
|
||||
1 src/renderer/src/lib/runtime-session-mirror-targets.ts
|
||||
1 src/renderer/src/lib/workspace/ownership/single-runtime-legacy-owner.ts
|
||||
1 src/renderer/src/lib/skill-runtime-command.ts
|
||||
1 src/renderer/src/lib/terminal-close-route.ts
|
||||
4 src/renderer/src/lib/terminal-worktree-route.ts # resolveTerminalPtyOwner: teardown, close and PTY identity read spawn's attribution (round 3 F8), which retired the deprecated resolver's readers
|
||||
1 src/renderer/src/lib/skills/runtime/skill-runtime-command.ts
|
||||
1 src/renderer/src/lib/workspace/ownership/terminal-close-route.ts
|
||||
4 src/renderer/src/lib/workspace/ownership/terminal-worktree-route.ts # resolveTerminalPtyOwner: teardown, close and PTY identity read spawn's attribution (round 3 F8), which retired the deprecated resolver's readers
|
||||
3 src/renderer/src/lib/unread-badge-count-selector.ts
|
||||
1 src/renderer/src/lib/web-runtime-worktree-terminal-after-wake.ts
|
||||
1 src/renderer/src/runtime/hosted-terminals/restoration/web-runtime-worktree-terminal-after-wake.ts
|
||||
1 src/renderer/src/lib/work-items/linear/linear-issue-url-lookup.ts
|
||||
1 src/renderer/src/lib/work-items/linear/linear-issue-write.ts
|
||||
1 src/renderer/src/lib/workspace/activation/worktree-activation.ts
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# JSX mapped straight over a host collection, per file, outside components/host-picker.
|
||||
# This is a RATCHET: counts may only go DOWN. Draw host lists with HostCombobox or
|
||||
# useBoundedHostRows. Prune after a fix: pnpm check:host-list-render-ratchet --prune
|
||||
1 src/renderer/src/components/automations/AutomationRunsDashboard.tsx
|
||||
1 src/renderer/src/components/automations/runs/AutomationRunsDashboard.tsx
|
||||
1 src/renderer/src/components/right-sidebar/ai-vault/panel/AiVaultPanelControls.tsx
|
||||
1 src/renderer/src/components/right-sidebar/source-control/ai/SourceControlAgentActionDialogForm.tsx
|
||||
1 src/renderer/src/components/settings/browser/profiles/BrowserSessionCookiesSection.tsx
|
||||
|
||||
@@ -554,7 +554,6 @@
|
||||
2 src/main/worker-threads/forked-child-entry-path.ts
|
||||
4 src/main/workspace-hooks/hooks.ts
|
||||
10 src/main/workspace-hooks/issue-command-file.ts
|
||||
4 src/main/workspace-hooks/worktree-runner-script.ts
|
||||
1 src/main/workspaces/catalog/folder-repo-git-conversion.ts
|
||||
2 src/main/workspaces/catalog/folder-upgrade-worktree-path.ts
|
||||
3 src/main/workspaces/execution-host/project-runtime-git-router.ts
|
||||
|
||||
@@ -560,21 +560,21 @@
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"filePath": "mobile/src/transport/hosts/mobile-relay-host-overlay.ts",
|
||||
"filePath": "mobile/src/host-catalog/mobile-relay-host-overlay.ts",
|
||||
"kind": "object-property:message",
|
||||
"text": "Expected exactly one endpoint for configured relay metadata",
|
||||
"dynamic": false,
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"filePath": "mobile/src/transport/hosts/mobile-relay-host-overlay.ts",
|
||||
"filePath": "mobile/src/host-catalog/mobile-relay-host-overlay.ts",
|
||||
"kind": "object-property:message",
|
||||
"text": "Relay host identity mismatch",
|
||||
"dynamic": false,
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"filePath": "mobile/src/transport/hosts/mobile-relay-host-overlay.ts",
|
||||
"filePath": "mobile/src/host-catalog/mobile-relay-host-overlay.ts",
|
||||
"kind": "object-property:message",
|
||||
"text": "Relay identity and endpoint must coexist",
|
||||
"dynamic": false,
|
||||
|
||||
@@ -28,27 +28,27 @@
|
||||
1 src/renderer/src/components/artifacts/ArtifactPublishButton.tsx
|
||||
2 src/renderer/src/components/artifacts/ArtifactsPage.tsx
|
||||
2 src/renderer/src/components/artifacts/useArtifactPagination.ts
|
||||
2 src/renderer/src/components/automations/AutomationEditorPromptEditor.tsx
|
||||
1 src/renderer/src/components/automations/AutomationHostFilterNotice.tsx
|
||||
1 src/renderer/src/components/automations/AutomationProjectCombobox.tsx
|
||||
1 src/renderer/src/components/automations/AutomationRunHistory.tsx
|
||||
1 src/renderer/src/components/automations/AutomationRunsDashboard.tsx
|
||||
1 src/renderer/src/components/automations/AutomationRunsTable.tsx
|
||||
2 src/renderer/src/components/automations/authoring/AutomationEditorPromptEditor.tsx
|
||||
1 src/renderer/src/components/automations/hosts/AutomationHostFilterNotice.tsx
|
||||
1 src/renderer/src/components/automations/authoring/AutomationProjectCombobox.tsx
|
||||
1 src/renderer/src/components/automations/runs/AutomationRunHistory.tsx
|
||||
1 src/renderer/src/components/automations/runs/AutomationRunsDashboard.tsx
|
||||
1 src/renderer/src/components/automations/runs/AutomationRunsTable.tsx
|
||||
1 src/renderer/src/components/automations/AutomationsPageSurface.tsx
|
||||
1 src/renderer/src/components/automations/use-automation-agent-picker-entries.ts
|
||||
2 src/renderer/src/components/automations/use-automation-create-destination.ts
|
||||
4 src/renderer/src/components/automations/use-automation-host-catalog.ts
|
||||
4 src/renderer/src/components/automations/use-automation-list-search.ts
|
||||
2 src/renderer/src/components/automations/use-automation-migrate-action.ts
|
||||
1 src/renderer/src/components/automations/use-automation-runs-dashboard.ts
|
||||
1 src/renderer/src/components/automations/use-automations-page-list-state.ts
|
||||
1 src/renderer/src/components/automations/authoring/use-automation-agent-picker-entries.ts
|
||||
2 src/renderer/src/components/automations/authoring/use-automation-create-destination.ts
|
||||
4 src/renderer/src/components/automations/hosts/use-automation-host-catalog.ts
|
||||
4 src/renderer/src/components/automations/listing/use-automation-list-search.ts
|
||||
2 src/renderer/src/components/automations/authoring/use-automation-migrate-action.ts
|
||||
1 src/renderer/src/components/automations/runs/use-automation-runs-dashboard.ts
|
||||
1 src/renderer/src/components/automations/listing/use-automations-page-list-state.ts
|
||||
1 src/renderer/src/components/automations/use-automations-page-local-state.ts
|
||||
1 src/renderer/src/components/automations/use-automations-page-refresh.ts
|
||||
1 src/renderer/src/components/automations/use-automations-page-setup-state.ts
|
||||
1 src/renderer/src/components/automations/authoring/use-automations-page-setup-state.ts
|
||||
1 src/renderer/src/components/automations/use-automations-page-store-state.ts
|
||||
1 src/renderer/src/components/automations/use-external-automation-scope-retention.ts
|
||||
2 src/renderer/src/components/automations/use-scoped-external-automations.ts
|
||||
16 src/renderer/src/components/automations/use-selected-automation-run-history.ts
|
||||
1 src/renderer/src/components/automations/external/use-external-automation-scope-retention.ts
|
||||
2 src/renderer/src/components/automations/external/use-scoped-external-automations.ts
|
||||
16 src/renderer/src/components/automations/runs/use-selected-automation-run-history.ts
|
||||
7 src/renderer/src/components/browser-extension-install-dialog.tsx
|
||||
1 src/renderer/src/components/browser-pane/ClientHostedBrowserPagePane.tsx
|
||||
2 src/renderer/src/components/browser-pane/annotate/MarkupOverlay.tsx
|
||||
@@ -542,16 +542,16 @@
|
||||
4 src/renderer/src/components/sidebar/worktree-list/viewport/use-row-measurement.ts
|
||||
1 src/renderer/src/components/sidebar/worktree-list/viewport/use-scroll-to-top.ts
|
||||
1 src/renderer/src/components/sidebar/worktree-list/viewport/use-virtualizer.ts
|
||||
1 src/renderer/src/components/skills/SkillBundleInstallFlow.tsx
|
||||
2 src/renderer/src/components/skills/SkillInstallDialog.tsx
|
||||
4 src/renderer/src/components/skills/SkillInstallManagementDialog.tsx
|
||||
1 src/renderer/src/components/skills/SkillShareDialog.tsx
|
||||
1 src/renderer/src/components/skills/SkillSharedLinkRow.tsx
|
||||
1 src/renderer/src/components/skills/installation/SkillBundleInstallFlow.tsx
|
||||
2 src/renderer/src/components/skills/installation/SkillInstallDialog.tsx
|
||||
4 src/renderer/src/components/skills/installation/SkillInstallManagementDialog.tsx
|
||||
1 src/renderer/src/components/skills/sharing/SkillShareDialog.tsx
|
||||
1 src/renderer/src/components/skills/sharing/SkillSharedLinkRow.tsx
|
||||
1 src/renderer/src/components/skills/SkillsPage.tsx
|
||||
1 src/renderer/src/components/skills/setup/WslAgentSkillSetupPanel.tsx
|
||||
2 src/renderer/src/components/skills/use-owned-skill-shares.ts
|
||||
1 src/renderer/src/components/skills/use-reviewed-skill-plan.ts
|
||||
1 src/renderer/src/components/skills/use-skill-delete-flow.ts
|
||||
2 src/renderer/src/components/skills/sharing/use-owned-skill-shares.ts
|
||||
1 src/renderer/src/components/skills/freshness/use-reviewed-skill-plan.ts
|
||||
1 src/renderer/src/components/skills/deletion/use-skill-delete-flow.ts
|
||||
1 src/renderer/src/components/sparse/SparseCheckoutPresetSelect.tsx
|
||||
1 src/renderer/src/components/ssh-host-recovery/SshHostMoveAnywayAction.tsx
|
||||
2 src/renderer/src/components/star-nag/StarNagAgentValueMomentObserver.tsx
|
||||
@@ -651,7 +651,7 @@
|
||||
2 src/renderer/src/components/terminal-pane/mobile-driver/MobileDriverOverlay.tsx
|
||||
1 src/renderer/src/components/terminal-pane/mobile-driver/TerminalPaneMobileDriverPortals.tsx
|
||||
1 src/renderer/src/components/terminal-pane/mounting/use-terminal-pane-mount-lifecycle.ts
|
||||
2 src/renderer/src/components/terminal-pane/parking/lifecycle/use-terminal-tab-cold-parking.ts
|
||||
1 src/renderer/src/components/terminal-pane/parking/lifecycle/use-terminal-tab-cold-parking.ts
|
||||
1 src/renderer/src/components/terminal-pane/parking/retention/terminal-pending-startup-park-presence.ts
|
||||
1 src/renderer/src/components/terminal-pane/pty-transport/remote-runtime/recovery/TerminalPaneRecoveryPortals.tsx
|
||||
2 src/renderer/src/components/terminal-pane/session-fork/TerminalAgentSessionForkDialog.tsx
|
||||
@@ -693,21 +693,21 @@
|
||||
1 src/renderer/src/hooks/composer-state/workspace-identity-state.ts
|
||||
3 src/renderer/src/hooks/linear-issue-committed-state.ts
|
||||
1 src/renderer/src/hooks/use-audio-capture.ts
|
||||
1 src/renderer/src/hooks/use-bundled-skill-install.ts
|
||||
1 src/renderer/src/hooks/skills/installation/use-bundled-skill-install.ts
|
||||
2 src/renderer/src/hooks/useDetectedAgents.ts
|
||||
2 src/renderer/src/hooks/useGitHubTaskItems.ts
|
||||
2 src/renderer/src/hooks/useImmediateMutation.ts
|
||||
6 src/renderer/src/hooks/useInstalledAgentSkills.ts
|
||||
6 src/renderer/src/hooks/skills/discovery/useInstalledAgentSkills.ts
|
||||
1 src/renderer/src/hooks/useIssueMetadata.ts
|
||||
3 src/renderer/src/hooks/useLinearIssuePublication.ts
|
||||
1 src/renderer/src/hooks/useMacTccAttributionSeveredNotice.ts
|
||||
1 src/renderer/src/hooks/useSettingsNavigationMetadata.ts
|
||||
4 src/renderer/src/hooks/useSkillFreshness.ts
|
||||
4 src/renderer/src/hooks/skills/freshness/useSkillFreshness.ts
|
||||
1 src/renderer/src/hooks/useTaskPageGitHubWorkItemMutation.ts
|
||||
6 src/renderer/src/hooks/useVirtualizedScrollAnchor.ts
|
||||
1 src/renderer/src/lib/host-chat-program-acquisition.ts
|
||||
1 src/renderer/src/lib/quick-open-file-history.ts
|
||||
2 src/renderer/src/lib/worker-auto-close.ts
|
||||
1 src/renderer/src/lib/agent-session/launch/inventory/host-chat-program-acquisition.ts
|
||||
1 src/renderer/src/lib/files/search/quick-open-file-history.ts
|
||||
2 src/renderer/src/runtime/agent-orchestration/worker-auto-close.ts
|
||||
1 src/renderer/src/runtime/native-chat/naming/structured-chat-name-observation.ts
|
||||
1 src/renderer/src/store/plugins/appearance/plugin-icon-themes.ts
|
||||
5 src/renderer/src/store/retained-views/app-state-view.ts
|
||||
|
||||
@@ -85,9 +85,9 @@
|
||||
1 src/renderer/src/components/terminal-pane/render-health/terminal-render-desync-sentinel.ts
|
||||
1 src/renderer/src/hooks/use-now.ts
|
||||
1 src/renderer/src/lib/agent-session/hibernation/agent-hibernation-coordinator.ts
|
||||
1 src/renderer/src/lib/crash-diagnostics.ts
|
||||
1 src/renderer/src/lib/window-visibility-interval.ts
|
||||
1 src/renderer/src/lib/worker-auto-close.ts
|
||||
1 src/renderer/src/diagnostics/crash-reporting/crash-diagnostics.ts
|
||||
1 src/renderer/src/lib/window-activity/window-visibility-interval.ts
|
||||
1 src/renderer/src/runtime/agent-orchestration/worker-auto-close.ts
|
||||
1 src/renderer/src/runtime/hosts/wsl/wsl-refused-read-watch.ts
|
||||
1 src/shared/remote-runtime/control/remote-runtime-shared-control-app-heartbeat.ts
|
||||
1 src/shared/remote-runtime/remote-runtime-socket-liveness.ts
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This is a RATCHET: counts may only go DOWN. Use useTranslate()/useIntlLocale() from
|
||||
# @/i18n/use-translate. Prune after a fix: pnpm check:render-path-translate-ratchet --prune
|
||||
2 src/renderer/src/components/agent/AgentLaunchPromptComposer.tsx
|
||||
5 src/renderer/src/components/automations/use-external-automation-actions.ts
|
||||
5 src/renderer/src/components/automations/external/use-external-automation-actions.ts
|
||||
1 src/renderer/src/components/diff-comments/useDiffCommentDecorator.tsx
|
||||
2 src/renderer/src/components/editor/markdown-preview/render-tree/use-markdown-preview-components.tsx
|
||||
1 src/renderer/src/components/tab-group/useTabGroupCreationCommands.ts
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
4 src/renderer/src/components/terminal-pane/render-health/recovery/terminal-recovery-ledger-test-store.ts
|
||||
3 src/renderer/src/components/worktree-jump/worktree-jump-palette-status-inputs.ts
|
||||
1 src/renderer/src/lib/agent-session/hibernation/agent-hibernation-coordinator.ts
|
||||
4 src/renderer/src/lib/floating-workspace-terminal-actions.ts
|
||||
4 src/renderer/src/components/floating-terminal/floating-workspace-terminal-actions.ts
|
||||
1 src/renderer/src/lib/pane-manager/client-hosted-browser-row-state.ts
|
||||
4 src/renderer/src/lib/workspace/persistence/session-write-subscriber.ts
|
||||
1 src/renderer/src/lib/workspace/persistence/workspace-session-browser-tabs.ts
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { readFile, readdir } from 'node:fs/promises'
|
||||
import { readRouteSnapshot } from '../../mobile-web-app/mobile-web-app-route-snapshot.mjs'
|
||||
import { MOBILE_WEB_APP_DEPENDENCY_PATH } from '../../mobile-web-app/mobile-web-app-bundle-dependencies.mjs'
|
||||
import { existsSync, realpathSync } from 'node:fs'
|
||||
@@ -457,6 +457,32 @@ export async function mobileWebAppModuleClosure(entryModules, { absWorkingDir }
|
||||
|
||||
// One lazily imported chunk per UI language; the page fetches only the active one after init.
|
||||
const LOCALE_CATALOG_INPUT = /(^|\/)src\/i18n\/locales\/[^/]+\.json$/
|
||||
const localeCatalogDir = join(mobileDir, 'src', 'i18n', 'locales')
|
||||
|
||||
// The same catalogs as JSON for the host to serve one at a time, to shells that skip the chunks;
|
||||
// English is the page's inline fallback, so it has none.
|
||||
export async function readLocaleCatalogs(directory = localeCatalogDir) {
|
||||
const names = (await readdir(directory))
|
||||
.filter((name) => name.endsWith('.json') && name !== 'en.json')
|
||||
.sort()
|
||||
return Promise.all(
|
||||
names.map(async (name) => {
|
||||
// Minify: the host sends and the phone keeps the parsed object, not the source layout.
|
||||
const bytes = Buffer.from(
|
||||
JSON.stringify(JSON.parse(await readFile(join(directory, name), 'utf8'))),
|
||||
'utf8'
|
||||
)
|
||||
const sha256 = sha256Hex(bytes)
|
||||
return {
|
||||
locale: name.slice(0, -'.json'.length),
|
||||
bytes,
|
||||
path: `catalogs/${sha256}.json`,
|
||||
sha256,
|
||||
byteLength: bytes.byteLength
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
function localeCatalogOutputs(metafile) {
|
||||
return new Set(
|
||||
@@ -586,11 +612,13 @@ export async function buildMobileWebAppBundle({
|
||||
desktopVersion,
|
||||
protocolWindow,
|
||||
{ script, chunks, images, catalogChunks, entryStaticBytes, chunkCount, routeChunks, routeKeys },
|
||||
catalogs,
|
||||
scrollbarStyle
|
||||
] = await Promise.all([
|
||||
readDesktopVersion(),
|
||||
readProtocolWindow(),
|
||||
bundleMobileWebApp({ appDir }),
|
||||
readLocaleCatalogs(),
|
||||
readFile(join(projectDir, 'src/shared/styles/scrollbar-sleek.css'), 'utf8').then((style) =>
|
||||
// The shared desktop stylesheet can be checked out as CRLF on Windows.
|
||||
style.replace(/\r\n/g, '\n')
|
||||
@@ -598,9 +626,14 @@ export async function buildMobileWebAppBundle({
|
||||
])
|
||||
// Names already hash final bytes, so hashedAsset must reproduce them.
|
||||
const scriptAsset = hashedAsset(script, 'js')
|
||||
const catalogChunkSet = new Set(catalogChunks)
|
||||
const written = [
|
||||
scriptAsset,
|
||||
...[...chunks, ...images].map(({ name, bytes }) => hashedAsset(bytes, extname(name).slice(1)))
|
||||
...[...chunks, ...images].map((output) => ({
|
||||
...hashedAsset(output.bytes, extname(output.name).slice(1)),
|
||||
// Shells that read catalogs from the host skip these; older shells download them as before.
|
||||
...(catalogChunkSet.has(output) ? { kind: 'catalog' } : {})
|
||||
}))
|
||||
]
|
||||
|
||||
// Root-absolute URLs survive nested routes; CSP allows only about: base. ESM entry/chunks load under existing self policy.
|
||||
@@ -624,6 +657,7 @@ export async function buildMobileWebAppBundle({
|
||||
const { manifest } = await writeMobileWebBundleTree({
|
||||
outDir,
|
||||
written: [indexAsset, ...written],
|
||||
catalogs,
|
||||
desktopVersion,
|
||||
protocolWindow,
|
||||
routes: resolveMobileWebPageRoutes(routeKeys, pageRoutes),
|
||||
|
||||
@@ -133,6 +133,8 @@ async function compressWithBrotli(written) {
|
||||
export async function writeMobileWebBundleTree({
|
||||
outDir,
|
||||
written,
|
||||
// Host-only JSON outside `assets` and buildId, served one at a time over RPC.
|
||||
catalogs = [],
|
||||
desktopVersion,
|
||||
protocolWindow,
|
||||
// Empty route list makes shell render every screen natively.
|
||||
@@ -143,14 +145,15 @@ export async function writeMobileWebBundleTree({
|
||||
}) {
|
||||
const brotliCopies = brotli ? await compressWithBrotli(written) : new Map()
|
||||
const assets = written
|
||||
.map(({ path, sha256, byteLength, contentType }) => {
|
||||
.map(({ path, sha256, byteLength, contentType, kind }) => {
|
||||
const copy = brotliCopies.get(path)
|
||||
return {
|
||||
path,
|
||||
sha256,
|
||||
byteLength,
|
||||
contentType,
|
||||
...(copy === undefined ? {} : { brotliByteLength: copy.byteLength })
|
||||
...(copy === undefined ? {} : { brotliByteLength: copy.byteLength }),
|
||||
...(kind === undefined ? {} : { kind })
|
||||
}
|
||||
})
|
||||
.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0))
|
||||
@@ -164,14 +167,27 @@ export async function writeMobileWebBundleTree({
|
||||
entrypoint: MOBILE_WEB_BUNDLE_ENTRYPOINT,
|
||||
totalBytes: assets.reduce((total, asset) => total + asset.byteLength, 0),
|
||||
assets,
|
||||
routes
|
||||
routes,
|
||||
...(catalogs.length === 0
|
||||
? {}
|
||||
: {
|
||||
catalogs: catalogs.map(({ locale, path, sha256, byteLength }) => ({
|
||||
locale,
|
||||
path,
|
||||
sha256,
|
||||
byteLength
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
// Clear entire output or stale unreferenced assets ship inside asar.
|
||||
await rm(outDir, { recursive: true, force: true })
|
||||
await mkdir(join(outDir, 'assets'), { recursive: true })
|
||||
for (const asset of written) {
|
||||
await writeFile(join(outDir, asset.path), asset.bytes)
|
||||
if (catalogs.length > 0) {
|
||||
await mkdir(join(outDir, 'catalogs'), { recursive: true })
|
||||
}
|
||||
for (const file of [...written, ...catalogs]) {
|
||||
await writeFile(join(outDir, file.path), file.bytes)
|
||||
}
|
||||
for (const [path, copy] of brotliCopies) {
|
||||
await writeFile(join(outDir, mobileWebBundleBrotliPath(path)), copy)
|
||||
|
||||
@@ -29,6 +29,8 @@ export function mobileWebAppBundleMaxAssets(routeCount, imageCount, catalogChunk
|
||||
// fetched only for the active language, never before the first route. Code keeps its own fence.
|
||||
export const MOBILE_WEB_APP_BUNDLE_MAX_CATALOG_CHUNKS = 10
|
||||
export const MOBILE_WEB_APP_BUNDLE_MAX_CATALOG_BYTES = 3 * 1024 * 1024
|
||||
// The host sends a catalog's JSON in one reply, which must fit a 1 MiB relay frame once encrypted.
|
||||
export const MOBILE_WEB_APP_HOST_CATALOG_MAX_BYTES = 384 * 1024
|
||||
|
||||
// Our own fence on the page's code, well inside the phone contract (32 MiB total, 10 MiB per asset in
|
||||
// manifest-contract.ts); it fails the build before the code weighs more than any one asset may.
|
||||
@@ -185,6 +187,23 @@ export async function verifyMobileWebAppBundle({ bundleDir = defaultBundleDir }
|
||||
`${String(MOBILE_WEB_APP_BUNDLE_MAX_CATALOG_BYTES)} bytes`
|
||||
)
|
||||
}
|
||||
// buildId leaves the host's JSON catalogs out, so a stale copy shows only here.
|
||||
const hostCatalogsOf = (built) => JSON.stringify(built.catalogs ?? [])
|
||||
if (hostCatalogsOf(first.manifest) !== hostCatalogsOf(second.manifest)) {
|
||||
fail('host language catalogs are not reproducible')
|
||||
}
|
||||
if (hostCatalogsOf(first.manifest) !== hostCatalogsOf(manifest)) {
|
||||
fail(`${bundleDir} is stale: its host language catalogs differ from a fresh build's`)
|
||||
}
|
||||
const oversized = (manifest.catalogs ?? []).find(
|
||||
(catalog) => catalog.byteLength > MOBILE_WEB_APP_HOST_CATALOG_MAX_BYTES
|
||||
)
|
||||
if (oversized) {
|
||||
fail(
|
||||
`the ${oversized.locale} host catalog is ${String(oversized.byteLength)} bytes, over the ` +
|
||||
`${String(MOBILE_WEB_APP_HOST_CATALOG_MAX_BYTES)} one reply carries`
|
||||
)
|
||||
}
|
||||
const budgetBytes = mobileWebAppBundleBudgetBytes(manifest) - first.catalogBytes
|
||||
if (budgetBytes > MOBILE_WEB_APP_BUNDLE_MAX_TOTAL_BYTES) {
|
||||
fail(
|
||||
|
||||
@@ -4622,11 +4622,9 @@
|
||||
"src/preload/usage-provider-api.test.ts": 46,
|
||||
"src/renderer/src/app-shell/app-command-handlers-tab-rename.test.ts": 1786,
|
||||
"src/renderer/src/app-shell/shutdown-checkpoint-persist.test.ts": 65,
|
||||
"src/renderer/src/app-shell/shutdown-checkpoint-restart-lifecycle.test.ts": 210,
|
||||
"src/renderer/src/app-shell/startup-window-parity.test.ts": 2306,
|
||||
"src/renderer/src/app-shell/use-profile-state-save-delay-notice.sonner.test.tsx": 355,
|
||||
"src/renderer/src/app-shell/use-profile-state-save-delay-notice.test.tsx": 293,
|
||||
"src/renderer/src/app-shell/use-visible-hosted-review-refresh.test.tsx": 572,
|
||||
"src/renderer/src/app-shell/visible-review-reporting.test.ts": 1872,
|
||||
"src/renderer/src/app-shell/workspace-view-cross-client-sync.test.tsx": 1170,
|
||||
"src/renderer/src/app-shell/worktree-creation-chat-handoff.test.tsx": 2824,
|
||||
@@ -4641,12 +4639,8 @@
|
||||
"src/renderer/src/components/JiraIssueWorkspace.optimistic-edit.test.tsx": 2340,
|
||||
"src/renderer/src/components/JiraIssueWorkspace.status-queue.test.tsx": 1852,
|
||||
"src/renderer/src/components/JiraIssueWorkspace.transition-source.test.tsx": 1843,
|
||||
"src/renderer/src/components/native-chat-recovery/integration/NativeChatRemoteResume.test.tsx": 8774,
|
||||
"src/renderer/src/components/native-chat-recovery/tree/NativeChatResumeOnRestartGroups.selection.test.tsx": 2633,
|
||||
"src/renderer/src/components/native-chat-recovery/tree/NativeChatResumeOnRestartGroups.test.tsx": 3472,
|
||||
"src/renderer/src/components/NewWorkspaceComposerCard.quick-file-drop.test.tsx": 4557,
|
||||
"src/renderer/src/components/NewWorkspaceComposerCard.set-location.test.tsx": 1301,
|
||||
"src/renderer/src/components/QuickOpen.selection.test.tsx": 1046,
|
||||
"src/renderer/src/components/SelectedTextCopyMenu.test.tsx": 329,
|
||||
"src/renderer/src/components/TerminalSearch.test.tsx": 458,
|
||||
"src/renderer/src/components/UpdateCard.error-card.test.tsx": 2851,
|
||||
@@ -4675,56 +4669,46 @@
|
||||
"src/renderer/src/components/artifacts/ArtifactPublishButton.test.tsx": 706,
|
||||
"src/renderer/src/components/artifacts/ArtifactsPage.test.tsx": 2052,
|
||||
"src/renderer/src/components/artifacts/artifact-publish-flow.test.ts": 114,
|
||||
"src/renderer/src/components/automations/AutomationEditorPromptEditor.test.tsx": 396,
|
||||
"src/renderer/src/components/automations/authoring/AutomationEditorPromptEditor.test.tsx": 396,
|
||||
"src/renderer/src/components/automations/AutomationPromptDisclosure.test.tsx": 893,
|
||||
"src/renderer/src/components/automations/AutomationRunsTable.test.tsx": 668,
|
||||
"src/renderer/src/components/automations/AutomationSchedulePicker.test.ts": 431,
|
||||
"src/renderer/src/components/automations/AutomationTimeField.test.tsx": 654,
|
||||
"src/renderer/src/components/automations/authoring/AutomationSchedulePicker.test.ts": 431,
|
||||
|
||||
"src/renderer/src/components/automations/AutomationsPage.behavior.test.tsx": 3389,
|
||||
"src/renderer/src/components/automations/AutomationsPage.edit-destination.test.tsx": 2932,
|
||||
"src/renderer/src/components/automations/AutomationsPage.run-navigation.test.tsx": 3056,
|
||||
|
||||
"src/renderer/src/components/automations/ExternalAutomationManagers.test.tsx": 852,
|
||||
"src/renderer/src/components/automations/automation-captured-owner.test.ts": 379,
|
||||
"src/renderer/src/components/automations/automation-create-projects.test.ts": 42,
|
||||
"src/renderer/src/components/automations/hosts/automation-captured-owner.test.ts": 379,
|
||||
"src/renderer/src/components/automations/automation-host-cache-controller.test.ts": 411,
|
||||
"src/renderer/src/components/automations/automation-host-cache-error.test.ts": 391,
|
||||
"src/renderer/src/components/automations/automation-host-cache-health.test.ts": 52,
|
||||
"src/renderer/src/components/automations/automation-host-cache.test.ts": 79,
|
||||
"src/renderer/src/components/automations/automation-host-catalog-generation.test.ts": 258,
|
||||
"src/renderer/src/components/automations/automation-host-client.test.ts": 374,
|
||||
"src/renderer/src/components/automations/hosts/automation-host-cache.test.ts": 79,
|
||||
|
||||
"src/renderer/src/components/automations/automation-host-diagnostics.test.ts": 460,
|
||||
"src/renderer/src/components/automations/automation-host-filter-resolution.test.ts": 256,
|
||||
"src/renderer/src/components/automations/automation-host-health.test.ts": 47,
|
||||
|
||||
"src/renderer/src/components/automations/automation-host-invalidation-window-events.test.ts": 83,
|
||||
"src/renderer/src/components/automations/automation-host-invalidation.test.ts": 85,
|
||||
"src/renderer/src/components/automations/automation-host-list-rows.test.ts": 419,
|
||||
"src/renderer/src/components/automations/automation-host-recovery.test.ts": 51,
|
||||
"src/renderer/src/components/automations/hosts/automation-host-list-rows.test.ts": 419,
|
||||
"src/renderer/src/components/automations/automation-host-scale-gates.test.ts": 638,
|
||||
"src/renderer/src/components/automations/automation-host-scheduler.test.ts": 439,
|
||||
"src/renderer/src/components/automations/automation-legacy-schedule-editing.test.ts": 449,
|
||||
"src/renderer/src/components/automations/automation-list-focus-recovery.test.ts": 48,
|
||||
"src/renderer/src/components/automations/automation-list-row-identity.test.ts": 626,
|
||||
"src/renderer/src/components/automations/automation-list-search.test.ts": 75,
|
||||
"src/renderer/src/components/automations/hosts/automation-host-scheduler.test.ts": 439,
|
||||
"src/renderer/src/components/automations/authoring/automation-legacy-schedule-editing.test.ts": 449,
|
||||
|
||||
"src/renderer/src/components/automations/automation-list-view.test.ts": 257,
|
||||
"src/renderer/src/components/automations/automation-run-context.test.ts": 58,
|
||||
"src/renderer/src/components/automations/automation-run-history-keyboard-navigation.test.ts": 434,
|
||||
"src/renderer/src/components/automations/automation-run-open-target.test.ts": 442,
|
||||
"src/renderer/src/components/automations/runs/automation-run-history-keyboard-navigation.test.ts": 434,
|
||||
"src/renderer/src/components/automations/runs/automation-run-open-target.test.ts": 442,
|
||||
"src/renderer/src/components/automations/automation-run-output-snapshot-equivalence.test.ts": 158,
|
||||
"src/renderer/src/components/automations/automation-run-output-snapshot.test.ts": 96,
|
||||
"src/renderer/src/components/automations/automation-setup-decision.test.ts": 58,
|
||||
"src/renderer/src/components/automations/authoring/automation-setup-decision.test.ts": 58,
|
||||
"src/renderer/src/components/automations/automation-usage-model.test.ts": 200,
|
||||
"src/renderer/src/components/automations/external-automation-list-entries.test.ts": 57,
|
||||
"src/renderer/src/components/automations/external-automation-scope-gating.test.ts": 67,
|
||||
"src/renderer/src/components/automations/external/external-automation-scope-gating.test.ts": 67,
|
||||
"src/renderer/src/components/automations/external-automation-scope-keys.test.ts": 53,
|
||||
"src/renderer/src/components/automations/use-automation-host-catalog-readoption.test.tsx": 802,
|
||||
"src/renderer/src/components/automations/use-automation-host-catalog.test.tsx": 920,
|
||||
"src/renderer/src/components/automations/use-automation-list-focus-recovery.test.tsx": 229,
|
||||
"src/renderer/src/components/automations/use-automation-list-search.test.tsx": 679,
|
||||
"src/renderer/src/components/automations/use-automation-runs-dashboard-payload.test.tsx": 6692,
|
||||
"src/renderer/src/components/automations/use-automation-runs-dashboard.test.tsx": 854,
|
||||
"src/renderer/src/components/automations/hosts/use-automation-host-catalog-readoption.test.tsx": 802,
|
||||
"src/renderer/src/components/automations/hosts/use-automation-host-catalog.test.tsx": 920,
|
||||
|
||||
"src/renderer/src/components/automations/listing/use-automation-list-search.test.tsx": 679,
|
||||
"src/renderer/src/components/automations/runs/use-automation-runs-dashboard-payload.test.tsx": 6692,
|
||||
"src/renderer/src/components/automations/runs/use-automation-runs-dashboard.test.tsx": 854,
|
||||
"src/renderer/src/components/automations/use-selected-automation-run-history.test.tsx": 2104,
|
||||
"src/renderer/src/components/browser-favicon.test.tsx": 333,
|
||||
"src/renderer/src/components/browser-pane/ClientHostedBrowserPagePane.dead-guest.test.tsx": 6219,
|
||||
"src/renderer/src/components/browser-pane/ClientHostedBrowserPagePane.drag-focus.test.tsx": 5826,
|
||||
"src/renderer/src/components/browser-pane/ClientHostedBrowserPagePane.failure-remount.test.tsx": 3085,
|
||||
"src/renderer/src/components/browser-pane/ClientHostedBrowserPagePane.markup.test.tsx": 4575,
|
||||
@@ -4821,7 +4805,6 @@
|
||||
"src/renderer/src/components/dashboard-popout/preview-terminal-box-fit-lifecycle.test.ts": 192,
|
||||
"src/renderer/src/components/dashboard-popout/preview-terminal-ime-bridge-kitty-bytes.test.ts": 479,
|
||||
"src/renderer/src/components/dashboard-popout/remote-runtime-terminal-preview-api.test.ts": 81,
|
||||
"src/renderer/src/components/dashboard-popout/use-agent-dashboard-telemetry.test.ts": 2108,
|
||||
"src/renderer/src/components/dashboard-popout/useDashboardSnapshot.test.tsx": 432,
|
||||
"src/renderer/src/components/dashboard/AgentDashboardDrawer.focus.test.tsx": 2567,
|
||||
"src/renderer/src/components/dashboard/AgentDashboardDrawer.test.tsx": 1981,
|
||||
@@ -4843,14 +4826,11 @@
|
||||
"src/renderer/src/components/diff-comments/diff-comment-popover-outside-click.test.tsx": 1889,
|
||||
"src/renderer/src/components/diff-comments/useDiffCommentDecorator.lifecycle.test.tsx": 2669,
|
||||
"src/renderer/src/components/diff-comments/useDiffCommentDecorator.range-selection.test.tsx": 1782,
|
||||
"src/renderer/src/components/editor/check-details/panel/CheckRunDetailsPanel.captured-failure.test.tsx": 2412,
|
||||
"src/renderer/src/components/editor/check-details/panel/CheckRunDetailsPanel.copy.test.tsx": 3108,
|
||||
"src/renderer/src/components/editor/check-details/panel/CheckRunDetailsPanel.log-outcomes.test.tsx": 3230,
|
||||
"src/renderer/src/components/editor/DiagramViewerModal.test.tsx": 2539,
|
||||
"src/renderer/src/components/editor/diff/sections/DiffSectionBody.word-wrap-lifecycle.test.tsx": 3036,
|
||||
"src/renderer/src/components/editor/diff/monaco-view/DiffViewer.word-wrap-lifecycle.test.tsx": 2499,
|
||||
"src/renderer/src/components/editor/EditorConflictReviewSurface.live-record.test.tsx": 1193,
|
||||
"src/renderer/src/components/editor/EditorContent.monaco-lifecycle.test.tsx": 3162,
|
||||
"src/renderer/src/components/editor/EditorEditFileSurface.monaco-containment.test.tsx": 2666,
|
||||
"src/renderer/src/components/editor/EditorFileLoadErrorView.test.tsx": 660,
|
||||
"src/renderer/src/components/editor/EditorFileLocationMenuItems.test.tsx": 846,
|
||||
@@ -4862,17 +4842,13 @@
|
||||
"src/renderer/src/components/editor/notebook/document/IpynbRendering.test.tsx": 2143,
|
||||
"src/renderer/src/components/editor/markdown-preview/surface/MarkdownPreview.link-routing.interaction.test.tsx": 1127,
|
||||
"src/renderer/src/components/editor/MediaViewer.test.tsx": 308,
|
||||
"src/renderer/src/components/editor/MermaidViewer.test.tsx": 3079,
|
||||
"src/renderer/src/components/editor/MonacoEditor.owner-view-state.test.tsx": 7073,
|
||||
"src/renderer/src/components/editor/PdfFind.test.tsx": 581,
|
||||
"src/renderer/src/components/editor/PluginBytesCustomEditorSurface.test.tsx": 641,
|
||||
"src/renderer/src/components/editor/PluginEditorNeedsDesktopNotice.test.tsx": 2107,
|
||||
"src/renderer/src/components/editor/PluginFileTypeSuggestion.test.tsx": 2062,
|
||||
"src/renderer/src/components/editor/rich-markdown/instance/RichMarkdownEditor.focus-leave.test.tsx": 4927,
|
||||
"src/renderer/src/components/editor/rich-markdown/instance/RichMarkdownErrorBoundary.lazy-chunk.test.tsx": 367,
|
||||
"src/renderer/src/components/editor/ai-vault-session-log-content.test.tsx": 1899,
|
||||
"src/renderer/src/components/editor/check-details/actions/check-annotation-path.test.ts": 53,
|
||||
"src/renderer/src/components/editor/check-details/reading/check-details-reading-viewport.test.ts": 259,
|
||||
"src/renderer/src/components/editor/model-lifetime/retention/closed-editor-model-lifetime.test.ts": 7921,
|
||||
"src/renderer/src/components/editor/model-lifetime/retention/closed-editor-model-shell.test.tsx": 4492,
|
||||
"src/renderer/src/components/editor/model-lifetime/retention/closed-editor-tab-disposal.test.ts": 121,
|
||||
@@ -4976,7 +4952,6 @@
|
||||
"src/renderer/src/components/editor/monaco-programmatic-sync.test.ts": 46,
|
||||
"src/renderer/src/components/editor/pdf-orca-media-range-transport.test.ts": 282,
|
||||
"src/renderer/src/components/editor/pdf-view-position.test.ts": 74,
|
||||
"src/renderer/src/components/editor/pdf-viewer-failed-load-recovery.test.tsx": 2363,
|
||||
"src/renderer/src/components/editor/pdf-viewer-zoom-ownership.test.tsx": 789,
|
||||
"src/renderer/src/components/editor/plugin-custom-editor-host.test.ts": 480,
|
||||
"src/renderer/src/components/editor/rich-markdown/raw-source/raw-markdown-html-line-break.test.ts": 2188,
|
||||
@@ -5047,17 +5022,13 @@
|
||||
"src/renderer/src/components/editor/use-monaco-editor-mount.cursor-owner.test.tsx": 1332,
|
||||
"src/renderer/src/components/editor/use-monaco-editor-mount.stale-cache.test.tsx": 877,
|
||||
"src/renderer/src/components/editor/use-monaco-reveal-scheduler.test.tsx": 273,
|
||||
"src/renderer/src/components/editor/use-pdf-viewer-find-shortcut.test.tsx": 907,
|
||||
"src/renderer/src/components/editor/use-preserve-section-during-external-edit.test.tsx": 268,
|
||||
"src/renderer/src/components/editor/rich-markdown/tables/use-rich-markdown-table-context-menu.test.tsx": 2238,
|
||||
"src/renderer/src/components/editor/useEditorPanelContentState.test.tsx": 3214,
|
||||
"src/renderer/src/components/editor/external-changes/useEditorPanelExternalContentEvents.test.tsx": 2018,
|
||||
"src/renderer/src/components/editor/useEditorPanelFloatingTabContentState.test.tsx": 889,
|
||||
"src/renderer/src/components/editor/useEditorPanelHostUnresolvedContentState.test.tsx": 1952,
|
||||
"src/renderer/src/components/editor/useEditorPanelVisibilityContentState.test.tsx": 2006,
|
||||
"src/renderer/src/components/editor/notebook/kernel/useIpynbCellExecution.test.tsx": 695,
|
||||
"src/renderer/src/components/editor/notebook/document/useIpynbDocumentEditing.test.tsx": 2192,
|
||||
"src/renderer/src/components/editor/notebook/document/useIpynbScrollRestoration.test.tsx": 323,
|
||||
"src/renderer/src/components/editor/rich-markdown/links/useLinkBubble.test.tsx": 493,
|
||||
"src/renderer/src/components/editor/rich-markdown/images/useLocalImagePick.test.tsx": 1319,
|
||||
"src/renderer/src/components/editor/document-images/useLocalImageSrc.test.ts": 736,
|
||||
@@ -5081,11 +5052,7 @@
|
||||
"src/renderer/src/components/emulator-pane/emulator-screen-stream-content.test.tsx": 408,
|
||||
"src/renderer/src/components/emulator-pane/use-emulator-pane-session.test.tsx": 1968,
|
||||
"src/renderer/src/components/emulator-pane/use-mobile-emulator-tab-intro-actions.test.tsx": 1828,
|
||||
"src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.lazy-chunk.test.tsx": 451,
|
||||
"src/renderer/src/components/error-boundaries/RecoverableRenderErrorBoundary.never-landed-reload.test.tsx": 449,
|
||||
"src/renderer/src/components/feature-tips/ChatUiHereCornerCard.test.tsx": 2798,
|
||||
"src/renderer/src/components/feature-tips/ChatUiHereFeatureTipVisual.test.tsx": 1093,
|
||||
"src/renderer/src/components/feature-tips/ChatUiHereTip.test.tsx": 6788,
|
||||
"src/renderer/src/components/feature-tips/feature-tip-modal-state.test.ts": 244,
|
||||
"src/renderer/src/components/feature-wall/FeatureWallSetupWorkflowActions.test.tsx": 2028,
|
||||
"src/renderer/src/components/feature-wall/FullDiskAccessSetupPrompt.test.ts": 466,
|
||||
@@ -5135,15 +5102,9 @@
|
||||
"src/renderer/src/components/mobile/WindowsFirewallNotice.test.tsx": 691,
|
||||
"src/renderer/src/components/mobile/paired-mobile-devices.test.ts": 192,
|
||||
"src/renderer/src/components/mobile/use-mobile-page-paired-devices.test.ts": 475,
|
||||
"src/renderer/src/components/native-chat-recovery/offers/native-chat-launch-resume-decision.test.tsx": 1844,
|
||||
"src/renderer/src/components/native-chat-recovery/integration/native-chat-resume-bulk-progress.test.tsx": 3261,
|
||||
"src/renderer/src/components/native-chat-recovery/offers/native-chat-resume-failed-chat-watch.test.ts": 1954,
|
||||
"src/renderer/src/components/native-chat-recovery/failures/native-chat-resume-failure-guidance.test.ts": 240,
|
||||
"src/renderer/src/components/native-chat-recovery/integration/native-chat-resume-finished-run.test.tsx": 4173,
|
||||
"src/renderer/src/components/native-chat-recovery/tree/native-chat-resume-on-restart-grouping.test.ts": 117,
|
||||
"src/renderer/src/components/native-chat-recovery/integration/native-chat-resume-result-view.test.tsx": 2723,
|
||||
"src/renderer/src/components/native-chat-recovery/runs/native-chat-resume-run.test.ts": 65,
|
||||
"src/renderer/src/components/native-chat-recovery/integration/native-chat-resume-skipped-progress.test.tsx": 3009,
|
||||
"src/renderer/src/components/native-chat/messages/rows/NativeChatAgentMessageCard.test.tsx": 3700,
|
||||
"src/renderer/src/components/native-chat/tools/tasks/NativeChatBackgroundTaskRun.test.tsx": 242,
|
||||
"src/renderer/src/components/native-chat/tools/tasks/NativeChatBackgroundTasksStatus.test.tsx": 782,
|
||||
@@ -5195,9 +5156,7 @@
|
||||
"src/renderer/src/components/native-chat/selection-quotes/NativeChatSelectionQuote.test.tsx": 2370,
|
||||
"src/renderer/src/components/native-chat/surfaces/integration/NativeChatStructuredSession.approval-and-start-failure.test.tsx": 2922,
|
||||
"src/renderer/src/components/native-chat/surfaces/integration/NativeChatStructuredSession.availability-notice.test.tsx": 2764,
|
||||
"src/renderer/src/components/native-chat/surfaces/integration/NativeChatStructuredSession.history-read-state.test.tsx": 4919,
|
||||
"src/renderer/src/components/native-chat/surfaces/integration/NativeChatStructuredSession.host-outage.test.tsx": 3552,
|
||||
"src/renderer/src/components/native-chat/surfaces/integration/NativeChatStructuredSession.notice-card.test.tsx": 2911,
|
||||
"src/renderer/src/components/native-chat/surfaces/integration/NativeChatStructuredSession.refusal-notices.test.tsx": 3014,
|
||||
"src/renderer/src/components/native-chat/surfaces/integration/NativeChatStructuredSession.test.tsx": 4459,
|
||||
"src/renderer/src/components/native-chat/tools/tasks/NativeChatStructuredSessionStatus.test.tsx": 583,
|
||||
@@ -5238,10 +5197,8 @@
|
||||
"src/renderer/src/components/native-chat/attachments/intake/native-chat-composer-drop-scope.test.tsx": 1409,
|
||||
"src/renderer/src/components/native-chat/attachments/intake/native-chat-composer-ime-file-drop.test.tsx": 1326,
|
||||
"src/renderer/src/components/native-chat/drafts/native-chat-composer-prompt-recall.test.tsx": 1724,
|
||||
"src/renderer/src/components/native-chat/composer/focus/native-chat-composer-reveal-focus.test.tsx": 526,
|
||||
"src/renderer/src/components/native-chat/attachments/intake/native-chat-composer-workspace-file-drop.test.tsx": 1166,
|
||||
"src/renderer/src/components/native-chat/drafts/native-chat-draft-retention.test.ts": 1415,
|
||||
"src/renderer/src/components/native-chat/attachments/intake/native-chat-element-file-drop.test.tsx": 2057,
|
||||
"src/renderer/src/components/native-chat/attachments/intake/native-chat-external-attachments-destination.test.tsx": 951,
|
||||
"src/renderer/src/components/native-chat/links/actions/native-chat-file-link-existence.test.ts": 1937,
|
||||
"src/renderer/src/components/native-chat/pane/actions/native-chat-header-ownership.test.tsx": 2796,
|
||||
@@ -5256,7 +5213,6 @@
|
||||
"src/renderer/src/components/native-chat/native-chat-new-rows-marker.test.tsx": 581,
|
||||
"src/renderer/src/components/native-chat/pane/routing/native-chat-open-wake.test.ts": 1807,
|
||||
"src/renderer/src/components/native-chat/pane/ownership/native-chat-owner-selectors.test.tsx": 525,
|
||||
"src/renderer/src/components/native-chat/attachments/intake/native-chat-pane-file-drop.test.tsx": 439,
|
||||
"src/renderer/src/components/native-chat/paste/native-chat-paste-routing.test.tsx": 2417,
|
||||
"src/renderer/src/components/native-chat/session/terminal/delivery/native-chat-pending.test.ts": 273,
|
||||
"src/renderer/src/components/native-chat/composer/editor/native-chat-prompt-document-text.test.ts": 219,
|
||||
@@ -5304,7 +5260,6 @@
|
||||
"src/renderer/src/components/native-chat/conversation/projection/use-native-chat-context-clear-floor.test.tsx": 271,
|
||||
"src/renderer/src/components/native-chat/pane/actions/use-native-chat-context-menu.targets.test.tsx": 3071,
|
||||
"src/renderer/src/components/native-chat/attachments/intake/use-native-chat-external-attachments.test.tsx": 797,
|
||||
"src/renderer/src/components/native-chat/viewport/find/use-native-chat-find.test.tsx": 1458,
|
||||
"src/renderer/src/components/native-chat/session/status/use-native-chat-hook-status.test.ts": 1927,
|
||||
"src/renderer/src/components/native-chat/host-access/use-native-chat-host-outage.test.tsx": 2131,
|
||||
"src/renderer/src/components/native-chat/drafts/use-native-chat-launch-draft-adoption.test.tsx": 319,
|
||||
@@ -5340,8 +5295,6 @@
|
||||
"src/renderer/src/components/new-workspace/DirectWorkItemSetupDialog.test.tsx": 5296,
|
||||
"src/renderer/src/components/new-workspace/NewWorkspaceComposerNameSection.test.tsx": 2493,
|
||||
"src/renderer/src/components/new-workspace/ProjectCombobox.dialog-handoff.test.tsx": 1043,
|
||||
"src/renderer/src/components/new-workspace/ProjectCombobox.test.tsx": 848,
|
||||
"src/renderer/src/components/new-workspace/ProjectComboboxRow.test.tsx": 415,
|
||||
"src/renderer/src/components/new-workspace/RunTargetCombobox.host-identity.test.tsx": 856,
|
||||
"src/renderer/src/components/new-workspace/SetProjectLocationDialog.host-identity.test.tsx": 1094,
|
||||
"src/renderer/src/components/new-workspace/SetProjectLocationDialog.test.tsx": 1387,
|
||||
@@ -5355,7 +5308,6 @@
|
||||
"src/renderer/src/components/new-workspace/use-recent-project-ids.test.ts": 1730,
|
||||
"src/renderer/src/components/new-workspace/use-smart-workspace-name-field-foundation.source.test.tsx": 2290,
|
||||
"src/renderer/src/components/new-workspace/work-item-source-selection.test.ts": 1736,
|
||||
"src/renderer/src/components/onboarding/OnboardingInlineCommandTerminal.command-finished.test.tsx": 681,
|
||||
"src/renderer/src/components/onboarding/OnboardingLanguageLoading.test.tsx": 2167,
|
||||
"src/renderer/src/components/onboarding/onboarding-feature-setup.test.ts": 76,
|
||||
"src/renderer/src/components/pet/pet-blob-cache.test.ts": 64,
|
||||
@@ -5419,7 +5371,6 @@
|
||||
"src/renderer/src/components/right-sidebar/ai-vault/scanning/ai-vault-panel-session-list-request.test.tsx": 3044,
|
||||
"src/renderer/src/components/right-sidebar/ai-vault/search/ai-vault-search-session.test.ts": 201,
|
||||
"src/renderer/src/components/right-sidebar/ai-vault/accounts/ai-vault-session-account-render.test.tsx": 2885,
|
||||
"src/renderer/src/components/right-sidebar/ai-vault/scanning/ai-vault-session-conditional-refresh-hook.test.tsx": 2370,
|
||||
"src/renderer/src/components/right-sidebar/ai-vault/session-list/ai-vault-session-filters.test.ts": 105,
|
||||
"src/renderer/src/components/right-sidebar/ai-vault/scope/ai-vault-session-projects.test.ts": 117,
|
||||
"src/renderer/src/components/right-sidebar/ai-vault/scanning/ai-vault-session-refresh.test.ts": 2034,
|
||||
@@ -5435,7 +5386,6 @@
|
||||
"src/renderer/src/components/right-sidebar/checks-panel/gitlab-review-client.test.ts": 321,
|
||||
"src/renderer/src/components/right-sidebar/checks-panel/comments/review-comment-markdown.test.tsx": 2171,
|
||||
"src/renderer/src/components/right-sidebar/checks-panel/refresh/use-checks-panel-manual-refresh-recovery.test.tsx": 2909,
|
||||
"src/renderer/src/components/right-sidebar/checks-panel/refresh/use-checks-panel-polling.test.tsx": 2189,
|
||||
"src/renderer/src/lib/repository-refresh/coalesced-poll-runner.test.ts": 61,
|
||||
"src/renderer/src/components/right-sidebar/file-explorer/mutations/file-explorer-delete-undo-precondition.test.tsx": 2023,
|
||||
"src/renderer/src/components/right-sidebar/file-explorer/tree/file-explorer-dir-pages.test.ts": 1767,
|
||||
@@ -5457,7 +5407,6 @@
|
||||
"src/renderer/src/components/right-sidebar/plugin-panels/health/plugin-panel-watchdog.test.ts": 116,
|
||||
"src/renderer/src/components/right-sidebar/checks-panel/comments/pr-comments-ai-launch-ack.test.ts": 118,
|
||||
"src/renderer/src/components/right-sidebar/checks-panel/comments/pr-comments-list-selection.test.tsx": 3290,
|
||||
"src/renderer/src/components/right-sidebar/right-sidebar-titlebar-drag-regions.render.test.tsx": 1044,
|
||||
"src/renderer/src/components/right-sidebar/source-control/ai/runSourceControlAgentActionStart.test.ts": 1917,
|
||||
"src/renderer/src/components/right-sidebar/source-control/review/source-control-create-pr-intent-flow.test.ts": 71,
|
||||
"src/renderer/src/components/right-sidebar/source-control/review/source-control-manual-review-url.test.ts": 77,
|
||||
@@ -5485,7 +5434,6 @@
|
||||
"src/renderer/src/components/right-sidebar/file-explorer/mutations/useFileDeletion.save-refusal.test.tsx": 840,
|
||||
"src/renderer/src/components/right-sidebar/file-explorer/mutations/useFileDeletion.trash-failure.test.tsx": 774,
|
||||
"src/renderer/src/components/right-sidebar/file-explorer/mutations/useFileExplorerImport.committed-scope.test.tsx": 588,
|
||||
"src/renderer/src/components/right-sidebar/file-explorer/mutations/useFileExplorerImport.remote.test.tsx": 2054,
|
||||
"src/renderer/src/components/right-sidebar/file-explorer/tree/useFileExplorerTree.lifecycle.test.tsx": 1925,
|
||||
"src/renderer/src/components/right-sidebar/file-explorer/tree/useFileExplorerTree.paged-dirs.test.tsx": 2484,
|
||||
"src/renderer/src/components/right-sidebar/file-explorer/tree/useFileExplorerTree.scoped-root.test.tsx": 2131,
|
||||
@@ -5495,10 +5443,7 @@
|
||||
"src/renderer/src/components/right-sidebar/hosted-review/provider-actions/useHostedReviewStackParent.test.tsx": 288,
|
||||
"src/renderer/src/components/right-sidebar/source-control/listing/useSourceControlSubmoduleStatus.test.tsx": 2076,
|
||||
"src/renderer/src/components/settings/accounts/AccountsPane.owner-scope.test.tsx": 4057,
|
||||
"src/renderer/src/components/skills/setup/AgentSkillSetupPanel.freshness.test.tsx": 15418,
|
||||
"src/renderer/src/components/skills/setup/AgentSkillSetupPanel.plan-status.test.tsx": 23334,
|
||||
"src/renderer/src/components/skills/setup/AgentSkillSetupPanel.remote-availability.test.tsx": 5937,
|
||||
"src/renderer/src/components/skills/setup/AgentSkillSetupPanel.test.tsx": 2315,
|
||||
|
||||
"src/renderer/src/components/settings/agents/AgentsPane.test.tsx": 3230,
|
||||
"src/renderer/src/components/settings/accounts/providers/AntigravityAccountsSection.test.tsx": 2722,
|
||||
"src/renderer/src/components/settings/appearance/chat/AppearanceChatContrastControls.draft.test.tsx": 795,
|
||||
@@ -5506,10 +5451,8 @@
|
||||
"src/renderer/src/components/settings/browser/BrowserSitePermissionsSetting.test.tsx": 739,
|
||||
"src/renderer/src/components/settings/browser/BrowserUserAgentSetting.test.tsx": 2325,
|
||||
"src/renderer/src/components/settings/chat/ChatNamingSetting.test.tsx": 2454,
|
||||
"src/renderer/src/components/settings/chat/ChatPermissionSetting.test.tsx": 834,
|
||||
"src/renderer/src/components/settings/chat/ChatSettingsSection.navigation.test.tsx": 2540,
|
||||
"src/renderer/src/components/settings/chat/ChatSettingsSection.test.tsx": 2718,
|
||||
"src/renderer/src/lib/skill-runtime-command.test.ts": 1670,
|
||||
"src/renderer/src/lib/skills/runtime/skill-runtime-command.test.ts": 1670,
|
||||
"src/renderer/src/components/settings/virtual-machines/recipes/EphemeralVmsPane.test.tsx": 1025,
|
||||
"src/renderer/src/components/settings/accounts/sign-in/HostAccountSignInPrompt.test.tsx": 309,
|
||||
"src/renderer/src/components/settings/agents/launch/HostAgentLaunchSettings.test.tsx": 7498,
|
||||
@@ -5520,7 +5463,6 @@
|
||||
"src/renderer/src/components/settings/advanced/network/NodeDistMirrorDialog.test.tsx": 2412,
|
||||
"src/renderer/src/components/plugins/list/PluginsSettingsSection.lifecycle.test.tsx": 5402,
|
||||
"src/renderer/src/components/settings/runtime-environments/pairing/RuntimePairingGeneratorForm.test.tsx": 461,
|
||||
"src/renderer/src/components/settings/session-history/SessionHistorySettingsPane.test.tsx": 1474,
|
||||
"src/renderer/src/components/settings/appearance/fonts/FontAutocomplete.test.tsx": 1202,
|
||||
"src/renderer/src/components/settings/form-controls/SettingsFormControls.segmented-control.test.tsx": 730,
|
||||
"src/renderer/src/components/settings/shortcuts/ShortcutFilterRail.test.ts": 273,
|
||||
@@ -5535,12 +5477,9 @@
|
||||
"src/renderer/src/components/settings/TerminalAppearanceSection.ghostty.test.ts": 549,
|
||||
"src/renderer/src/components/settings/terminal/appearance/TerminalContrastSetting.test.tsx": 798,
|
||||
"src/renderer/src/components/settings/terminal/session-management/TerminalLimitSetting.test.tsx": 1015,
|
||||
"src/renderer/src/components/settings/terminal/TerminalPane.section-lifetime.test.tsx": 1237,
|
||||
"src/renderer/src/components/settings/terminal/appearance/TerminalSettingsPreview.lifecycle.test.tsx": 595,
|
||||
"src/renderer/src/components/settings/developer-permissions/TerminalTccAttributionNotice.test.tsx": 401,
|
||||
"src/renderer/src/components/settings/voice/VoiceMicrophoneSetting.test.tsx": 957,
|
||||
"src/renderer/src/components/settings/voice/VoicePane.test.tsx": 1042,
|
||||
"src/renderer/src/components/settings/voice/VoiceSpeechModelSection.test.tsx": 503,
|
||||
"src/renderer/src/components/settings/accounts/sign-in/account-add-cancel-target.test.ts": 217,
|
||||
"src/renderer/src/components/settings/accounts/usage/accounts-pane-opencode-credentials.test.ts": 519,
|
||||
"src/renderer/src/lib/agent-session/launch/agent-settings-update-queue.test.ts": 249,
|
||||
@@ -5550,7 +5489,6 @@
|
||||
"src/renderer/src/components/settings/developer-permissions/developer-permissions-search.test.ts": 308,
|
||||
"src/renderer/src/components/settings/shortcuts/keybinding-diagnostic-text.test.ts": 522,
|
||||
"src/renderer/src/components/settings/shortcuts/keybinding-title-copy.test.ts": 227,
|
||||
"src/renderer/src/lib/agent-session/launch/native-chat-provider-choice.test.tsx": 3738,
|
||||
"src/renderer/src/components/settings/notifications/notification-host-pending-save.test.tsx": 2029,
|
||||
"src/renderer/src/components/settings/repository/RepositoryJiraProjectSection.test.tsx": 463,
|
||||
"src/renderer/src/components/settings/repository/RepositoryPaneDraftInput.test.tsx": 314,
|
||||
@@ -5572,10 +5510,7 @@
|
||||
"src/renderer/src/components/settings/runtime-environments/catalog/use-runtime-environment-mutation-actions.test.tsx": 2069,
|
||||
"src/renderer/src/components/session-search/use-session-search-status.test.tsx": 477,
|
||||
"src/renderer/src/components/settings/accounts/usage/use-zcode-plan-credentials.test.tsx": 880,
|
||||
"src/renderer/src/lib/directory-path-suggestion-filter.scan-budget.test.ts": 68,
|
||||
"src/renderer/src/lib/directory-path-suggestion-filter.test.ts": 51,
|
||||
"src/renderer/src/components/setup-guide/SetupGuideModal.mount-gating.test.tsx": 2348,
|
||||
"src/renderer/src/components/shared/MacFolderAccessFixDialog.test.tsx": 1356,
|
||||
"src/renderer/src/components/shared/kill-all-terminal-surfaces.test.ts": 1925,
|
||||
"src/renderer/src/components/shared/useDaemonActions.test.tsx": 332,
|
||||
"src/renderer/src/components/sidebar/host-admission/ssh/AddRemoteHostDialog.config-picker.test.tsx": 1178,
|
||||
@@ -5597,7 +5532,6 @@
|
||||
"src/renderer/src/components/sidebar/SeveredTerminalDaemonBanner.test.tsx": 574,
|
||||
"src/renderer/src/components/sidebar/Sidebar.test.tsx": 833,
|
||||
"src/renderer/src/components/sidebar/SidebarAgentsList.test.tsx": 2985,
|
||||
"src/renderer/src/components/sidebar/sidebar-feedback/SidebarFeedbackDialog.test.tsx": 2529,
|
||||
"src/renderer/src/components/sidebar/StalledTerminalDaemonBanner.test.tsx": 320,
|
||||
"src/renderer/src/components/sidebar/workspace-board/viewport/WorkspaceKanbanLaneGrid.test.tsx": 360,
|
||||
"src/renderer/src/components/sidebar/workspace-card/surface/WorktreeCard.single-reference-details.test.tsx": 2032,
|
||||
@@ -5690,22 +5624,17 @@
|
||||
"src/renderer/src/components/sidebar/workspace-actions/parenting/worktree-parent-eligibility.test.ts": 68,
|
||||
"src/renderer/src/components/sidebar/worktree-list/listing/worktree-sort-label-ordering.test.ts": 114,
|
||||
"src/renderer/src/components/sidebar/wsl-host-offer-move.test.ts": 227,
|
||||
"src/renderer/src/components/skills/SkillFreshnessUpdateDialog.test.tsx": 913,
|
||||
"src/renderer/src/components/skills/SkillInstallDialog.test.tsx": 4429,
|
||||
"src/renderer/src/components/skills/SkillInstallManagementDialog.test.tsx": 3300,
|
||||
"src/renderer/src/components/skills/SkillSharedLinkRow.test.tsx": 817,
|
||||
|
||||
"src/renderer/src/components/skills/installation/SkillInstallManagementDialog.test.tsx": 3300,
|
||||
"src/renderer/src/components/skills/sharing/SkillSharedLinkRow.test.tsx": 817,
|
||||
"src/renderer/src/components/skills/SkillsPage.test.tsx": 3822,
|
||||
"src/renderer/src/components/skills/skill-agent-filter.test.ts": 274,
|
||||
"src/renderer/src/components/skills/skill-share-link.test.ts": 55,
|
||||
"src/renderer/src/components/skills/skill-share-package-selection.test.ts": 49,
|
||||
"src/renderer/src/components/skills/skills-filter.test.ts": 204,
|
||||
"src/renderer/src/components/skills/catalog/skill-agent-filter.test.ts": 274,
|
||||
|
||||
"src/renderer/src/components/sparse/sparse-directory-entry-input.test.ts": 207,
|
||||
"src/renderer/src/components/stats/usage-daily-chart.test.tsx": 333,
|
||||
"src/renderer/src/components/stats/usage-overview-model.test.ts": 364,
|
||||
"src/renderer/src/components/status-bar/ClaudeSwitcherMenu.owner-lifetime.test.tsx": 2317,
|
||||
"src/renderer/src/components/status-bar/NativeChatResumeStatusSegment.test.tsx": 2452,
|
||||
"src/renderer/src/components/status-bar/PortsStatusSegment.render-stability.test.tsx": 2161,
|
||||
"src/renderer/src/components/status-bar/SkillUpdateStatusSegment.test.tsx": 594,
|
||||
|
||||
"src/renderer/src/components/status-bar/SshStatusSegment.large-host-list.test.tsx": 1838,
|
||||
"src/renderer/src/components/status-bar/StatusBarUsageChangeNotices.test.tsx": 785,
|
||||
"src/renderer/src/components/status-bar/UpdateStatusSegment.test.tsx": 2484,
|
||||
@@ -5726,7 +5655,6 @@
|
||||
"src/renderer/src/components/status-bar/use-resource-pty-actions.test.tsx": 879,
|
||||
"src/renderer/src/components/status-bar/use-resource-usage-derived-model.test.tsx": 742,
|
||||
"src/renderer/src/components/tab-bar/CopyTabIdMenuItem.test.tsx": 428,
|
||||
"src/renderer/src/components/tab-bar/NativeChatNamingFailure.test.tsx": 1062,
|
||||
"src/renderer/src/components/tab-bar/TabBarCreateEntry.search.test.tsx": 3224,
|
||||
"src/renderer/src/components/tab-bar/TabBarItemRow.test.tsx": 2116,
|
||||
"src/renderer/src/components/tab-bar/TabBarQuickCommandItem.test.tsx": 384,
|
||||
@@ -5745,7 +5673,6 @@
|
||||
"src/renderer/src/components/tab-bar/tab-context-menu.test.tsx": 5620,
|
||||
"src/renderer/src/components/tab-bar/tab-create-entry-classifier.test.ts": 510,
|
||||
"src/renderer/src/components/tab-bar/tab-create-entry-local-path.test.ts": 2614,
|
||||
"src/renderer/src/components/tab-bar/tab-create-entry-preview.test.ts": 882,
|
||||
"src/renderer/src/components/tab-bar/tab-session-history-switch.test.ts": 2348,
|
||||
"src/renderer/src/components/tab-bar/tab-strip-growth-scroll.test.tsx": 2164,
|
||||
"src/renderer/src/components/tab-bar/tab-strip-pointer-activation.test.tsx": 2047,
|
||||
@@ -5801,7 +5728,6 @@
|
||||
"src/renderer/src/components/task-page/use-task-page-source-display.test.tsx": 5228,
|
||||
"src/renderer/src/components/terminal-pane/layout/close/RunningTerminalCloseDialog.test.tsx": 2303,
|
||||
"src/renderer/src/components/terminal-pane/session-fork/TerminalAgentSessionForkDialog.test.tsx": 266,
|
||||
"src/renderer/src/components/terminal-pane/titles/TerminalPaneHeaderOverlay.test.tsx": 1104,
|
||||
"src/renderer/src/components/terminal-pane/account-restart/detached/account-restart-queue-progress.test.ts": 1988,
|
||||
"src/renderer/src/components/terminal-pane/agent-completion/agent-completion-coordinator-attention-dispatch.test.ts": 301,
|
||||
"src/renderer/src/components/terminal-pane/agent-completion/agent-completion-coordinator-completion-replay-guard.test.ts": 318,
|
||||
@@ -5851,7 +5777,6 @@
|
||||
"src/renderer/src/components/terminal-pane/layout/close/pending-pane-close-confirmation.test.ts": 4695,
|
||||
"src/renderer/src/components/terminal-pane/layout/close/pending-runtime-pane-close.test.ts": 3487,
|
||||
"src/renderer/src/components/terminal-pane/layout/close/pending-split-close.test.ts": 4680,
|
||||
"tests/e2e/terminal-agent-pane-launch.unit.test.ts": 8045,
|
||||
"src/renderer/src/components/terminal-pane/snapshots/pty-buffer-serializer.test.ts": 53,
|
||||
"src/renderer/src/components/terminal-pane/pty-connection/agent-identity/pty-connection-command-finished-late-done.test.ts": 10940,
|
||||
"src/renderer/src/components/terminal-pane/pty-connection/tests/pty-connection-completion-and-notification.test.ts": 18380,
|
||||
@@ -5899,7 +5824,6 @@
|
||||
"src/renderer/src/components/terminal-pane/pty-connection/host-ownership/unserved-ssh-pane-bridge.test.ts": 70,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/delivery/pty-dispatcher-delivery-resync.test.ts": 85,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/delivery/pty-dispatcher-pi-routing.test.ts": 1362,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/delivery/pty-dispatcher-push-reattach.test.ts": 108,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/input/pty-input-write-queue.test.ts": 787,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/delivery/pty-model-restore-channel.test.ts": 44,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/output/pty-output-processor-program-activity.test.ts": 160,
|
||||
@@ -5912,7 +5836,6 @@
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/shutdown/pty-shutdown-exit-deferral.test.ts": 121,
|
||||
"src/renderer/src/components/terminal-pane/viewport/pty-size-reassertion.test.ts": 58,
|
||||
"src/renderer/src/components/terminal-pane/viewport/pty-size-reconcile.test.ts": 68,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/ipc/pty-transport-connect-spawn.test.ts": 3186,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/ipc/pty-transport-detach-attach-handoff.test.ts": 1199,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/ipc/pty-transport-eager-buffer-replay.test.ts": 1636,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/ipc/pty-transport-handler-suspension.test.ts": 1243,
|
||||
@@ -5937,7 +5860,6 @@
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/remote-runtime/remote-runtime-pty-query-reply-immediate.test.ts": 1556,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/remote-runtime/recovery/remote-runtime-pty-recovery-state.test.ts": 85,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/remote-runtime/remote-runtime-pty-transport-activation-inventory-fallback.test.ts": 1311,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/remote-runtime/remote-runtime-pty-transport-attach-subscription.test.ts": 2346,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/remote-runtime/remote-runtime-pty-transport-create-handoff.test.ts": 14353,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/remote-runtime/remote-runtime-pty-transport-create-outcome-recovery.test.ts": 2041,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/remote-runtime/remote-runtime-pty-transport-empty-initial-snapshot.test.ts": 1491,
|
||||
@@ -5986,13 +5908,9 @@
|
||||
"src/renderer/src/components/terminal-pane/input/paste/terminal-bracketed-paste.test.ts": 57,
|
||||
"src/renderer/src/components/terminal-pane/emulation/terminal-capability-replies.test.ts": 131,
|
||||
"src/renderer/src/components/terminal-pane/clipboard/terminal-clipboard-paste.test.ts": 76,
|
||||
"src/renderer/src/components/terminal-pane/parking/retention/terminal-cold-park-timer-rearm.test.tsx": 701,
|
||||
"src/renderer/src/components/terminal-pane/input/file-drop/terminal-drop-handler.test.ts": 638,
|
||||
"src/renderer/src/components/terminal-pane/input/file-drop/terminal-drop-image-path.test.ts": 61,
|
||||
"src/renderer/src/components/terminal-pane/input/file-drop/terminal-drop-internal-handler.test.ts": 800,
|
||||
"src/renderer/src/components/terminal-pane/input/file-drop/terminal-drop-path-writer.test.ts": 245,
|
||||
"src/renderer/src/components/terminal-pane/input/file-drop/terminal-drop-runtime-catalog-owner.test.ts": 872,
|
||||
"src/renderer/src/components/terminal-pane/input/file-drop/terminal-drop-source-owner.test.ts": 622,
|
||||
"src/renderer/src/components/terminal-pane/viewport/terminal-fit-restore.test.ts": 59,
|
||||
"src/renderer/src/components/terminal-pane/links/handles/terminal-handle-links.test.ts": 527,
|
||||
"src/renderer/src/components/terminal-pane/parking/retention/terminal-hidden-view-parking.test.ts": 325,
|
||||
@@ -6025,7 +5943,6 @@
|
||||
"src/shared/workspace-layout/terminal-layout-pty-ownership-depth.test.ts": 82,
|
||||
"src/renderer/src/components/terminal-pane/layout/terminal-layout-pty-ownership.test.ts": 99,
|
||||
"src/renderer/src/components/terminal-pane/links/terminal-link-click-fallback.test.ts": 985,
|
||||
"src/renderer/src/components/terminal-pane/links/files/terminal-link-file-open-routing.test.ts": 970,
|
||||
"src/renderer/src/components/terminal-pane/links/terminal-link-open-beside-source.test.ts": 947,
|
||||
"src/renderer/src/components/terminal-pane/links/http/terminal-link-osc-url-routing.test.ts": 986,
|
||||
"src/renderer/src/components/terminal-pane/links/terminal-link-paired-click-fallback.test.ts": 989,
|
||||
@@ -6043,14 +5960,11 @@
|
||||
"src/renderer/src/components/terminal-pane/layout/reconciliation/terminal-pane-frame-reconciliation.test.ts": 903,
|
||||
"src/renderer/src/components/terminal-pane/host-state/terminal-pane-host-state-memo.test.ts": 4534,
|
||||
"src/renderer/src/components/terminal-pane/mounting/terminal-pane-mount-bootstrap.test.ts": 1723,
|
||||
"src/renderer/src/components/terminal-pane/render-health/recovery/terminal-pane-recovery-unsettled-fallback.test.ts": 831,
|
||||
"src/renderer/src/components/terminal-pane/render-health/recovery/terminal-pane-recovery.test.ts": 949,
|
||||
"src/renderer/src/components/terminal-pane/layout/split/terminal-pane-split-request-routing.test.ts": 2015,
|
||||
"src/renderer/src/components/terminal-pane/pty-transport/recovery/terminal-pane-surface-ownership.test.ts": 426,
|
||||
"src/renderer/src/components/terminal-pane/layout/detach/terminal-pane-tab-detach-main-commit.test.ts": 2090,
|
||||
"src/renderer/src/components/terminal-pane/layout/detach/terminal-pane-tab-detach-main-move.test.ts": 2147,
|
||||
"src/renderer/src/components/terminal-pane/parking/verdict/terminal-park-verdict-flip-telemetry.test.ts": 123,
|
||||
"src/renderer/src/components/terminal-pane/parking/verdict/terminal-park-verdict-worktree-driver-loop.test.tsx": 735,
|
||||
"src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-tab-watchers.test.ts": 473,
|
||||
"src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-watcher-reconciliation.test.ts": 243,
|
||||
"src/renderer/src/components/terminal-pane/parking/output-watchers/terminal-parked-watcher-registry.test.ts": 245,
|
||||
@@ -6172,8 +6086,7 @@
|
||||
"src/renderer/src/hooks/editor-external-watch-overflow.test.ts": 1023,
|
||||
"src/renderer/src/hooks/editor-external-watch-selected-host.test.ts": 1988,
|
||||
"src/renderer/src/hooks/editor-runtime-file-watch.test.ts": 58,
|
||||
"src/renderer/src/hooks/installed-agent-skill-discovery-cache.test.ts": 53,
|
||||
"src/renderer/src/hooks/installed-agent-skill-discovery.test.ts": 74,
|
||||
|
||||
"src/renderer/src/hooks/ipc-events/agent-status-pane-routing-index-retention.test.ts": 4878,
|
||||
"src/renderer/src/hooks/ipc-events/agent-status-pending-retry-gate.test.ts": 466,
|
||||
"src/renderer/src/hooks/ipc-events/agent-status-terminal-title-tab-write.test.ts": 2247,
|
||||
@@ -6210,7 +6123,7 @@
|
||||
"src/renderer/src/hooks/runtime-project-refresh-scheduler.test.ts": 65,
|
||||
"src/renderer/src/hooks/shortcut-label-cache.test.tsx": 2021,
|
||||
"src/renderer/src/hooks/unpaired-device-auth-notification.test.ts": 41,
|
||||
"src/renderer/src/hooks/use-bundled-skill-install.test.tsx": 553,
|
||||
|
||||
"src/renderer/src/hooks/use-document-dark-theme.test.tsx": 350,
|
||||
"src/renderer/src/hooks/use-list-multi-selection.test.tsx": 545,
|
||||
"src/renderer/src/hooks/use-monaco-theme.test.tsx": 323,
|
||||
@@ -6236,9 +6149,8 @@
|
||||
"src/renderer/src/hooks/useEphemeralVmRecipeOptions.test.tsx": 415,
|
||||
"src/renderer/src/hooks/useGitHubSlugMetadata.assignee-reuse.test.tsx": 233,
|
||||
"src/renderer/src/hooks/useImmediateMutation.test.ts": 618,
|
||||
"src/renderer/src/hooks/useInstalledAgentSkills.react.test.tsx": 2093,
|
||||
"src/renderer/src/hooks/skills/discovery/useInstalledAgentSkills.react.test.tsx": 2093,
|
||||
"src/renderer/src/hooks/useIpcEvents-agent-status-connection-attribution.test.ts": 5510,
|
||||
"src/renderer/src/hooks/useIpcEvents-agent-status-hook-titles.test.ts": 5621,
|
||||
"src/renderer/src/hooks/useIpcEvents-agent-status-pane-teardown.test.ts": 5268,
|
||||
"src/renderer/src/hooks/useIpcEvents-agent-status-queue-ordering.test.ts": 3680,
|
||||
"src/renderer/src/hooks/useIpcEvents-agent-status-snapshot-hydration.test.ts": 7403,
|
||||
@@ -6252,11 +6164,9 @@
|
||||
"src/renderer/src/hooks/useIpcEvents-cmd-j-digit-chord.test.ts": 2703,
|
||||
"src/renderer/src/hooks/useIpcEvents-lifecycle.test.ts": 2326,
|
||||
"src/renderer/src/hooks/useIpcEvents-new-workspace-shortcut.test.ts": 72,
|
||||
"src/renderer/src/hooks/useIpcEvents-rate-limit-hydration.test.ts": 1597,
|
||||
"src/renderer/src/hooks/useIpcEvents-runtime-environment-selectors.test.ts": 530,
|
||||
"src/renderer/src/hooks/useIpcEvents-session-tab-close-request.test.ts": 2252,
|
||||
"src/renderer/src/hooks/useIssueMetadata.test.tsx": 344,
|
||||
"src/renderer/src/hooks/useMacTccAttributionSeveredNotice.test.tsx": 2358,
|
||||
"src/renderer/src/hooks/useMetadataListRequest.test.tsx": 266,
|
||||
"src/renderer/src/hooks/useModalReturnFocus.test.tsx": 1938,
|
||||
"src/renderer/src/hooks/clipboard/primary-selection/usePrimarySelectionPaste.terminal-native-paste.test.tsx": 388,
|
||||
@@ -6268,7 +6178,7 @@
|
||||
"src/renderer/src/hooks/useReadOnScreenAttention.mixed-workspace.test.ts": 1725,
|
||||
"src/renderer/src/hooks/useReadOnScreenAttention.test.ts": 1915,
|
||||
"src/renderer/src/hooks/useRetiredWorktreeNames.test.ts": 593,
|
||||
"src/renderer/src/hooks/useSkillFreshness.test.tsx": 554,
|
||||
|
||||
"src/renderer/src/hooks/useUnreadDockBadge.test.ts": 2126,
|
||||
"src/renderer/src/hooks/virtualized-hidden-row-measurement.test.ts": 199,
|
||||
"src/renderer/src/hooks/worktree-change-refresh-queue.test.ts": 59,
|
||||
@@ -6292,8 +6202,6 @@
|
||||
"src/renderer/src/lib/agent-session/hibernation/agent-hibernation-pane-age.test.ts": 41,
|
||||
"src/renderer/src/lib/agent-session/hibernation/agent-hibernation-planner.test.ts": 341,
|
||||
"src/renderer/src/lib/agent-session/hibernation/agent-hibernation-runtime-liveness-race.test.ts": 1914,
|
||||
"src/renderer/src/lib/agent-session/launch/new-tab/agent-launch-caller-prompt-transport.test.ts": 1326,
|
||||
"src/renderer/src/lib/agent-session/launch/new-tab/agent-launch-caller-routing.test.ts": 1266,
|
||||
"src/renderer/src/lib/agent-session/launch/pane/agent-launch-pane-verdict-application.test.ts": 1869,
|
||||
"src/renderer/src/lib/agent-session/launch/routing/agent-launch-route-input.test.ts": 1659,
|
||||
"src/renderer/src/lib/agent-session/launch/routing/agent-launch-route-registered-agents.test.ts": 1749,
|
||||
@@ -6347,7 +6255,7 @@
|
||||
"src/renderer/src/lib/browser/navigation/browser-link-profile-isolation.test.ts": 2511,
|
||||
"src/renderer/src/lib/browser/palette/browser-page-palette-activation.test.ts": 1983,
|
||||
"src/renderer/src/lib/browser/palette/browser-palette-page-entries.test.ts": 480,
|
||||
"src/renderer/src/lib/bundled-skill-target.test.ts": 54,
|
||||
"src/renderer/src/lib/skills/runtime/bundled-skill-target.test.ts": 54,
|
||||
"src/renderer/src/lib/source-control/checks/check-run-details-log-normalization-performance.test.ts": 846,
|
||||
"src/renderer/src/lib/source-control/checks/check-run-details-log-normalization.test.ts": 75,
|
||||
"src/renderer/src/lib/claude-account-switch-sessions.test.ts": 782,
|
||||
@@ -6364,7 +6272,6 @@
|
||||
"src/renderer/src/lib/source-control/review/comments/comment-body-submit-state.test.ts": 55,
|
||||
"src/renderer/src/lib/composer-submit-cancellation.test.ts": 41,
|
||||
"src/renderer/src/lib/workspace/ownership/connection-context.test.ts": 1817,
|
||||
"src/renderer/src/lib/crash-diagnostics.test.ts": 176,
|
||||
"src/renderer/src/lib/create-untitled-markdown.test.ts": 566,
|
||||
"src/renderer/src/lib/desktop-created-server-tabs.test.ts": 1933,
|
||||
"src/renderer/src/lib/workspace/ownership/direct-ssh-target-scope.test.ts": 48,
|
||||
@@ -6373,21 +6280,14 @@
|
||||
"src/renderer/src/lib/browser/documents/doc-preview-grants.test.ts": 2094,
|
||||
"src/renderer/src/lib/editor/file-operations/editor-file-operation-owner.test.ts": 2848,
|
||||
"src/renderer/src/lib/emulator-error-copy.test.ts": 415,
|
||||
"src/renderer/src/lib/ensure-hooks-confirmed.test.ts": 799,
|
||||
"src/renderer/src/runtime/repo-hooks/ensure-hooks-confirmed.test.ts": 799,
|
||||
"src/renderer/src/lib/simulator/tabs/ensure-simulator-tab-behavior.test.ts": 3601,
|
||||
"src/renderer/src/runtime/hosts/platform/execution-host-facts.test.ts": 1796,
|
||||
"src/renderer/src/lib/feature-education-telemetry.test.ts": 52,
|
||||
"src/renderer/src/lib/feedback-image-attachments.test.ts": 557,
|
||||
"src/renderer/src/lib/file-search-selection.test.ts": 51,
|
||||
"src/renderer/src/lib/find-query-bounds.test.ts": 45,
|
||||
"src/renderer/src/components/sidebar/sidebar-feedback/feedback-image-attachments.test.ts": 557,
|
||||
"src/renderer/src/lib/files/search/file-search-selection.test.ts": 51,
|
||||
"src/renderer/src/lib/finished-agent-resume-resurrection.test.ts": 1872,
|
||||
"src/renderer/src/lib/focus-terminal-tab-surface.split-focus.test.ts": 331,
|
||||
"src/renderer/src/lib/foreground-terminal-tabs.test.ts": 55,
|
||||
"src/shared/new-workspace/github-links.test.ts": 76,
|
||||
"src/renderer/src/components/terminal-pane/parking/retention/foreground-terminal-tabs.test.ts": 55,
|
||||
"src/renderer/src/lib/work-items/github/github-source-runtime-context.test.ts": 62,
|
||||
"src/shared/new-workspace/gitlab-links.test.ts": 56,
|
||||
"src/renderer/src/lib/hook-command-delayed-delivery.test.ts": 1904,
|
||||
"src/renderer/src/lib/host-chat-program.test.ts": 2419,
|
||||
"src/renderer/src/lib/host-mirror-handle-gap-drain.test.ts": 1706,
|
||||
"src/renderer/src/lib/host-mirror-handle-gap-resume.test.ts": 1811,
|
||||
"src/renderer/src/lib/host-mirrored-pane-resume-replay.test.ts": 1814,
|
||||
@@ -6409,10 +6309,7 @@
|
||||
"src/renderer/src/lib/workspace/creation/work-item/launch-work-item-direct-accepted.test.tsx": 2754,
|
||||
"src/renderer/src/lib/workspace/creation/work-item/launch-work-item-direct-defaults.test.ts": 1594,
|
||||
"src/renderer/src/lib/workspace/creation/work-item/launch-work-item-direct-setup.test.tsx": 3435,
|
||||
"src/renderer/src/lib/lazy-chunk-recovery-reload.test.ts": 246,
|
||||
"src/renderer/src/lib/lazy-with-retry.never-landed-reload.test.ts": 194,
|
||||
"src/renderer/src/lib/lazy-with-retry.preload.test.tsx": 208,
|
||||
"src/renderer/src/lib/lazy-with-retry.test.ts": 282,
|
||||
"src/renderer/src/app-shell/startup/lazy-with-retry.never-landed-reload.test.ts": 194,
|
||||
"src/renderer/src/lib/work-items/linear/linear-board-drag-payload.test.ts": 58,
|
||||
"src/renderer/src/lib/work-items/linear/linear-issue-workspace-attachment.test.ts": 99,
|
||||
"src/renderer/src/lib/link-source-local-open-owner.test.ts": 433,
|
||||
@@ -6432,37 +6329,25 @@
|
||||
"src/renderer/src/lib/monaco-languages/textmate-token-provider.test.ts": 245,
|
||||
"src/renderer/src/lib/monaco-languages/zig-highlighting.test.ts": 7984,
|
||||
"src/renderer/src/lib/agent-session/resume/cli-fork/native-chat-cli-fork-preparation.test.ts": 2773,
|
||||
"src/renderer/src/lib/new-workspace.test.ts": 4534,
|
||||
"src/renderer/src/lib/non-secure-context-crypto.repro.test.ts": 1691,
|
||||
"src/renderer/src/lib/onboarding-folder-cancellation.test.ts": 2486,
|
||||
"src/renderer/src/lib/open-agent-message-sender.test.ts": 1497,
|
||||
"src/renderer/src/lib/simulator/launch/open-mobile-emulator-tab.test.ts": 545,
|
||||
"src/renderer/src/lib/orca-yaml-trust-prompt-slot-eviction.test.ts": 884,
|
||||
"src/renderer/src/lib/order-empty-query-worktrees.test.ts": 62,
|
||||
"src/renderer/src/lib/os-file-drop-cancellation-guard.test.ts": 204,
|
||||
"src/renderer/src/lib/os-file-drop-preload-integration.test.tsx": 353,
|
||||
"src/renderer/src/lib/files/drop/os-file-drop-cancellation-guard.test.ts": 204,
|
||||
"src/renderer/src/lib/paired-runtime-closed-tab-resume.test.ts": 2008,
|
||||
"src/renderer/src/lib/pane-manager/pane-close-focus-successor.test.ts": 1123,
|
||||
"src/renderer/src/lib/pane-manager/pane-container-listener-lifecycle.test.ts": 312,
|
||||
"src/renderer/src/lib/pane-manager/pane-cursor-blink-suspension.test.ts": 429,
|
||||
"src/renderer/src/lib/pane-manager/pane-drag-window-blur.test.ts": 618,
|
||||
"src/renderer/src/lib/pane-manager/pane-fit-resize-observer.test.ts": 94,
|
||||
"src/renderer/src/lib/pane-manager/pane-fit.test.ts": 166,
|
||||
"src/renderer/src/lib/pane-manager/pane-inline-image-recovery.test.ts": 61,
|
||||
"src/renderer/src/lib/pane-manager/pane-inline-images.test.ts": 74,
|
||||
"src/renderer/src/lib/pane-manager/pane-layout-geometry-apply.test.ts": 897,
|
||||
"src/renderer/src/lib/pane-manager/pane-manager-registry.test.ts": 69,
|
||||
"src/renderer/src/lib/pane-manager/pane-manager-spawn-placement.test.ts": 766,
|
||||
"src/renderer/src/lib/pane-manager/pane-overlay-focus.test.ts": 622,
|
||||
"src/renderer/src/lib/pane-manager/pane-scroll.test.ts": 153,
|
||||
"src/renderer/src/lib/pane-manager/pane-terminal-foreground-render-settle.test.ts": 43,
|
||||
"src/renderer/src/lib/pane-manager/pane-terminal-mouse-wheel.test.ts": 88,
|
||||
"src/renderer/src/lib/pane-manager/pane-terminal-output-queue-chunks.test.ts": 44,
|
||||
"src/renderer/src/lib/pane-manager/pane-terminal-output-scheduler-ack-credit.test.ts": 173,
|
||||
"src/renderer/src/lib/pane-manager/pane-terminal-output-scheduler-disposed-writes.test.ts": 121,
|
||||
"src/renderer/src/lib/pane-manager/pane-terminal-output-scheduler-queue-retention.test.ts": 301,
|
||||
"src/renderer/src/lib/pane-manager/pane-terminal-output-scheduler-synchronized-frames.test.ts": 213,
|
||||
"src/renderer/src/lib/pane-manager/pane-terminal-output-scheduler.test.ts": 236,
|
||||
"src/renderer/src/lib/pane-manager/pane-tree-equalization-parity.test.ts": 182,
|
||||
"src/renderer/src/lib/pane-manager/pane-tree-equalization-scaling.test.ts": 239,
|
||||
"src/renderer/src/lib/pane-manager/pane-tree-match-moves.test.ts": 662,
|
||||
@@ -6479,7 +6364,6 @@
|
||||
"src/renderer/src/lib/pane-manager/terminal-indic-cluster-ranges.test.ts": 50,
|
||||
"src/renderer/src/lib/pane-manager/terminal-kitty-file-reader.test.ts": 83,
|
||||
"src/renderer/src/lib/pane-manager/terminal-ligatures-addon.test.ts": 59,
|
||||
"src/renderer/src/lib/pane-manager/terminal-link-provider-guard.test.ts": 48,
|
||||
"src/renderer/src/lib/pane-manager/terminal-linkifier-hover-reset-on-write.test.ts": 59,
|
||||
"src/renderer/src/lib/pane-manager/terminal-mouse-encoding-tracker.test.ts": 95,
|
||||
"src/renderer/src/lib/pane-manager/terminal-mouse-report-finite-coordinates.test.ts": 272,
|
||||
@@ -6497,30 +6381,24 @@
|
||||
"src/renderer/src/lib/pane-manager/xterm-instance-disposed.test.ts": 57,
|
||||
"src/renderer/src/lib/pane-manager/xterm-parse-barrier.test.ts": 154,
|
||||
"src/renderer/src/lib/pane-manager/xterm-user-scrolling-contract.test.ts": 1266,
|
||||
"src/renderer/src/lib/pane-manager/xterm-write-callback-guard.test.ts": 53,
|
||||
"src/renderer/src/lib/pane-spawn-deferral-drain.test.ts": 61,
|
||||
"src/renderer/src/lib/parked-terminal-host-hydration.test.ts": 274,
|
||||
"src/renderer/src/components/terminal-pane/session-restore/spawn-deferral/pane-spawn-deferral-drain.test.ts": 61,
|
||||
"src/renderer/src/components/terminal-pane/mounting/parked-terminal-host-hydration.test.ts": 274,
|
||||
"src/renderer/src/lib/text-input/paste/paste-payload-metadata.test.ts": 53,
|
||||
"src/renderer/src/lib/path-head-elision.test.ts": 53,
|
||||
"src/renderer/src/lib/path-display/path-head-elision.test.ts": 53,
|
||||
"src/renderer/src/lib/path.test.ts": 55,
|
||||
"src/renderer/src/lib/plugin-command-keybindings.test.ts": 1909,
|
||||
"src/renderer/src/lib/plugin-command-replacements.test.ts": 95,
|
||||
"src/renderer/src/lib/plugin-icons/plugin-icon-svg.test.ts": 231,
|
||||
"src/renderer/src/lib/plugin-monaco-token-rules.test.ts": 51,
|
||||
"src/renderer/src/lib/editor/appearance/plugin-monaco-token-rules.test.ts": 51,
|
||||
"src/renderer/src/lib/source-control/review/pr-bot-author-overrides.test.ts": 349,
|
||||
"src/renderer/src/lib/source-control/review/comments/pr-comment-thread-resolution.test.ts": 48,
|
||||
"src/renderer/src/lib/project-clone-url-prefill.test.ts": 61,
|
||||
"src/renderer/src/lib/project-host-workspace-target.jira-mapping.test.ts": 76,
|
||||
"src/renderer/src/lib/project-host-workspace-target.test.ts": 92,
|
||||
"src/renderer/src/lib/react-commit-cascade-observer.react185.test.tsx": 285,
|
||||
"src/renderer/src/lib/react-commit-cascade-observer.test.ts": 189,
|
||||
"src/renderer/src/lib/react-commit-cascade-telemetry.test.ts": 159,
|
||||
"src/renderer/src/lib/react-error-boundary-reporting.test.ts": 55,
|
||||
"src/renderer/src/lib/workspace/creation/project-clone-url-prefill.test.ts": 61,
|
||||
"src/renderer/src/lib/workspace/creation/project-host-workspace-target.jira-mapping.test.ts": 76,
|
||||
"src/renderer/src/lib/workspace/creation/project-host-workspace-target.test.ts": 92,
|
||||
"src/renderer/src/lib/editor/file-operations/remap-open-editor-tabs-for-path-change.test.ts": 2178,
|
||||
"src/renderer/src/lib/rename-user-named-tab-access.test.ts": 2804,
|
||||
"src/renderer/src/lib/renderer-agent-status-observation-ingress.test.ts": 81,
|
||||
"src/renderer/src/lib/renderer-app-platform.test.ts": 197,
|
||||
"src/renderer/src/lib/renderer-memory-profile.test.ts": 70,
|
||||
"src/renderer/src/diagnostics/memory/renderer-memory-profile.test.ts": 70,
|
||||
"src/renderer/src/lib/repo-search.test.ts": 54,
|
||||
"src/renderer/src/lib/repo-slug-cache.test.ts": 52,
|
||||
"src/renderer/src/lib/repo-slug-index.test.ts": 2240,
|
||||
@@ -6543,7 +6421,6 @@
|
||||
"src/renderer/src/lib/script-textarea-rows.test.ts": 93,
|
||||
"src/renderer/src/lib/session-write-subscriber-acknowledgment.test.ts": 1823,
|
||||
"src/renderer/src/lib/session-write-subscriber.test.ts": 1882,
|
||||
"src/renderer/src/lib/shutdown-checkpoint-guard.test.ts": 209,
|
||||
"src/renderer/src/lib/sidebar-ended-creations.test.ts": 1889,
|
||||
"src/renderer/src/lib/sidebar-pending-layer.test.ts": 338,
|
||||
"src/renderer/src/lib/sidebar-shadow/workspace-activity-shadow.test.ts": 1728,
|
||||
@@ -6552,10 +6429,9 @@
|
||||
"src/renderer/src/lib/simulator/tabs/simulator-pane-shutdown-scheduler.test.ts": 1679,
|
||||
"src/renderer/src/lib/simulator/tabs/simulator-tab-layout-owner.test.ts": 2398,
|
||||
"src/renderer/src/lib/simulator/tabs/simulator-tab-palette-activation.test.ts": 1903,
|
||||
"src/renderer/src/lib/sleeping-agent-session-launch-windows-quoting.test.ts": 547,
|
||||
"src/renderer/src/lib/source-control/remote/source-control-remote-error.test.ts": 340,
|
||||
"src/renderer/src/lib/ssh-config-passive-sync.test.ts": 1513,
|
||||
"src/renderer/src/lib/state-collection-byte-estimate.test.ts": 86,
|
||||
"src/renderer/src/diagnostics/memory/state-collection-byte-estimate.test.ts": 86,
|
||||
"src/renderer/src/lib/agent-session/launch/structured-agent-session-launch-draft.test.ts": 1042,
|
||||
"src/renderer/src/lib/agent-session/launch/structured-agent-session-launch-prerequisites.test.ts": 2427,
|
||||
"src/renderer/src/lib/agent-session/options/structured-agent-session-selection-lifetime.test.tsx": 2947,
|
||||
@@ -6567,7 +6443,7 @@
|
||||
"src/renderer/src/lib/syntax-highlighting/textmate-core.test.ts": 60,
|
||||
"src/renderer/src/lib/tab-agent-status-index.test.ts": 210,
|
||||
"src/renderer/src/lib/task-provider-error-copy.test.ts": 363,
|
||||
"src/renderer/src/lib/terminal-app-theme.test.ts": 301,
|
||||
"src/renderer/src/app-shell/appearance/terminal-app-theme.test.ts": 301,
|
||||
"src/renderer/src/lib/terminal-input-activity-coalescing.test.ts": 43,
|
||||
"src/renderer/src/lib/text-input/paste/text-control-paste-ownership.test.ts": 217,
|
||||
"src/renderer/src/lib/text-input/paste/text-control-paste.test.ts": 222,
|
||||
@@ -6579,17 +6455,10 @@
|
||||
"src/renderer/src/lib/use-tab-agent-observed-signal-dispatch.test.tsx": 1971,
|
||||
"src/renderer/src/lib/use-tab-agent-opencode-native-title.test.ts": 2093,
|
||||
"src/renderer/src/lib/use-tab-agent.test.ts": 1961,
|
||||
"src/renderer/src/lib/user-opened-local-path.test.ts": 325,
|
||||
"src/renderer/src/lib/wake-sleeping-agents-live-unmounted-pane.test.ts": 2432,
|
||||
"src/renderer/src/lib/window-visibility-interval.test.ts": 48,
|
||||
"src/renderer/src/lib/window-visibility-timeout-poller.test.ts": 207,
|
||||
"src/renderer/src/lib/windows-terminal-capabilities-race.test.ts": 450,
|
||||
"src/renderer/src/lib/windows-terminal-capabilities.test.ts": 585,
|
||||
"src/renderer/src/lib/windows-terminal-capability-reprobe.test.ts": 198,
|
||||
"src/renderer/src/runtime/hosts/capabilities/windows-terminal-capabilities-race.test.ts": 450,
|
||||
"src/renderer/src/lib/workspace/activation/workspace-activation-path-gate.test.ts": 2107,
|
||||
"src/renderer/src/lib/browser/workspace/workspace-browser-tab-open-placement.test.ts": 1996,
|
||||
"src/renderer/src/lib/workspace-doc-address-input.test.ts": 470,
|
||||
"src/renderer/src/lib/workspace-file-drag.test.ts": 70,
|
||||
"src/renderer/src/lib/workspace-ports/workspace-port-scan-debounce.test.ts": 57,
|
||||
"src/renderer/src/lib/workspace/persistence/workspace-session-host-contention.test.ts": 265,
|
||||
"src/renderer/src/lib/workspace/persistence/workspace-session-host-emptied-fields.test.ts": 279,
|
||||
@@ -6679,7 +6548,6 @@
|
||||
"src/renderer/src/runtime/workspace-layout/server/server-layout-frames.test.ts": 2053,
|
||||
"src/renderer/src/runtime/native-chat/status/structured-agent-session-status-feed-lifecycle.test.ts": 62,
|
||||
"src/renderer/src/runtime/native-chat/status/structured-agent-session-status-feed.test.ts": 82,
|
||||
"src/renderer/src/runtime/native-chat/tab-retirement/structured-agent-session-tab-retirement.test.ts": 2115,
|
||||
"src/renderer/src/runtime/native-chat/status/structured-agent-session-turn-completion-feed.test.ts": 118,
|
||||
"src/renderer/src/runtime/native-chat/host-capabilities/structured-chat-host-permission.test.ts": 523,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/placement/structured-conversation-tab-replacement.test.ts": 2029,
|
||||
@@ -6696,11 +6564,6 @@
|
||||
"src/renderer/src/runtime/browser/creation/web-runtime-browser-creation-placement.test.ts": 1927,
|
||||
"src/renderer/src/runtime/browser/creation/web-runtime-browser-link-open.test.ts": 2217,
|
||||
"src/renderer/src/runtime/browser/creation/web-runtime-browser-link-session.test.ts": 1964,
|
||||
"src/renderer/src/runtime/browser/creation/web-runtime-session-browser-create-split-placement.test.ts": 949,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/closing/web-runtime-session-tab-activate-close.test.ts": 1426,
|
||||
"src/renderer/src/runtime/hosted-terminals/actions/web-runtime-session-terminal-pane-delegation.test.ts": 1341,
|
||||
"src/renderer/src/runtime/hosted-terminals/creation/web-runtime-session-terminal-workspace-routing.test.ts": 768,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/inventory/web-runtime-session.test.ts": 743,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/closing/web-session-close-replay.test.ts": 1119,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/placement/web-session-open-files-batch-equivalence.test.ts": 1478,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/identity/web-session-restored-placeholder-identity.test.ts": 985,
|
||||
@@ -6709,7 +6572,6 @@
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/subscriptions/web-session-tabs-stream-end-resubscribe.test.tsx": 2282,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/agent-status/web-session-tabs-sync-agent-status.test.ts": 987,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/placement/web-session-tabs-sync-browser-tabs.test.ts": 925,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/subscriptions/web-session-tabs-sync-completion-on-reveal.test.tsx": 2249,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/identity/web-session-tabs-sync-cross-runtime-worktree.test.ts": 964,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/placement/web-session-tabs-sync-editor-ownership.test.ts": 1902,
|
||||
"src/renderer/src/runtime/web-session-tabs-sync/placement/web-session-tabs-sync-editor-tabs.test.ts": 1073,
|
||||
@@ -6803,7 +6665,6 @@
|
||||
"src/renderer/src/store/slices/browser/pages/browser-workspace-doc-location.test.ts": 2007,
|
||||
"src/renderer/src/store/slices/browser/browser.test.ts": 2001,
|
||||
"src/renderer/src/store/slices/worktrees/teardown/bulk-worktree-purge-terminal-maps-leak.test.ts": 1727,
|
||||
"src/renderer/src/store/workspaces/creation/active-workspace-create-actions.test.ts": 1879,
|
||||
"src/renderer/src/store/terminals/codex-restart-notice-lifecycle.test.ts": 1685,
|
||||
"src/renderer/src/store/slices/tabs/content-tabs-from-main-frames.test.ts": 2025,
|
||||
"src/renderer/src/store/slices/tabs/content-tabs-paired-server-workspace.test.ts": 1923,
|
||||
@@ -7994,7 +7855,7 @@
|
||||
"tests/e2e/ai-vault-account-stream.unit.test.ts": 4506,
|
||||
"tests/e2e/ai-vault-manual-name-clear.unit.test.ts": 21206,
|
||||
"tests/e2e/automation-chat-reopen.unit.test.ts": 6262,
|
||||
"tests/e2e/automation-save-fallback.unit.test.ts": 9065,
|
||||
|
||||
"tests/e2e/claude-agent-row-view.unit.test.ts": 1491,
|
||||
"tests/e2e/codex-child-approval-activity-row.unit.test.ts": 14886,
|
||||
"tests/e2e/completed-worker-retirement-resume.unit.test.ts": 38857,
|
||||
@@ -8030,7 +7891,7 @@
|
||||
"tests/e2e/host-agent-launch-preferences-work.unit.test.ts": 3882,
|
||||
"tests/e2e/host-agent-launch-settings-hook-bookkeeping.unit.test.ts": 21972,
|
||||
"tests/e2e/host-cold-park-remote-subscriber.unit.test.ts": 5314,
|
||||
"tests/e2e/journal-restored-consumers.unit.test.ts": 33933,
|
||||
|
||||
"tests/e2e/launch-agent-background-session-remote.unit.test.ts": 1016,
|
||||
"tests/e2e/launch-agent-in-new-tab-web-runtime.unit.test.ts": 14288,
|
||||
"tests/e2e/linear-cli-recovery.unit.test.ts": 7592,
|
||||
@@ -8042,7 +7903,7 @@
|
||||
"tests/e2e/native-chat-rewind-boundary.unit.test.ts": 2977,
|
||||
"tests/e2e/native-chat-ssh-transcript.unit.test.ts": 1166,
|
||||
"tests/e2e/native-chat-startup-option-pickers.unit.test.ts": 9377,
|
||||
"tests/e2e/native-chat-transcript-file-order.unit.test.ts": 1066,
|
||||
|
||||
"tests/e2e/native-chat-transcript-reasoning.unit.test.ts": 3341,
|
||||
"tests/e2e/nested-agent-idle-owner.unit.test.ts": 2469,
|
||||
"tests/e2e/omp-child-session-recovery.unit.test.ts": 2205,
|
||||
@@ -8077,12 +7938,9 @@
|
||||
"tests/e2e/structured-session-tab-close-regressions.unit.test.ts": 32432,
|
||||
"tests/e2e/sustained-agent-typing-load-scripts.unit.test.ts": 2169,
|
||||
"tests/e2e/task-page-linear-refresh-authority.unit.test.ts": 5548,
|
||||
"tests/e2e/task-page-linear-refresh-transport.unit.test.ts": 2019,
|
||||
"tests/e2e/terminal-agent-fork-draft-ownership.unit.test.ts": 30195,
|
||||
"tests/e2e/terminal-binding-crash-hydration.unit.test.ts": 1769,
|
||||
"tests/e2e/terminal-foreground-confirmation.unit.test.ts": 644,
|
||||
"tests/e2e/terminal-perf-presentation.unit.test.ts": 60,
|
||||
"tests/e2e/web-runtime-session-terminal-host-authority.unit.test.ts": 1061,
|
||||
"tests/e2e/worktree-status-warning.unit.test.ts": 2331,
|
||||
"tests/tools/branch-line-total-renderer.test.mjs": 1222,
|
||||
"tests/tools/omp-close-lifecycle.test.mjs": 403,
|
||||
|
||||
@@ -106,6 +106,19 @@ function parseManifest(bundleDir) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (manifest.catalogs !== undefined && !Array.isArray(manifest.catalogs)) {
|
||||
throw failure('manifest catalogs is not a list')
|
||||
}
|
||||
for (const catalog of manifest.catalogs ?? []) {
|
||||
if (typeof catalog !== 'object' || catalog === null || typeof catalog.locale !== 'string') {
|
||||
throw failure('manifest catalog entry has no locale')
|
||||
}
|
||||
assertSafeRelativePath(catalog.path)
|
||||
if (typeof catalog.sha256 !== 'string' || !SHA256_PATTERN.test(catalog.sha256)) {
|
||||
throw failure(`manifest catalog ${catalog.path} has no sha256 digest`)
|
||||
}
|
||||
assertInteger(catalog.byteLength, `catalogs[${catalog.path}].byteLength`)
|
||||
}
|
||||
if (!manifest.assets.some((asset) => asset.path === manifest.entrypoint)) {
|
||||
throw failure(`manifest entrypoint ${manifest.entrypoint} is not one of its assets`)
|
||||
}
|
||||
@@ -126,6 +139,11 @@ function parseManifest(bundleDir) {
|
||||
return manifest
|
||||
}
|
||||
|
||||
// Assets go to the phone; catalogs stay on the host, which serves one on request.
|
||||
function servedFiles(manifest) {
|
||||
return [...manifest.assets, ...(manifest.catalogs ?? [])]
|
||||
}
|
||||
|
||||
function listBundleFiles(directory, prefix = '') {
|
||||
const found = []
|
||||
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
||||
@@ -164,7 +182,7 @@ function assertNoUnlistedFiles(bundleDir, manifest) {
|
||||
const listed = new Set([
|
||||
'manifest.json',
|
||||
...darkBuildMarkerFileNames(),
|
||||
...manifest.assets.map((asset) => asset.path),
|
||||
...servedFiles(manifest).map((file) => file.path),
|
||||
...brotliCopies(manifest).map((asset) => brotliPath(asset))
|
||||
])
|
||||
const strays = listBundleFiles(bundleDir).filter((path) => !listed.has(path))
|
||||
@@ -180,7 +198,7 @@ function assertNoUnlistedFiles(bundleDir, manifest) {
|
||||
function assertMobileWebBundleBuilt(bundleDir = MOBILE_WEB_BUNDLE_DIR) {
|
||||
const manifest = parseManifest(bundleDir)
|
||||
assertNoUnlistedFiles(bundleDir, manifest)
|
||||
for (const asset of manifest.assets) {
|
||||
for (const asset of servedFiles(manifest)) {
|
||||
const assetPath = join(bundleDir, asset.path)
|
||||
const size = statSize(bundleDir, asset.path)
|
||||
if (size !== asset.byteLength) {
|
||||
|
||||
@@ -6,10 +6,11 @@ import process from 'node:process'
|
||||
// TypeScript 7 is a native CLI; AST consumers still need the legacy JavaScript API.
|
||||
import ts from 'typescript-api'
|
||||
import { isTestOnlySourcePath } from '../../static-analysis/process-boundaries/test-only-source-path.mjs'
|
||||
import { isVisibleObjectKey } from './localization-visible-object-keys.mjs'
|
||||
|
||||
const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mts', '.cts'])
|
||||
const SKIP_PATH_PARTS = new Set(['.git', 'dist', 'node_modules', 'out', '__snapshots__', 'assets'])
|
||||
const LOCALIZATION_CALL_NAMES = new Set(['t', 'translate'])
|
||||
const LOCALIZATION_CALL_NAMES = new Set(['t', 'translate', 'translateMain'])
|
||||
const CLASS_PROPERTY_NAMES = new Set(['className', 'classNames'])
|
||||
// Why: the children of these elements are CSS or code, never copy a translator should see.
|
||||
const NON_COPY_JSX_ELEMENTS = new Set(['style', 'script'])
|
||||
@@ -35,25 +36,6 @@ const USER_VISIBLE_JSX_ATTRIBUTES = new Set([
|
||||
'toggleDescription',
|
||||
'tooltip'
|
||||
])
|
||||
const USER_VISIBLE_OBJECT_KEYS = new Set([
|
||||
'accessibilityHint',
|
||||
'accessibilityLabel',
|
||||
'ariaLabel',
|
||||
'badge',
|
||||
'description',
|
||||
'emptyText',
|
||||
'error',
|
||||
'headerTitle',
|
||||
'helperText',
|
||||
'keywords',
|
||||
'label',
|
||||
'message',
|
||||
'placeholder',
|
||||
'subtitle',
|
||||
'title',
|
||||
'toggleDescription',
|
||||
'tooltip'
|
||||
])
|
||||
const USER_VISIBLE_FUNCTION_NAMES = new Set([
|
||||
'alert',
|
||||
'confirm',
|
||||
@@ -331,7 +313,7 @@ function isInsideNonCopyJsxElement(node) {
|
||||
return Boolean(element && NON_COPY_JSX_ELEMENTS.has(element.openingElement.tagName.getText()))
|
||||
}
|
||||
|
||||
function classifyStringNode(node) {
|
||||
function classifyStringNode(node, includeNativeDialogFields = false) {
|
||||
if (
|
||||
hasAncestorObjectPropertyName(node, CLASS_PROPERTY_NAMES) ||
|
||||
isInsideNonCopyJsxElement(node)
|
||||
@@ -369,12 +351,15 @@ function classifyStringNode(node) {
|
||||
}
|
||||
|
||||
const objectPropertyName = nearestObjectPropertyName(node)
|
||||
if (objectPropertyName && !USER_VISIBLE_OBJECT_KEYS.has(objectPropertyName)) {
|
||||
if (objectPropertyName && !isVisibleObjectKey(objectPropertyName, includeNativeDialogFields)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const ancestorObjectPropertyName = nearestAncestorObjectPropertyName(node)
|
||||
if (ancestorObjectPropertyName && !USER_VISIBLE_OBJECT_KEYS.has(ancestorObjectPropertyName)) {
|
||||
if (
|
||||
ancestorObjectPropertyName &&
|
||||
!isVisibleObjectKey(ancestorObjectPropertyName, includeNativeDialogFields)
|
||||
) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -407,7 +392,12 @@ function areaForFile(relativePath) {
|
||||
return `renderer/${parts[0] ?? 'root'}`
|
||||
}
|
||||
|
||||
export function collectLocalizationCandidates(filePath, sourceText, root = process.cwd()) {
|
||||
export function collectLocalizationCandidates(
|
||||
filePath,
|
||||
sourceText,
|
||||
root = process.cwd(),
|
||||
options = {}
|
||||
) {
|
||||
const sourceKind =
|
||||
filePath.endsWith('.tsx') || filePath.endsWith('.jsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS
|
||||
const sourceFile = ts.createSourceFile(
|
||||
@@ -450,7 +440,7 @@ export function collectLocalizationCandidates(filePath, sourceText, root = proce
|
||||
ts.isNoSubstitutionTemplateLiteral(node) ||
|
||||
ts.isTemplateExpression(node)
|
||||
) {
|
||||
const kind = classifyStringNode(node)
|
||||
const kind = classifyStringNode(node, options.includeNativeDialogFields)
|
||||
if (kind) {
|
||||
for (const part of stringParts(node)) {
|
||||
pushReport(node, kind, part.text, part.dynamic)
|
||||
@@ -521,6 +511,7 @@ function parseArgs(argv) {
|
||||
allowlistPath: path.join('config', 'localization-coverage-allowlist.json'),
|
||||
check: false,
|
||||
format: 'summary',
|
||||
includeNativeDialogFields: false,
|
||||
outputPath: null,
|
||||
sourceRoots: []
|
||||
}
|
||||
@@ -531,6 +522,8 @@ function parseArgs(argv) {
|
||||
options.format = 'json'
|
||||
} else if (arg === '--markdown') {
|
||||
options.format = 'markdown'
|
||||
} else if (arg === '--native-dialog-fields') {
|
||||
options.includeNativeDialogFields = true
|
||||
} else if (arg === '--check') {
|
||||
options.check = true
|
||||
} else if (arg === '--allowlist') {
|
||||
@@ -616,7 +609,7 @@ export async function main(root = process.cwd(), argv = process.argv.slice(2)) {
|
||||
|
||||
for (const filePath of files) {
|
||||
const sourceText = await fs.readFile(filePath, 'utf8')
|
||||
reports.push(...collectLocalizationCandidates(filePath, sourceText, root))
|
||||
reports.push(...collectLocalizationCandidates(filePath, sourceText, root, options))
|
||||
}
|
||||
|
||||
if (options.check) {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { collectLocalizationCandidates, main } from './audit-localization-coverage.mjs'
|
||||
|
||||
const path = '/repo/src/main/startup/dialog.ts'
|
||||
const source = `
|
||||
const options = {
|
||||
message: translateMain('message', 'Translated message'),
|
||||
detail: 'Untranslated detail',
|
||||
buttons: ['Proceed', translateMain('cancel', 'Cancel')],
|
||||
body: 'Untranslated body',
|
||||
buttonLabel: 'Retry',
|
||||
checkboxLabel: 'Remember choice'
|
||||
}
|
||||
`
|
||||
|
||||
describe('native dialog localization coverage', () => {
|
||||
it('finds untranslated native dialog fields while ignoring translated copy', () => {
|
||||
const candidates = collectLocalizationCandidates(path, source, '/repo', {
|
||||
includeNativeDialogFields: true
|
||||
})
|
||||
expect(candidates.map(({ kind, text }) => [kind, text])).toEqual([
|
||||
['object-property:detail', 'Untranslated detail'],
|
||||
['object-property:buttons', 'Proceed'],
|
||||
['object-property:body', 'Untranslated body'],
|
||||
['object-property:buttonLabel', 'Retry'],
|
||||
['object-property:checkboxLabel', 'Remember choice']
|
||||
])
|
||||
})
|
||||
|
||||
it('does not change the existing renderer scan by default', () => {
|
||||
expect(collectLocalizationCandidates(path, source, '/repo')).toEqual([])
|
||||
})
|
||||
|
||||
it('fails the opt-in check for a new native dialog literal', async () => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'orca-native-localization-'))
|
||||
const report = vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
try {
|
||||
await mkdir(join(root, 'src'))
|
||||
await writeFile(join(root, 'src', 'dialog.ts'), "const options = { detail: 'Raw detail' }")
|
||||
await writeFile(join(root, 'allowlist.json'), '[]')
|
||||
await expect(
|
||||
main(root, [
|
||||
'--check',
|
||||
'--native-dialog-fields',
|
||||
'--source-root',
|
||||
'src',
|
||||
'--allowlist',
|
||||
'allowlist.json'
|
||||
])
|
||||
).resolves.toBe(1)
|
||||
} finally {
|
||||
report.mockRestore()
|
||||
await rm(root, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,33 @@
|
||||
const USER_VISIBLE_OBJECT_KEYS = new Set([
|
||||
'accessibilityHint',
|
||||
'accessibilityLabel',
|
||||
'ariaLabel',
|
||||
'badge',
|
||||
'description',
|
||||
'emptyText',
|
||||
'error',
|
||||
'headerTitle',
|
||||
'helperText',
|
||||
'keywords',
|
||||
'label',
|
||||
'message',
|
||||
'placeholder',
|
||||
'subtitle',
|
||||
'title',
|
||||
'toggleDescription',
|
||||
'tooltip'
|
||||
])
|
||||
const NATIVE_DIALOG_OBJECT_KEYS = new Set([
|
||||
'detail',
|
||||
'buttons',
|
||||
'body',
|
||||
'buttonLabel',
|
||||
'checkboxLabel'
|
||||
])
|
||||
|
||||
export function isVisibleObjectKey(name, includeNativeDialogFields) {
|
||||
return (
|
||||
USER_VISIBLE_OBJECT_KEYS.has(name) ||
|
||||
(includeNativeDialogFields && NATIVE_DIALOG_OBJECT_KEYS.has(name))
|
||||
)
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import { View } from 'react-native'
|
||||
import { GestureHandlerRootView } from 'react-native-gesture-handler'
|
||||
import { MobileNativeChatQueuedMessages } from './src/session/native-chat/input/MobileNativeChatQueuedMessages'
|
||||
import { MobileNativeChatComposer } from './src/session/native-chat/composer/MobileNativeChatComposer'
|
||||
import { mobileQueuedMessageCards } from './src/session/mobile-structured-queued-message-cards'
|
||||
import { mobileQueuedMessageCards } from './src/session/native-chat/input/mobile-structured-queued-message-cards'
|
||||
import { activateMobileUiLocale, translate } from './src/i18n/mobile-i18n'
|
||||
|
||||
const [mode, locale] = location.hash.slice(1).split(':')
|
||||
|
||||
@@ -19,7 +19,7 @@ export function stageOrcadMobileWebBundle(outputDir, bundleDir = MOBILE_WEB_BUND
|
||||
// The release template refuses the variable itself.
|
||||
assertNoDarkOutputOfOffSwitches([bundleDir])
|
||||
assertMobileWebBundleBuilt(bundleDir)
|
||||
// The guard refuses unlisted files, so the tree is the manifest, its assets and a dark marker.
|
||||
// The guard refuses unlisted files, so the tree is the manifest, its assets and catalogs, and a dark marker.
|
||||
cpSync(bundleDir, join(outputDir, ...ORCAD_MOBILE_WEB_DIR.split('/')), { recursive: true })
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ const { sortJiraIssues } = await jiti.import(
|
||||
'../../../../src/renderer/src/components/jira-issue-sorter.ts'
|
||||
)
|
||||
const { sortAutomationListViewItems } = await jiti.import(
|
||||
'../../../../src/renderer/src/components/automations/automation-list-view.ts'
|
||||
'../../../../src/renderer/src/components/automations/listing/automation-list-view.ts'
|
||||
)
|
||||
const automationLocale = 'en-US'
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { performance } from 'node:perf_hooks'
|
||||
import { transform } from 'esbuild'
|
||||
import { buildCounterbalancedSchedule } from '../measurement/counterbalanced-benchmark-schedule.mjs'
|
||||
|
||||
const path = 'src/renderer/src/components/skills/skill-source-inventory.ts'
|
||||
const path = 'src/renderer/src/components/skills/catalog/skill-source-inventory.ts'
|
||||
const arms = {}
|
||||
for (const [name, source] of [
|
||||
['baseline', readFileSync(0, 'utf8')],
|
||||
|
||||
@@ -48,6 +48,7 @@ const RATCHET_INPUTS = {
|
||||
'check-repo-host-read-ratchet.mjs': ['src/cli/', 'src/main/', 'src/shared/'],
|
||||
'check-runtime-electron-ratchet.mjs': ['src/main/', 'src/cli/', 'src/shared/'],
|
||||
'check-tab-map-seam-ratchet.mjs': ['src/renderer/src/'],
|
||||
'check-terminal-parking-ownership-ratchet.mjs': ['src/renderer/src/'],
|
||||
'check-unproven-pty-retirement-ratchet.mjs': ['src/main/'],
|
||||
'check-workspace-record-read-ratchet.mjs': ['src/renderer/src/'],
|
||||
'check-worktree-id-composer-ratchet.mjs': ['src/', 'mobile/src/']
|
||||
@@ -102,7 +103,33 @@ export const VERIFY_CHECKS = [
|
||||
'config/scripts/localization/source-extraction/audit-localization-coverage.mjs',
|
||||
'--check'
|
||||
],
|
||||
inputs: ['src/renderer/src/', LOCALES]
|
||||
inputs: [
|
||||
'src/renderer/src/',
|
||||
LOCALES,
|
||||
'config/scripts/localization/source-extraction/audit-localization-coverage',
|
||||
'config/scripts/localization/source-extraction/localization-visible-object-keys'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'startup and worktree localization coverage',
|
||||
args: [
|
||||
'config/scripts/localization/source-extraction/audit-localization-coverage.mjs',
|
||||
'--check',
|
||||
'--native-dialog-fields',
|
||||
'--source-root',
|
||||
'src/main/startup',
|
||||
'--source-root',
|
||||
'src/shared/worktree',
|
||||
'--allowlist',
|
||||
'config/startup-worktree-localization-allowlist.json'
|
||||
],
|
||||
inputs: [
|
||||
'src/main/startup/',
|
||||
'src/shared/worktree/',
|
||||
'config/scripts/localization/source-extraction/audit-localization-coverage',
|
||||
'config/scripts/localization/source-extraction/localization-visible-object-keys',
|
||||
'config/startup-worktree-localization-allowlist.json'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'mobile localization',
|
||||
@@ -145,7 +172,8 @@ export const VERIFY_CHECKS = [
|
||||
'mobile/web-entry/',
|
||||
'config/mobile-localization-coverage-allowlist.json',
|
||||
'config/scripts/audit-localization-coverage',
|
||||
'config/scripts/localization/source-extraction/audit-localization-coverage'
|
||||
'config/scripts/localization/source-extraction/audit-localization-coverage',
|
||||
'config/scripts/localization/source-extraction/localization-visible-object-keys'
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@ export const LINT_STEPS = [
|
||||
'check:test-file-runners',
|
||||
'verify:localization-catalogs',
|
||||
'verify:localization-coverage',
|
||||
'verify:startup-worktree-localization-coverage',
|
||||
'verify:mobile-localization',
|
||||
'verify:mobile-localization-coverage',
|
||||
'lint:ast-grep-gates',
|
||||
@@ -40,6 +41,7 @@ export const LINT_STEPS = [
|
||||
'check:ts-nocheck-ratchet',
|
||||
'check:workspace-record-read-ratchet',
|
||||
'check:tab-map-seam-ratchet',
|
||||
'check:terminal-parking-ownership-ratchet',
|
||||
'check:unproven-pty-retirement-ratchet',
|
||||
'check:daemon-blocking-call-ratchet',
|
||||
'check:main-sync-fs-ratchet',
|
||||
|
||||
@@ -299,7 +299,7 @@ function renderEvents({ events, eventContribution, typeText }, { services, frame
|
||||
const { REFERENCE_TYPE_TEXT, zodTypeText } = typeText
|
||||
const workerEvents = eventContribution.PLUGIN_EVENT_NAMES.map(
|
||||
(name) =>
|
||||
`- ${code(name)} (capability ${code(eventContribution.PLUGIN_EVENT_CAPABILITY[name])}; since ${eventContribution.PLUGIN_EVENT_SINCE[name]}): ${events.PLUGIN_EVENT_SUMMARIES[name]}\n ${code(zodTypeText(events.PLUGIN_EVENT_PAYLOAD_SCHEMAS[name], 'output', REFERENCE_TYPE_TEXT))}`
|
||||
`- ${code(name)} (${eventContribution.PLUGIN_EVENT_CAPABILITY[name] ? `capability ${code(eventContribution.PLUGIN_EVENT_CAPABILITY[name])}` : 'no capability'}; since ${eventContribution.PLUGIN_EVENT_SINCE[name]}): ${events.PLUGIN_EVENT_SUMMARIES[name]}\n ${code(zodTypeText(events.PLUGIN_EVENT_PAYLOAD_SCHEMAS[name], 'output', REFERENCE_TYPE_TEXT))}`
|
||||
)
|
||||
return document(
|
||||
'Events',
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { parseListedFiles } from '../../../../build-plugins/react-compiler-uncompiled-files.mjs'
|
||||
import { findStaleUncompiledFiles } from './check-react-compiler-compat-ratchet.mjs'
|
||||
|
||||
describe('uncompiled file list', () => {
|
||||
it('reads paths from list, count and hazard lines, dropping notes', () => {
|
||||
const text = [
|
||||
'# header',
|
||||
'src/renderer/src/a.tsx',
|
||||
'src/renderer/src/b.tsx # why it stays uncompiled',
|
||||
'2 src/renderer/src/c.ts',
|
||||
'1 src/renderer/src/d.ts#useD:store-read-in-memo-block',
|
||||
''
|
||||
].join('\n')
|
||||
expect(parseListedFiles(text)).toEqual([
|
||||
'src/renderer/src/a.tsx',
|
||||
'src/renderer/src/b.tsx',
|
||||
'src/renderer/src/c.ts',
|
||||
'src/renderer/src/d.ts'
|
||||
])
|
||||
})
|
||||
|
||||
it('reports listed paths that no longer name a renderer file', () => {
|
||||
const files = new Set([
|
||||
'src/renderer/src/kept.tsx',
|
||||
'src/renderer/src/notification-test-delivery.ts'
|
||||
])
|
||||
expect(
|
||||
findStaleUncompiledFiles(
|
||||
new Set([
|
||||
'src/renderer/src/kept.tsx',
|
||||
'src/renderer/src/notification-test-delivery.ts',
|
||||
'src/renderer/src/renamed.tsx'
|
||||
]),
|
||||
(rel) => files.has(rel)
|
||||
)
|
||||
).toEqual(['src/renderer/src/renamed.tsx'])
|
||||
})
|
||||
})
|
||||
@@ -1,87 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { CONSUMERS, consumerViolations, writerViolations } from './check-tab-map-seam-ratchet.mjs'
|
||||
|
||||
const BRIDGE =
|
||||
'src/renderer/src/components/native-chat/session/status/StructuredAgentSessionStatusBridge.tsx'
|
||||
const rules = CONSUMERS.get(BRIDGE)
|
||||
|
||||
describe('tab-map seam guard', () => {
|
||||
it('rejects an ordinary handler reaching the cold path or walking a map', () => {
|
||||
const text = [
|
||||
'const reconcileFromSnapshot = () => getStructuredAgentSessionTabs(source)',
|
||||
'const reconcile = () => reconcileFromSnapshot()',
|
||||
'const ordinary = () => { reconcileFromSnapshot(); Object.keys(source) }'
|
||||
].join('\n')
|
||||
expect(consumerViolations('bridge.tsx', text, rules)).toEqual([
|
||||
'bridge.tsx:3 reconcileFromSnapshot() outside a named cold path',
|
||||
'bridge.tsx:3 Object.keys outside a named cold path'
|
||||
])
|
||||
})
|
||||
|
||||
it('rejects an unreviewed value import, not type imports', () => {
|
||||
const text = [
|
||||
"import { wholeMap } from './new-walk'",
|
||||
"import type { Walk } from './new-walk'"
|
||||
].join('\n')
|
||||
expect(consumerViolations('bridge.tsx', text, rules)).toEqual([
|
||||
'bridge.tsx:1 imports wholeMap; repaired consumers import only reviewed helpers'
|
||||
])
|
||||
})
|
||||
|
||||
it('follows a raw record through a local binding unless it is marked full resync', () => {
|
||||
const text = [
|
||||
'function raw(state) {',
|
||||
' const next = { ...state.unifiedTabsByWorktree, [id]: tabs }',
|
||||
' set({ unifiedTabsByWorktree: next })',
|
||||
'}',
|
||||
'function annotated(state) {',
|
||||
' const next = { ...state.unifiedTabsByWorktree, [id]: tabs }',
|
||||
' markFullResync(next, "hydration")',
|
||||
' set({ unifiedTabsByWorktree: next })',
|
||||
'}'
|
||||
].join('\n')
|
||||
expect(writerViolations('writer.ts', text)).toEqual([
|
||||
'writer.ts:3 raw unifiedTabsByWorktree record; build it with a replace helper or draft, or mark it full resync'
|
||||
])
|
||||
})
|
||||
|
||||
it('follows aliases of cold helpers and enumerators', () => {
|
||||
const text = [
|
||||
'const reconcileFromSnapshot = () => getStructuredAgentSessionTabs(source)',
|
||||
'const reconcile = () => reconcileFromSnapshot()',
|
||||
'const resync = reconcileFromSnapshot',
|
||||
'const keys = Object.keys'
|
||||
].join('\n')
|
||||
expect(consumerViolations('bridge.tsx', text, rules)).toEqual([
|
||||
'bridge.tsx:3 reconcileFromSnapshot() outside a named cold path',
|
||||
'bridge.tsx:4 Object.keys outside a named cold path'
|
||||
])
|
||||
})
|
||||
|
||||
it('follows aliased raw records and requires annotation before publication', () => {
|
||||
const raw =
|
||||
'raw unifiedTabsByWorktree record; build it with a replace helper or draft, or mark it full resync'
|
||||
const text = [
|
||||
'function aliased(state) {',
|
||||
' const next = { ...state.unifiedTabsByWorktree, [id]: tabs }',
|
||||
' const unifiedTabsByWorktree = next',
|
||||
' set({ unifiedTabsByWorktree })',
|
||||
'}',
|
||||
'function late(state) {',
|
||||
' const next = { ...state.unifiedTabsByWorktree, [id]: tabs }',
|
||||
' set({ unifiedTabsByWorktree: next })',
|
||||
' markFullResync(next, "hydration")',
|
||||
'}',
|
||||
'function early(state) {',
|
||||
' const next = { ...state.unifiedTabsByWorktree, [id]: tabs }',
|
||||
' const alias = next',
|
||||
' markFullResync(alias, "hydration")',
|
||||
' set({ unifiedTabsByWorktree: alias })',
|
||||
'}'
|
||||
].join('\n')
|
||||
expect(writerViolations('writer.ts', text)).toEqual([
|
||||
`writer.ts:4 ${raw}`,
|
||||
`writer.ts:8 ${raw}`
|
||||
])
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,475 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import ts from 'typescript-api'
|
||||
|
||||
const RENDERER = 'src/renderer/src/'
|
||||
const WATCHERS = `${RENDERER}components/terminal-pane/parking/output-watchers/`
|
||||
const ROOTS = new Map([
|
||||
[
|
||||
`${RENDERER}components/terminal/terminal-provider-snapshot-bound-pty-ids.ts`,
|
||||
['createTerminalProviderSnapshotBoundPtyIdsSelector']
|
||||
],
|
||||
[`${RENDERER}components/use-terminal-watcher-effects.ts`, ['useTerminalWatcherEffects']],
|
||||
[`${RENDERER}components/use-terminal-parking-pass.ts`, ['useTerminalParkingPass']],
|
||||
[
|
||||
`${RENDERER}components/terminal-parking-pass-candidates.ts`,
|
||||
['collectTerminalParkingPassCandidates']
|
||||
],
|
||||
[`${RENDERER}components/terminal/split-group-mount.ts`, ['anyMountedWorktreeHasLayout']],
|
||||
[
|
||||
`${RENDERER}components/terminal-pane/parking/lifecycle/use-parked-terminal-watcher-synchronization.ts`,
|
||||
['useParkedTerminalWatcherSynchronization']
|
||||
],
|
||||
[
|
||||
`${RENDERER}components/terminal-pane/parking/lifecycle/use-terminal-tab-cold-parking.ts`,
|
||||
['useTerminalTabColdParking']
|
||||
],
|
||||
[`${WATCHERS}terminal-parked-tab-watchers.ts`, ['syncParkedTerminalTabWatchers']],
|
||||
[`${WATCHERS}parked-terminal-tab-coverage.ts`, ['canWatcherCoverParkedTerminalTab']],
|
||||
[
|
||||
`${RENDERER}lib/agent-session/resume/resume-sleeping-agent-session.ts`,
|
||||
['resumeSleepingAgentSessionsForWorktree']
|
||||
]
|
||||
])
|
||||
const HOT_MAPS = new Set([
|
||||
'tabsByWorktree',
|
||||
'unifiedTabsByWorktree',
|
||||
'terminalLayoutsByTabId',
|
||||
'sleepingAgentSessionsByPaneKey'
|
||||
])
|
||||
const OWNER_ROOTS = [
|
||||
{
|
||||
rel: 'store/terminals/terminal-parking-input-owner.ts',
|
||||
name: 'acceptTerminalParkingInputs',
|
||||
inputs: []
|
||||
},
|
||||
{
|
||||
rel: 'store/terminals/terminal-parking-input-owner.ts',
|
||||
name: 'publishAcceptedTerminalParkingInputs',
|
||||
inputs: []
|
||||
},
|
||||
{
|
||||
rel: 'store/terminals/terminal-parking-input-owner.ts',
|
||||
name: 'invalidateTerminalParkingPtyInputs',
|
||||
inputs: []
|
||||
},
|
||||
{
|
||||
rel: 'store/terminals/terminal-tab-owner-index.ts',
|
||||
name: 'update',
|
||||
inputs: ['tabsByWorktree']
|
||||
},
|
||||
{ rel: 'store/terminals/sleeping-agent-record-index.ts', name: 'update', inputs: ['records'] },
|
||||
{
|
||||
rel: 'store/terminals/sleeping-agent-record-index.ts',
|
||||
name: 'acceptTransition',
|
||||
inputs: ['previous', 'next']
|
||||
},
|
||||
{
|
||||
rel: 'lib/workspace/tabs/worktree-tab-bucket-projection.ts',
|
||||
name: 'project',
|
||||
inputs: ['source']
|
||||
}
|
||||
]
|
||||
const KEY_DIFFS = new Set([
|
||||
`${RENDERER}store/terminals/terminal-parking-input-owner.ts#diffUnknownParkingRecordKeys`,
|
||||
`${RENDERER}store/terminals/terminal-tab-owner-index.ts#diffUnknownTabOwnerKeys`,
|
||||
`${RENDERER}store/terminals/sleeping-agent-record-index.ts#diffUnknownSleepingRecordKeys`,
|
||||
`${RENDERER}lib/workspace/tabs/worktree-tab-bucket-projection.ts#diffUnknownProjectionKeys`
|
||||
])
|
||||
const COLD_RESYNCS = new Set([
|
||||
`${RENDERER}store/terminals/terminal-parking-input-owner.ts#resyncTerminalParkingWorkspaceIds`,
|
||||
`${RENDERER}store/terminals/sleeping-agent-record-index.ts#resyncSleepingAgentRecordKeys`
|
||||
])
|
||||
|
||||
function isColdResyncCall(node, source) {
|
||||
for (let ancestor = node.parent; ancestor; ancestor = ancestor.parent) {
|
||||
if (
|
||||
ts.isConditionalExpression(ancestor) &&
|
||||
ancestor.condition.getText(source) === 'previous' &&
|
||||
node.pos >= ancestor.whenFalse.pos
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
ts.isBinaryExpression(ancestor) &&
|
||||
ancestor.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken &&
|
||||
ancestor.left.getText(source) === 'keys'
|
||||
) {
|
||||
return true
|
||||
}
|
||||
if (
|
||||
ts.isIfStatement(ancestor) &&
|
||||
node.pos >= ancestor.thenStatement.pos &&
|
||||
node.end <= ancestor.thenStatement.end
|
||||
) {
|
||||
const condition = ancestor.expression.getText(source).replace(/\s+/g, ' ')
|
||||
if (
|
||||
condition === 'ptyIds === undefined' ||
|
||||
condition.includes(
|
||||
'previous.settings?.terminalSshViewParking !== state.settings?.terminalSshViewParking'
|
||||
)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
const STORE_BOUNDARIES = new Set([`${RENDERER}store/index.ts`, `${RENDERER}store.ts`])
|
||||
// Resource delivery and startup recovery are separate entry points, not parking input discovery.
|
||||
const EFFECT_BOUNDARIES = new Set([
|
||||
`${RENDERER}components/terminal/terminal-provider-snapshot-bound-pty-ids.ts#resyncUnknownSnapshot`,
|
||||
`${RENDERER}components/terminal/use-terminal-startup-activation.ts#useTerminalStartupActivation`,
|
||||
`${WATCHERS}terminal-parked-pty-watcher.ts#startParkedPtyWatcher`,
|
||||
`${RENDERER}components/terminal-pane/parking/capture/parked-terminal-buffer-capture.ts#captureParkedTerminalBuffers`,
|
||||
`${RENDERER}lib/agent-session/resume/sleeping-agent-session-launch.ts#launchSleepingAgentSession`,
|
||||
`${RENDERER}lib/host-mirror-handle-gap-wait.ts#parkUntilHostMirrorHandleLands`,
|
||||
`${RENDERER}runtime/web-session-tabs-sync/hydration/host-session-mirror-hydration.ts#parkUntilHostSessionMirrorHydrates`
|
||||
])
|
||||
const ENUMERATORS = new Set(['entries', 'values', 'keys', 'assign'])
|
||||
|
||||
const ADDRESSED_FIELDS = new Set([
|
||||
'terminalLayoutsByTabId',
|
||||
'ptyIdsByTabId',
|
||||
'lastKnownRelayPtyIdByTabId',
|
||||
'runtimePaneTitlesByTabId',
|
||||
'pendingStartupByTabId',
|
||||
'sleepingAgentSessionsByPaneKey'
|
||||
])
|
||||
const ORDINARY_WRITERS = [
|
||||
'store/terminals/terminal-layout-state.ts',
|
||||
'store/terminals/terminal-pane-hibernation.ts',
|
||||
'store/terminals/terminal-pty-bindings.ts',
|
||||
'store/terminals/terminal-pty-release.ts',
|
||||
'store/terminals/terminal-orphan-cleanup.ts',
|
||||
'store/terminals/terminal-startup-queues.ts',
|
||||
'store/terminals/terminal-tab-presentation.ts',
|
||||
'store/terminals/terminal-shutdown-state.ts',
|
||||
'store/terminals/window-tab-start-in-main.ts',
|
||||
'store/slices/agent-status/agent-status-live-reducer.ts',
|
||||
'store/slices/agent-status/agent-status-launch-actions.ts',
|
||||
'store/slices/agent-status/agent-status-provider-session-actions.ts',
|
||||
'store/slices/agent-status/agent-status-recovery-actions.ts',
|
||||
'store/slices/agent-status/agent-status-authority-actions.ts'
|
||||
].map((rel) => RENDERER + rel)
|
||||
const RECORD_TRANSITIONS = new Set([
|
||||
'replaceRecordEntries',
|
||||
'removePaneKeys',
|
||||
'removePaneKeysByTabPrefix'
|
||||
])
|
||||
|
||||
function collectUnaddressedWrites(root) {
|
||||
const violations = []
|
||||
for (const rel of ORDINARY_WRITERS) {
|
||||
const { source, aliases, assignments } = readModule(root, rel)
|
||||
function addressed(value, field, seen = new Set()) {
|
||||
if (ts.isCallExpression(value) && ts.isIdentifier(value.expression)) {
|
||||
return RECORD_TRANSITIONS.has(value.expression.text)
|
||||
}
|
||||
if (ts.isPropertyAccessExpression(value)) {
|
||||
return value.name.text === field
|
||||
}
|
||||
if (ts.isConditionalExpression(value)) {
|
||||
return addressed(value.whenTrue, field, seen) && addressed(value.whenFalse, field, seen)
|
||||
}
|
||||
if (ts.isIdentifier(value)) {
|
||||
if (seen.has(value.text)) {
|
||||
return false
|
||||
}
|
||||
seen.add(value.text)
|
||||
const alias = aliases.get(value.text)
|
||||
return (
|
||||
alias !== undefined &&
|
||||
[alias, ...(assignments.get(value.text) ?? [])].every((replacement) =>
|
||||
addressed(replacement, field, new Set(seen))
|
||||
)
|
||||
)
|
||||
}
|
||||
return false
|
||||
}
|
||||
function visit(node) {
|
||||
if (ts.isPropertyAssignment(node) || ts.isShorthandPropertyAssignment(node)) {
|
||||
const field =
|
||||
ts.isIdentifier(node.name) || ts.isStringLiteral(node.name) ? node.name.text : null
|
||||
const value = ts.isPropertyAssignment(node) ? node.initializer : node.name
|
||||
if (ADDRESSED_FIELDS.has(field) && !addressed(value, field)) {
|
||||
const line = source.getLineAndCharacterOfPosition(node.getStart(source)).line + 1
|
||||
violations.push(`${rel}:${line}: ${field} write needs complete record-key provenance.`)
|
||||
}
|
||||
}
|
||||
ts.forEachChild(node, visit)
|
||||
}
|
||||
visit(source)
|
||||
}
|
||||
return violations
|
||||
}
|
||||
|
||||
function resolveImport(root, from, specifier) {
|
||||
const base = specifier.startsWith('@/')
|
||||
? RENDERER + specifier.slice(2)
|
||||
: specifier.startsWith('.')
|
||||
? path.posix.join(path.posix.dirname(from), specifier)
|
||||
: null
|
||||
if (!base) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
[base, `${base}.ts`, `${base}.tsx`, `${base}/index.ts`].find(
|
||||
(candidate) =>
|
||||
fs.existsSync(path.join(root, candidate)) &&
|
||||
fs.statSync(path.join(root, candidate)).isFile()
|
||||
) ?? null
|
||||
)
|
||||
}
|
||||
|
||||
function readModule(root, rel) {
|
||||
const source = ts.createSourceFile(
|
||||
rel,
|
||||
fs.readFileSync(path.join(root, rel), 'utf8'),
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
)
|
||||
const imports = new Map()
|
||||
const functions = new Map()
|
||||
const aliases = new Map()
|
||||
const assignments = new Map()
|
||||
function visit(node) {
|
||||
if (
|
||||
ts.isBinaryExpression(node) &&
|
||||
ts.isIdentifier(node.left) &&
|
||||
node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment &&
|
||||
node.operatorToken.kind <= ts.SyntaxKind.LastAssignment
|
||||
) {
|
||||
const values = assignments.get(node.left.text) ?? []
|
||||
values.push(node.right)
|
||||
assignments.set(node.left.text, values)
|
||||
}
|
||||
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
||||
const target = resolveImport(root, rel, node.moduleSpecifier.text)
|
||||
const bindings = node.importClause?.namedBindings
|
||||
if (target && bindings && ts.isNamedImports(bindings)) {
|
||||
for (const binding of bindings.elements) {
|
||||
imports.set(binding.name.text, {
|
||||
rel: target,
|
||||
name: binding.propertyName?.text ?? binding.name.text
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
(ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) &&
|
||||
node.name &&
|
||||
node.body
|
||||
) {
|
||||
functions.set(node.name.text, node)
|
||||
}
|
||||
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) {
|
||||
aliases.set(node.name.text, node.initializer)
|
||||
if (ts.isArrowFunction(node.initializer) || ts.isFunctionExpression(node.initializer)) {
|
||||
functions.set(node.name.text, node.initializer)
|
||||
}
|
||||
}
|
||||
ts.forEachChild(node, visit)
|
||||
}
|
||||
visit(source)
|
||||
return { source, imports, functions, aliases, assignments }
|
||||
}
|
||||
|
||||
export function collectParkingOwnershipViolations(root = process.cwd()) {
|
||||
const modules = new Map()
|
||||
const pending = [...ROOTS].flatMap(([rel, names]) =>
|
||||
names.map((name) => ({ rel, name, tainted: new Set() }))
|
||||
)
|
||||
for (const { rel, name, inputs } of OWNER_ROOTS) {
|
||||
pending.push({ rel: RENDERER + rel, name, tainted: new Set(inputs) })
|
||||
}
|
||||
const visited = new Set()
|
||||
const violations = new Set()
|
||||
while (pending.length) {
|
||||
const { rel, name, tainted } = pending.pop()
|
||||
if (STORE_BOUNDARIES.has(rel) || EFFECT_BOUNDARIES.has(`${rel}#${name}`)) {
|
||||
continue
|
||||
}
|
||||
const identity = `${rel}#${name}#${[...tainted].sort().join(',')}`
|
||||
if (visited.has(identity)) {
|
||||
continue
|
||||
}
|
||||
visited.add(identity)
|
||||
let mod = modules.get(rel)
|
||||
if (!mod) {
|
||||
modules.set(rel, (mod = readModule(root, rel)))
|
||||
}
|
||||
const fn = mod.functions.get(name)
|
||||
if (!fn) {
|
||||
continue
|
||||
}
|
||||
function hotMap(node, seen = new Set()) {
|
||||
if (ts.isPropertyAccessExpression(node)) {
|
||||
if (HOT_MAPS.has(node.name.text)) {
|
||||
return true
|
||||
}
|
||||
if (ts.isIdentifier(node.expression)) {
|
||||
const value = mod.aliases.get(node.expression.text)
|
||||
if (value && ts.isObjectLiteralExpression(value)) {
|
||||
const property = value.properties.find(
|
||||
(candidate) =>
|
||||
ts.isPropertyAssignment(candidate) &&
|
||||
candidate.name.getText(mod.source) === node.name.text
|
||||
)
|
||||
if (property && ts.isPropertyAssignment(property)) {
|
||||
return hotMap(property.initializer, seen)
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (ts.isElementAccessExpression(node)) {
|
||||
return (
|
||||
ts.isStringLiteral(node.argumentExpression) && HOT_MAPS.has(node.argumentExpression.text)
|
||||
)
|
||||
}
|
||||
if (ts.isIdentifier(node)) {
|
||||
if (HOT_MAPS.has(node.text) || tainted.has(node.text)) {
|
||||
return true
|
||||
}
|
||||
if (seen.has(node.text)) {
|
||||
return false
|
||||
}
|
||||
seen.add(node.text)
|
||||
const alias = mod.aliases.get(node.text)
|
||||
return alias ? hotMap(alias, seen) : false
|
||||
}
|
||||
if (
|
||||
ts.isParenthesizedExpression(node) ||
|
||||
ts.isAsExpression(node) ||
|
||||
ts.isNonNullExpression(node)
|
||||
) {
|
||||
return hotMap(node.expression, seen)
|
||||
}
|
||||
if (
|
||||
ts.isBinaryExpression(node) &&
|
||||
node.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken
|
||||
) {
|
||||
return hotMap(node.left, seen)
|
||||
}
|
||||
return false
|
||||
}
|
||||
function report(node) {
|
||||
const line = mod.source.getLineAndCharacterOfPosition(node.getStart(mod.source)).line + 1
|
||||
violations.add(
|
||||
`${rel}:${line}: ${name} enumerates a whole parking input; use the addressed owner or a named source resync.`
|
||||
)
|
||||
}
|
||||
function visit(node) {
|
||||
if (
|
||||
ts.isFunctionDeclaration(node) &&
|
||||
node.name &&
|
||||
EFFECT_BOUNDARIES.has(`${rel}#${node.name.text}`)
|
||||
) {
|
||||
return
|
||||
}
|
||||
if (ts.isForInStatement(node) && hotMap(node.expression)) {
|
||||
report(node)
|
||||
}
|
||||
if (ts.isCallExpression(node)) {
|
||||
const callee = node.expression
|
||||
if (
|
||||
ts.isPropertyAccessExpression(callee) &&
|
||||
ts.isIdentifier(callee.expression) &&
|
||||
callee.expression.text === 'Object' &&
|
||||
ENUMERATORS.has(callee.name.text) &&
|
||||
node.arguments.some((arg) => hotMap(arg)) &&
|
||||
!(callee.name.text === 'keys' && KEY_DIFFS.has(`${rel}#${name}`)) &&
|
||||
!COLD_RESYNCS.has(`${rel}#${name}`)
|
||||
) {
|
||||
report(node)
|
||||
}
|
||||
if (ts.isIdentifier(callee)) {
|
||||
const target = mod.imports.get(callee.text) ?? { rel, name: callee.text }
|
||||
if (
|
||||
COLD_RESYNCS.has(`${target.rel}#${target.name}`) &&
|
||||
!isColdResyncCall(node, mod.source)
|
||||
) {
|
||||
report(node)
|
||||
}
|
||||
if (!STORE_BOUNDARIES.has(target.rel)) {
|
||||
let targetModule = modules.get(target.rel)
|
||||
if (!targetModule) {
|
||||
modules.set(target.rel, (targetModule = readModule(root, target.rel)))
|
||||
}
|
||||
const called = targetModule.functions.get(target.name)
|
||||
const parameters = new Set()
|
||||
called?.parameters.forEach((parameter, index) => {
|
||||
if (
|
||||
ts.isIdentifier(parameter.name) &&
|
||||
node.arguments[index] &&
|
||||
hotMap(node.arguments[index])
|
||||
) {
|
||||
parameters.add(parameter.name.text)
|
||||
}
|
||||
})
|
||||
if (called) {
|
||||
pending.push({ ...target, tainted: parameters })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ts.forEachChild(node, visit)
|
||||
}
|
||||
visit(fn.body)
|
||||
}
|
||||
return [...violations].sort()
|
||||
}
|
||||
|
||||
function collectPublicCoverageViolations(root) {
|
||||
const rel = `${WATCHERS}parked-terminal-tab-coverage.ts`
|
||||
const { source } = readModule(root, rel)
|
||||
const privateNames = new Set([
|
||||
'fallbackParkedPaneCandidates',
|
||||
'resolveParkedTerminalPaneCandidates',
|
||||
'capturedCoversFallback'
|
||||
])
|
||||
const violations = []
|
||||
for (const statement of source.statements) {
|
||||
const exported =
|
||||
ts.canHaveModifiers(statement) &&
|
||||
ts.getModifiers(statement)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)
|
||||
const leaksDeclaration =
|
||||
exported && ts.isFunctionDeclaration(statement) && privateNames.has(statement.name?.text)
|
||||
const leaksNamedExport =
|
||||
ts.isExportDeclaration(statement) &&
|
||||
statement.exportClause &&
|
||||
ts.isNamedExports(statement.exportClause) &&
|
||||
statement.exportClause.elements.some((element) =>
|
||||
privateNames.has(element.propertyName?.text ?? element.name.text)
|
||||
)
|
||||
if (leaksDeclaration || leaksNamedExport) {
|
||||
violations.push(`${rel}: raw coverage derivation must stay private to its owner.`)
|
||||
}
|
||||
}
|
||||
return violations
|
||||
}
|
||||
|
||||
export function main(root = process.cwd()) {
|
||||
const violations = [
|
||||
...collectParkingOwnershipViolations(root),
|
||||
...collectUnaddressedWrites(root),
|
||||
...collectPublicCoverageViolations(root)
|
||||
]
|
||||
for (const violation of violations) {
|
||||
console.error(violation)
|
||||
}
|
||||
if (violations.length) {
|
||||
return 1
|
||||
}
|
||||
console.log(
|
||||
'terminal-parking-ownership: addressed consumer paths contain no whole input enumeration'
|
||||
)
|
||||
return 0
|
||||
}
|
||||
|
||||
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
||||
process.exitCode = main()
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestRunner } from 'vitest'
|
||||
|
||||
export default class SharedWorkerSetupRunner extends TestRunner {
|
||||
importFile(filepath, source) {
|
||||
if (source === 'setup') {
|
||||
// Warm transforms can key setup roots by a different URL than Vitest invalidates.
|
||||
const modules = this.moduleRunner.evaluatedModules
|
||||
for (const node of modules.getModulesByFile(filepath) ?? []) {
|
||||
if (node.evaluated) {
|
||||
modules.invalidateModule(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.importFile(filepath, source)
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,6 @@ const NODE_RUNTIME_INCLUDE = [
|
||||
'src/main/browser/extensions/native-messaging/browser-extension-native-host-process-backpressure.test.ts',
|
||||
'src/main/daemon/providers/lifecycle/testing/daemon-init-provider-installation.test.ts',
|
||||
'src/renderer/src/components/terminal-pane/pty-transport/input/pty-input-write-queue.test.ts',
|
||||
'src/renderer/src/lib/react-commit-cascade-observer.test.ts',
|
||||
'src/renderer/src/lib/react-commit-cascade-telemetry.test.ts',
|
||||
// Asserts payloads are collected; Bun's GC scans the stack conservatively and may keep one alive.
|
||||
'src/shared/ws-inbound-message-queue.test.ts',
|
||||
'src/renderer/src/lib/agent-session/history/title-sync/ai-vault-tab-title-sync-inputs.test.ts',
|
||||
@@ -137,7 +135,7 @@ const NODE_RUNTIME_INCLUDE = [
|
||||
'src/main/gitlab/gitlab-known-host-retirement.test.ts',
|
||||
'src/main/window/main-window-updater-deferred-setup.test.ts',
|
||||
'src/renderer/src/components/terminal-pane/host-state/terminal-pane-host-state-memo.test.ts',
|
||||
'src/renderer/src/components/automations/use-automation-runs-dashboard-payload.test.tsx',
|
||||
'src/renderer/src/components/automations/runs/use-automation-runs-dashboard-payload.test.tsx',
|
||||
'src/main/native-chat/agent-session-journal/**/*.test.ts',
|
||||
'src/main/native-chat/agent-session-wire/host/testing/structured-agent-session-terminal-writer-acquire.test.ts',
|
||||
'src/main/runtime/agent-session/records/agent-session-conversation-name-store.test.ts',
|
||||
@@ -169,7 +167,14 @@ const NODE_RUNTIME_INCLUDE = [
|
||||
'src/main/claude/claude-agent-sdk-contract-pins.test.ts',
|
||||
'config/scripts/orcad-distribution/server-bundle/profile-state-worker-smoke.test.mjs',
|
||||
'config/scripts/desktop-distribution/runtime-verification/process-host-dev-rebuild.test.ts',
|
||||
'config/scripts/test-runtime/node-worker/vitest-node-runtime-pool.test.ts'
|
||||
'config/scripts/test-runtime/node-worker/vitest-node-runtime-pool.test.ts',
|
||||
// Reopen WAL-backed row caches read-only, which Bun on macOS cannot.
|
||||
'src/main/agent-hooks/server/testing/identity/server-hook-session-binding.test.ts',
|
||||
'tests/e2e/helpers/persisted-profile-state.unit.test.ts',
|
||||
'src/main/runtime/push/notifications/mobile-notification-dismissal-store.test.ts',
|
||||
'src/main/runtime/push/notifications/mobile-notification-dismissal-read-failure.test.ts',
|
||||
'src/main/ipc/notifications-subject-retirement.test.ts',
|
||||
'src/main/ipc/notifications-external-acknowledgement.test.ts'
|
||||
]
|
||||
|
||||
/** `filters` limits the SQLite import scan to the tests a filtered CLI run can select. */
|
||||
|
||||
@@ -25,7 +25,7 @@ const LAYOUT_ORACLE_PREFIXES = [
|
||||
'src/renderer/src/store/workspace-layout/workspace-layout-cache',
|
||||
'src/renderer/src/components/terminal-pane/',
|
||||
'src/renderer/src/components/agent-session-continuation/AgentSessionContinuationMenuItem.tsx',
|
||||
'src/renderer/src/components/orchestration-crew/WorkerAutoCloseBanner.tsx',
|
||||
'src/renderer/src/components/terminal-pane/worker-lifetime/WorkerAutoCloseBanner.tsx',
|
||||
'src/renderer/src/attention/orca-window-foreground-focus.ts',
|
||||
'src/renderer/src/attention/notification-workspace-labels.ts',
|
||||
'src/renderer/src/lib/agent-session/identity/pane-agent-session-id.ts',
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"filePath": "src/main/startup/main-process-quit.ts",
|
||||
"kind": "object-property:message",
|
||||
"text": "before-quit allowed for update install",
|
||||
"dynamic": false,
|
||||
"count": 1,
|
||||
"reason": "Updater lifecycle diagnostics are not displayed as UI copy."
|
||||
},
|
||||
{
|
||||
"filePath": "src/main/startup/main-process-quit.ts",
|
||||
"kind": "object-property:message",
|
||||
"text": "will-quit cleanup for update install; daemonTeardown=disconnect",
|
||||
"dynamic": false,
|
||||
"count": 1,
|
||||
"reason": "Updater lifecycle diagnostics are not displayed as UI copy."
|
||||
},
|
||||
{
|
||||
"filePath": "src/main/startup/profile-state-recovery-preflight.ts",
|
||||
"kind": "object-property:message",
|
||||
"text": "Invalid profile-state recovery launch.",
|
||||
"dynamic": false,
|
||||
"count": 1,
|
||||
"reason": "Existing recovery detail is user-visible and remains untranslated; tracked in issue 32207."
|
||||
}
|
||||
]
|
||||
@@ -23,8 +23,7 @@
|
||||
"../src/cli/runtime/runtime-access-denied.ts",
|
||||
"../src/cli/runtime/runtime-pid-liveness.ts",
|
||||
"../src/renderer/src/store/slices/worktrees/create/worktree-create-payload.ts",
|
||||
"../src/renderer/src/lib/orca-hook-trust.ts",
|
||||
"../src/renderer/src/lib/sha256.ts",
|
||||
"../src/renderer/src/runtime/repo-hooks/orca-hook-trust.ts",
|
||||
"../src/renderer/src/components/native-chat/native-chat-resolution-receipt.ts",
|
||||
"../src/renderer/src/components/native-chat/structured-agent-question-projection.ts",
|
||||
"../src/renderer/src/components/native-chat/subagents/native-chat-subagent-delegation.ts",
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"exclude": [
|
||||
"../src/renderer/src/lib/agent-session/launch/new-tab/launch-agent-in-new-tab-main-surface.test.ts",
|
||||
"../src/renderer/src/components/task-page/linear/task-page-linear-detail-query.test.tsx",
|
||||
"../tests/e2e/terminal-agent-pane-launch.unit.test.ts",
|
||||
"../src/renderer/src/runtime/provider-accounts/observations/provider-account-observation.test-fixture.ts",
|
||||
"../src/shared/**/*.test.ts",
|
||||
"../src/shared/**/*.test.tsx",
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
"../src/main/runtime/orchestration/terminal-authority/structured-sessions/structured-chat-coordinator-mail.test.ts",
|
||||
"../src/main/runtime/rpc/methods/orchestration/orchestration-check-ambiguous-caller.test.ts",
|
||||
"../src/renderer/src/components/task-page/linear/task-page-linear-detail-query.test.tsx",
|
||||
"../tests/e2e/terminal-agent-pane-launch.unit.test.ts",
|
||||
"../src/renderer/src/runtime/observed-provider-accounts.test.tsx",
|
||||
"../src/renderer/src/components/status-bar/ClaudeSwitcherMenu.observation.test.tsx",
|
||||
"../src/renderer/src/runtime/provider-accounts/observations/provider-account-observation.test-fixture.ts",
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
"exclude": [
|
||||
"../src/renderer/src/lib/agent-session/launch/new-tab/launch-agent-in-new-tab-main-surface.test.ts",
|
||||
"../src/renderer/src/components/task-page/linear/task-page-linear-detail-query.test.tsx",
|
||||
"../tests/e2e/terminal-agent-pane-launch.unit.test.ts",
|
||||
"../src/renderer/src/runtime/provider-accounts/observations/provider-account-observation.test-fixture.ts"
|
||||
],
|
||||
"compilerOptions": {
|
||||
|
||||
@@ -126,10 +126,12 @@ const bunProject = {
|
||||
}
|
||||
// Files whose state the per-file reset can undo share one worker's module cache instead of
|
||||
// re-importing thousands of modules each. ORCA_VITEST_ISOLATE_EVERY_FILE=1 turns it off.
|
||||
// Windows workers that keep native addons (process tree, ConPTY) across files die of heap
|
||||
// corruption (0xC0000374); production code loads them lazily, so the file scan can't see them.
|
||||
const runtimeProject = process.versions.bun ? bunProject : nodeProject
|
||||
const nodeRuntimeFiles = new Set(nodeRuntimeInclude.map((file) => file.replaceAll('\\', '/')))
|
||||
const sharedWorkerFiles =
|
||||
process.env.ORCA_VITEST_ISOLATE_EVERY_FILE === '1'
|
||||
process.env.ORCA_VITEST_ISOLATE_EVERY_FILE === '1' || process.platform === 'win32'
|
||||
? []
|
||||
: filesSafeToShareWorker(
|
||||
process.cwd(),
|
||||
@@ -151,6 +153,9 @@ const sharedProjects =
|
||||
name: `${runtimeProject.test.name}-shared`,
|
||||
include: sharedWorkerFiles,
|
||||
isolate: false,
|
||||
runner: resolve(
|
||||
'config/scripts/test-runtime/execution-policy/vitest-shared-worker-setup-runner.mjs'
|
||||
),
|
||||
setupFiles: [
|
||||
...runtimeProject.test.setupFiles,
|
||||
resolve('config/scripts/test-runtime/environment/vitest-shared-worker-file-reset.mjs')
|
||||
|
||||
@@ -17,7 +17,6 @@ const contracts = [
|
||||
'src/main/codex-usage/scanner-incremental-append.test.ts',
|
||||
'src/main/usage/jsonl-file-reader.test.ts',
|
||||
'src/main/usage/jsonl-file-snapshot.test.ts',
|
||||
'src/renderer/src/lib/pane-manager/pane-terminal-output-scheduler-queue-retention.test.ts',
|
||||
'config/scripts/static-analysis/oxlint-contracts/app-store-performance-plugin.test.mjs',
|
||||
'config/scripts/static-analysis/oxlint-contracts/quadratic-buffer-concat-plugin.test.mjs',
|
||||
'src/main/claude-usage/scanner-incremental-append.test.ts',
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
1 src/renderer/src/components/sidebar/worktree-list/navigation/pending-reveal-inputs.ts # reads a passed-in copy
|
||||
1 src/renderer/src/components/sidebar/worktree-list/navigation/use-pending-reveal.ts # reads a passed-in copy
|
||||
2 src/renderer/src/components/sidebar/worktree-list/viewport/VirtualizedWorktreeViewport.tsx # reads a passed-in copy
|
||||
2 src/renderer/src/components/skills/skill-install-workspace-choices.ts # reads a passed-in copy
|
||||
2 src/renderer/src/components/skills/installation/skill-install-workspace-choices.ts # reads a passed-in copy
|
||||
1 src/renderer/src/components/terminal-pane/links/files/terminal-worktree-path-link.ts # P5b-2 must clear: loosely typed state param
|
||||
1 src/renderer/src/components/workspace-space/space-window-state.ts # reads a passed-in copy
|
||||
1 src/renderer/src/hooks/composer-state/composer-source-state.ts # P5b-2 must clear: composer store snapshot
|
||||
@@ -36,10 +36,10 @@
|
||||
1 src/renderer/src/runtime/hosts/wsl/local-project-runtime-workspace.ts # P5b-2 must clear: optional state field defaults to empty
|
||||
1 src/renderer/src/lib/resolved-worktree-execution-host.ts # P5b-2 must clear: loosely typed state param
|
||||
2 src/renderer/src/lib/workspace/ownership/runtime-session-mirror-owners.ts # P5b-2 must clear: optional state fields default to empty
|
||||
2 src/renderer/src/lib/terminal-worktree-route.ts # P5b-2 must clear: the unattributed-twin check reads both catalogs directly
|
||||
2 src/renderer/src/lib/workspace/ownership/terminal-worktree-route.ts # P5b-2 must clear: the unattributed-twin check reads both catalogs directly
|
||||
3 src/renderer/src/lib/typing-latency/diagnostic-summary.ts # P5b-2 must clear: optional state field
|
||||
2 src/renderer/src/lib/unread-badge-count.ts # reads a passed-in copy
|
||||
1 src/renderer/src/lib/workspace-directory.ts # P5b-2 must clear: optional state field defaults to empty
|
||||
1 src/renderer/src/lib/workspace/paths/workspace-directory.ts # P5b-2 must clear: optional state field defaults to empty
|
||||
2 src/renderer/src/lib/workspace/ownership/workspace-terminal-host-authority.ts # P5b-2 must clear: optional state fields
|
||||
1 src/renderer/src/lib/workspace/activation/initial-surface/worktree-initial-terminal-seeding.ts # P5b-2 must clear: treats an undefined field as a narrow adapter
|
||||
1 src/renderer/src/lib/workspace/activation/worktree-activation-pty-inventory.ts # P5b-2 must clear: loosely typed state param
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="113" height="20" role="img" aria-label="downloads: 163m">
|
||||
<title>downloads: 163m</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="113" height="20" role="img" aria-label="downloads: 168m">
|
||||
<title>downloads: 168m</title>
|
||||
<linearGradient id="s" x2="0" y2="100%">
|
||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
@@ -15,7 +15,7 @@
|
||||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="11">
|
||||
<text x="37" y="15" fill="#010101" fill-opacity=".3">downloads</text>
|
||||
<text x="37" y="14">downloads</text>
|
||||
<text x="93.5" y="15" fill="#010101" fill-opacity=".3">163m</text>
|
||||
<text x="93.5" y="14">163m</text>
|
||||
<text x="93.5" y="15" fill="#010101" fill-opacity=".3">168m</text>
|
||||
<text x="93.5" y="14">168m</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 943 B After Width: | Height: | Size: 943 B |
|
Before Width: | Height: | Size: 392 KiB |
|
Before Width: | Height: | Size: 400 KiB |
|
Before Width: | Height: | Size: 391 KiB |
|
Before Width: | Height: | Size: 385 KiB |
|
Before Width: | Height: | Size: 381 KiB |
|
Before Width: | Height: | Size: 386 KiB After Width: | Height: | Size: 395 KiB |
@@ -53,5 +53,5 @@ pnpm dev:fresh [--keep] [--seed-from[=<profile dir>]] # temporary profile, rem
|
||||
|
||||
- Slow main-process rebuilds: set `ORCA_DEV_MAIN_SOURCEMAPS=0` before `pnpm dev` when you don't need main-process source maps.
|
||||
- Renderer misbehaving in dev: set `ORCA_DEV_BUNDLED=0` to turn off bundled dev mode, and report it.
|
||||
- Test passes alone but fails after others: add `// @orca-isolated-worker` to the file; `ORCA_VITEST_ISOLATE_EVERY_FILE=1` isolates every file to confirm a leak.
|
||||
- Test passes alone but fails after others: add `// @orca-isolated-worker` to the file; `ORCA_VITEST_ISOLATE_EVERY_FILE=1` isolates every file to confirm a leak. Windows always isolates every file, because native addons kept across files corrupt the heap.
|
||||
- Slow typechecks: where supported, `pnpm tc` keeps incremental caches in `.cache/typecheck/`; delete it to force a fresh check.
|
||||
|
||||
@@ -249,11 +249,9 @@ Associez-la à l'app de bureau pour surveiller et piloter vos agents depuis votr
|
||||
|
||||
- **Discord :** Rejoignez la communauté sur **[Discord](https://discord.gg/fzjDKHxv8Q)**.
|
||||
- **Twitter / X :** Suivez **[@orca_build](https://x.com/orca_build)** pour les news et annonces.
|
||||
- **WeChat :** Scannez pour rejoindre un groupe WeChat de la communauté Orca. Si un groupe est complet, rejoignez-en un autre.
|
||||
- **WeChat :** Scannez pour rejoindre un groupe WeChat de la communauté Orca.
|
||||
|
||||
<img src="../assets/wechat-qr-group14.jpg" alt="QR code du groupe WeChat de la communauté Orca" width="160" />
|
||||
<img src="../assets/wechat-qr-group15.jpg" alt="QR code du groupe WeChat de la communauté Orca" width="160" />
|
||||
<img src="../assets/wechat-qr-group16.jpg" alt="QR code du groupe WeChat de la communauté Orca" width="160" />
|
||||
<img src="../assets/wechat-qr.jpg" alt="QR code du groupe WeChat de la communauté Orca" width="160" />
|
||||
|
||||
- **Feedback & idées :** On ship vite. Il manque quelque chose ? [Demandez une feature](https://github.com/stablyai/orca/issues).
|
||||
- **Confidentialité :** Voir la [doc confidentialité & télémétrie](https://www.onorca.dev/docs/telemetry) pour ce qu'Orca collecte en anonyme et comment désactiver la télémétrie.
|
||||
|
||||
@@ -244,11 +244,9 @@ yay -S stably-orca-bin
|
||||
|
||||
- **Discord:** **[Discord](https://discord.gg/fzjDKHxv8Q)** 커뮤니티에 참여하세요.
|
||||
- **Twitter / X:** 업데이트와 공지는 **[@orca_build](https://x.com/orca_build)** 를 팔로우하세요.
|
||||
- **WeChat:** QR 코드를 스캔해 Orca 커뮤니티 WeChat 그룹에 참여하세요. 한 그룹이 가득 찼다면 다른 그룹에 참여하세요.
|
||||
- **WeChat:** QR 코드를 스캔해 Orca 커뮤니티 WeChat 그룹에 참여하세요.
|
||||
|
||||
<img src="../assets/wechat-qr-group14.jpg" alt="Orca 커뮤니티 WeChat 그룹 QR 코드" width="160" />
|
||||
<img src="../assets/wechat-qr-group15.jpg" alt="Orca 커뮤니티 WeChat 그룹 QR 코드" width="160" />
|
||||
<img src="../assets/wechat-qr-group16.jpg" alt="Orca 커뮤니티 WeChat 그룹 QR 코드" width="160" />
|
||||
<img src="../assets/wechat-qr.jpg" alt="Orca 커뮤니티 WeChat 그룹 QR 코드" width="160" />
|
||||
|
||||
- **피드백과 아이디어:** 우리는 빠르게 출시합니다. 필요한 기능이 있나요? [새 기능을 요청](https://github.com/stablyai/orca/issues)하세요.
|
||||
- **개인정보 보호:** Orca가 수집하는 익명 사용 데이터와 수집 거부 방법은 [개인정보 및 텔레메트리 문서](https://www.onorca.dev/docs/telemetry)를 참고하세요.
|
||||
|
||||
@@ -245,11 +245,9 @@ yay -S stably-orca-bin
|
||||
|
||||
- **Discord:** Присоединяйтесь к сообществу в **[Discord](https://discord.gg/fzjDKHxv8Q)**.
|
||||
- **Twitter / X:** Подпишитесь на **[@orca_build](https://x.com/orca_build)**, чтобы узнавать об обновлениях и анонсах.
|
||||
- **WeChat:** Отсканируйте QR-код, чтобы присоединиться к группе сообщества Orca в WeChat. Если одна группа заполнена, присоединяйтесь к другой.
|
||||
- **WeChat:** Отсканируйте QR-код, чтобы присоединиться к группе сообщества Orca в WeChat.
|
||||
|
||||
<img src="../assets/wechat-qr-group14.jpg" alt="QR-код группы сообщества Orca в WeChat" width="160" />
|
||||
<img src="../assets/wechat-qr-group15.jpg" alt="QR-код группы сообщества Orca в WeChat" width="160" />
|
||||
<img src="../assets/wechat-qr-group16.jpg" alt="QR-код группы сообщества Orca в WeChat" width="160" />
|
||||
<img src="../assets/wechat-qr.jpg" alt="QR-код группы сообщества Orca в WeChat" width="160" />
|
||||
|
||||
- **Отзывы и идеи:** Мы быстро выпускаем обновления. Чего-то не хватает? [Предложите новую возможность](https://github.com/stablyai/orca/issues).
|
||||
- **Конфиденциальность:** В [документации о конфиденциальности и телеметрии](https://www.onorca.dev/docs/telemetry) описано, какие анонимные данные об использовании собирает Orca и как отказаться от их сбора.
|
||||
|
||||
@@ -242,11 +242,9 @@ Ajanlarınızı telefonunuzdan izlemek ve yönlendirmek için masaüstü uygulam
|
||||
|
||||
- **Discord:** Topluluğa **[Discord](https://discord.gg/fzjDKHxv8Q)** üzerinden katılın.
|
||||
- **Twitter / X:** Güncellemeler ve duyurular için **[@orca_build](https://x.com/orca_build)** hesabını takip edin.
|
||||
- **WeChat:** Orca topluluğunun bir WeChat grubuna katılmak için karekodu okutun. Bir grup doluysa başka bir gruba katılabilirsiniz.
|
||||
- **WeChat:** Orca topluluğunun bir WeChat grubuna katılmak için karekodu okutun.
|
||||
|
||||
<img src="../assets/wechat-qr-group14.jpg" alt="Orca topluluğunun WeChat grubu karekodu" width="160" />
|
||||
<img src="../assets/wechat-qr-group15.jpg" alt="Orca topluluğunun WeChat grubu karekodu" width="160" />
|
||||
<img src="../assets/wechat-qr-group16.jpg" alt="Orca topluluğunun WeChat grubu karekodu" width="160" />
|
||||
<img src="../assets/wechat-qr.jpg" alt="Orca topluluğunun WeChat grubu karekodu" width="160" />
|
||||
|
||||
- **Geri bildirim ve fikirler:** Hızlı sürüm çıkarıyoruz. Eksik bulduğunuz bir şey mi var? [Yeni bir özellik isteyin](https://github.com/stablyai/orca/issues).
|
||||
- **Gizlilik:** Orca'nın hangi anonim kullanım verisini topladığını ve bunu nasıl kapatacağınızı [gizlilik ve telemetri dokümanlarında](https://www.onorca.dev/docs/telemetry) bulabilirsiniz.
|
||||
|
||||
@@ -242,11 +242,9 @@ yay -S stably-orca-bin
|
||||
|
||||
- **Discord:** 加入 **[Discord](https://discord.gg/fzjDKHxv8Q)** 社区。
|
||||
- **Twitter / X:** 关注 **[@orca_build](https://x.com/orca_build)** 获取更新和公告。
|
||||
- **微信:** 扫码加入 Orca 社区微信群。如果一个群已满,可以加入其他群。
|
||||
- **微信:** 扫码加入 Orca 社区微信群。
|
||||
|
||||
<img src="../assets/wechat-qr-group14.jpg" alt="Orca 社区微信群二维码" width="160" />
|
||||
<img src="../assets/wechat-qr-group15.jpg" alt="Orca 社区微信群二维码" width="160" />
|
||||
<img src="../assets/wechat-qr-group16.jpg" alt="Orca 社区微信群二维码" width="160" />
|
||||
<img src="../assets/wechat-qr.jpg" alt="Orca 社区微信群二维码" width="160" />
|
||||
|
||||
- **反馈与想法:** 我们发布很快。缺少什么功能?[提交功能请求](https://github.com/stablyai/orca/issues)。
|
||||
- **隐私:** 查看[隐私与遥测文档](https://www.onorca.dev/docs/telemetry),了解 Orca 收集哪些匿名使用数据以及如何退出。
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<!-- Generated by `pnpm generate:plugin-schemas` from src/shared/plugins. Do not edit. -->
|
||||
|
||||
Host API 1.5 (`"pluginApi": 1`). Workers call a method with `await orca.host.call(name, params)`; panels and custom editors call the same methods through `window.orca.host.call(name, params)`. Each method lists the surfaces allowed to call it; any other surface gets `not_permitted`. `orca.host.has(name)` answers synchronously whether this Orca offers a method on the current surface, and `orca.api` is `{ major, minor }`. See [Plugin authoring](./plugin-authoring.md) for the frame API.
|
||||
Host API 1.6 (`"pluginApi": 1`). Workers call a method with `await orca.host.call(name, params)`; panels and custom editors call the same methods through `window.orca.host.call(name, params)`. Each method lists the surfaces allowed to call it; any other surface gets `not_permitted`. `orca.host.has(name)` answers synchronously whether this Orca offers a method on the current surface, and `orca.api` is `{ major, minor }`. See [Plugin authoring](./plugin-authoring.md) for the frame API.
|
||||
|
||||
Every call is checked against the capabilities the user approved, and params are validated before Orca runs anything: params are strict, so a field this Orca does not know is refused with `invalid_params` instead of being dropped. Mutations are recorded in the audit log as `plugin:<publisher>.<id>`.
|
||||
|
||||
@@ -29,7 +29,7 @@ Methods whose capability is `none` need no capability but still need the plugin
|
||||
| [`files.saveAs`](#filessaveas) | none | panel, editor | yes | 1.1 | Offers data (a string or ArrayBuffer, up to 64 MiB) in Orca's save dialog; the plugin never learns the path. Needs a click or key press in the frame; desktop app only. |
|
||||
| [`plugin.request`](#pluginrequest) | none | panel, editor | no | 1.2 | Asks the plugin's own worker to run the handler it registered with `orca.panels.handle(name)`, starting the worker if needed; resolves with what the handler returned. `unknown_method` when no handler has that name. |
|
||||
| [`agents.list`](#agentslist) | `agent:read` | worker, panel, editor | no | 1.2 | The agents in the focused workspace: their terminal, title, agent kind and status. `agent.status.changed` reports each change after. |
|
||||
| [`events.subscribe`](#eventssubscribe) | none | panel, editor | no | 1.2 | Delivers a workspace or agent event to this panel as `orca.on(event)`; needs the event's read capability. The frame APIs call it for you. |
|
||||
| [`events.subscribe`](#eventssubscribe) | none | panel, editor | no | 1.2 | Delivers a workspace, agent or editor event to this panel as `orca.on(event)`; needs the event's read capability, when it has one. The frame APIs call it for you. |
|
||||
| [`statusBar.update`](#statusbarupdate) | none | worker | no | 1.2 | Changes one of the plugin's `contributes.statusBarItems` (named by `id`): fields given replace their current value, `visible: false` hides it. Desktop app only; lasts until Orca restarts, and is hidden while the plugin is disabled. A plugin with `main` and status bar items has its worker started when it is enabled and kept running while it stays enabled, so a worker can poll and update its items without an event or a hook. |
|
||||
| [`appearance.read`](#appearanceread) | `appearance:write` | worker | no | 1.4 | Reads the current desktop appearance revision for a conditional update. |
|
||||
| [`appearance.apply`](#appearanceapply) | `appearance:write` | worker | yes | 1.4 | Publishes owned app/editor and terminal colors and selects them in the desktop. Returns publication, not renderer acknowledgement. |
|
||||
@@ -41,6 +41,7 @@ Methods whose capability is `none` need no capability but still need the plugin
|
||||
| [`agent.launch`](#agentlaunch) | `agent:launch` | worker | yes | 1.3 | Starts an agent's CLI in a new terminal of a workspace, in the background, and returns as soon as it starts; a `prompt` is sent once the agent is ready. |
|
||||
| [`editor.open`](#editoropen) | `workspace:write` | worker | yes | 1.3 | Opens a file of a workspace in an editor tab of Orca's window; desktop app only. `workspace.open` shows the workspace. |
|
||||
| [`commands.run`](#commandsrun) | `workspace:write` | worker | yes | 1.3 | Runs one of Orca's built-in actions in its window, never a plugin's replacement of it; desktop app only. |
|
||||
| [`editor.readTypography`](#editorreadtypography) | none | worker, panel, editor | no | 1.6 | The font family, size, weight, line height, ligatures, word wrap and minimap Orca's file editor uses now, editor zoom included. `editor.typography.changed` reports each change after. |
|
||||
|
||||
### `workspace.readContext`
|
||||
|
||||
@@ -180,10 +181,10 @@ The agents in the focused workspace: their terminal, title, agent kind and statu
|
||||
|
||||
### `events.subscribe`
|
||||
|
||||
Delivers a workspace or agent event to this panel as `orca.on(event)`; needs the event's read capability. The frame APIs call it for you.
|
||||
Delivers a workspace, agent or editor event to this panel as `orca.on(event)`; needs the event's read capability, when it has one. The frame APIs call it for you.
|
||||
|
||||
```ts
|
||||
(params: { event: "workspace.created" | "workspace.removed" | "agent.status.changed" | "workspace.changed" }) => { ok: true }
|
||||
(params: { event: "workspace.created" | "workspace.removed" | "agent.status.changed" | "workspace.changed" | "editor.typography.changed" }) => { ok: true }
|
||||
```
|
||||
|
||||
### `statusBar.update`
|
||||
@@ -274,9 +275,17 @@ Runs one of Orca's built-in actions in its window, never a plugin's replacement
|
||||
(params: { action: "worktree.history.back" | "worktree.history.forward" | "sidebar.left.toggle" | "sidebar.sleepingWorkspaces.toggle" | "floatingWorkspace.maximize" | "tab.rename" | "workspace.rename" | "workspace.openBoard" | "view.tasks" | "sidebar.right.toggle" | "sidebar.explorer.toggle" | "sidebar.search.toggle" | "sidebar.sourceControl.toggle" | "sidebar.checks.toggle" | "sidebar.ports.toggle" }) => { ran: true }
|
||||
```
|
||||
|
||||
### `editor.readTypography`
|
||||
|
||||
The font family, size, weight, line height, ligatures, word wrap and minimap Orca's file editor uses now, editor zoom included. `editor.typography.changed` reports each change after.
|
||||
|
||||
```ts
|
||||
(params?: {}) => { fontFamily: string; cssFontFamily: string; fontSize: number; fontWeight: string; lineHeight: number; fontLigatures: boolean; wordWrap: "on" | "off"; minimap: boolean }
|
||||
```
|
||||
|
||||
## Events
|
||||
|
||||
A worker receives the events its manifest lists in `contributes.events` through `orca.events.on(event, handler)`, which returns `{ dispose() }`. Each needs `main`, the `trusted-worker` profile and its domain's capability (`workspace:read` or `agent:read`). `orca plugin types` writes the payloads as `PluginEvents` in `orca/host`.
|
||||
A worker receives the events its manifest lists in `contributes.events` through `orca.events.on(event, handler)`, which returns `{ dispose() }`. Each needs `main`, the `trusted-worker` profile and its domain's capability (`workspace:read` or `agent:read`; editor events need none). `orca plugin types` writes the payloads as `PluginEvents` in `orca/host`.
|
||||
|
||||
| Event | Payload | Summary |
|
||||
| --- | --- | --- |
|
||||
@@ -284,6 +293,7 @@ A worker receives the events its manifest lists in `contributes.events` through
|
||||
| `workspace.removed` | `{ workspaceId: string; kind: "worktree" \| "folder"; path: string }` | A worktree workspace was removed. |
|
||||
| `agent.status.changed` | `{ workspaceId: string \| null; paneKey: string; terminalId?: string; title?: string; state: "working" \| "blocked" \| "waiting" \| "done"; receivedAt: number; mainAgent?: { state: "working" \| "blocked" \| "waiting" \| "done"; outcome?: "success" \| "failure" \| "cancellation" \| "superseded" \| "interruption" \| "unconfirmed"; stateStartedAt: number } }` | An agent in a terminal pane changed status; `workspaceId` is null when Orca cannot tie the pane to a workspace, and `terminalId` names its terminal when Orca lists it. |
|
||||
| `workspace.changed` | `{ context: { branch: string; displayName: string; terminals: { id: string; title?: string }[] } \| null }` | The focused workspace changed, or its terminals were opened, closed or renamed; `context` is what `workspace.readContext` now answers. Each new subscriber first gets the current context. |
|
||||
| `editor.typography.changed` | `{ fontFamily: string; cssFontFamily: string; fontSize: number; fontWeight: string; lineHeight: number; fontLigatures: boolean; wordWrap: "on" \| "off"; minimap: boolean }` | What Orca's file editor uses changed (a setting or the editor zoom); the payload is what `editor.readTypography` now answers. Needs no capability. |
|
||||
|
||||
## Hooks
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ Add `"$schema": "https://raw.githubusercontent.com/stablyai/orca/main/docs/schem
|
||||
| `contributes` | object | no | 1.4.160 | What the plugin adds to Orca. Every point defaults to empty. |
|
||||
| `contributes.panels` | [PanelContribution](#panelcontribution)[] | no | 1.4.160 | Sidebar panels. At most 64. |
|
||||
| `contributes.commands` | [CommandContribution](#commandcontribution)[] | no | 1.4.160 | Command palette entries. At most 256. |
|
||||
| `contributes.events` | [EventContribution](#eventcontribution)[] | no | 1.4.160 | Events delivered to the plugin worker. At most 4. |
|
||||
| `contributes.events` | [EventContribution](#eventcontribution)[] | no | 1.4.160 | Events delivered to the plugin worker. At most 5. |
|
||||
| `contributes.hooks` | [HookContribution](#hookcontribution)[] | no | 1.4.248 | Hooks the worker runs before or after Orca acts; Orca waits only on plugins that list one. At most 8. |
|
||||
| `contributes.languagePacks` | [LanguagePackContribution](#languagepackcontribution)[] | no | 1.4.160 | Interface translations. At most 16. |
|
||||
| `contributes.keybindings` | [KeybindingContribution](#keybindingcontribution)[] | no | 1.4.160 | Keyboard shortcuts for contributed commands. At most 256. |
|
||||
@@ -85,11 +85,11 @@ A command palette entry. Requires the `declarative` execution profile or higher.
|
||||
|
||||
## EventContribution
|
||||
|
||||
An event subscription. Requires `main`, the `trusted-worker` execution profile and the capability of the event's domain: `workspace:read` for workspace events, `agent:read` for agent events.
|
||||
An event subscription. Requires `main`, the `trusted-worker` execution profile and the capability of the event's domain: `workspace:read` for workspace events, `agent:read` for agent events. Editor events need no capability.
|
||||
|
||||
| Field | Type | Required | Since | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `on` | `"workspace.created"` \| `"workspace.removed"` \| `"agent.status.changed"` \| `"workspace.changed"` | yes | 1.4.160 | Event delivered to the plugin worker. |
|
||||
| `on` | `"workspace.created"` \| `"workspace.removed"` \| `"agent.status.changed"` \| `"workspace.changed"` \| `"editor.typography.changed"` | yes | 1.4.160 | Event delivered to the plugin worker. |
|
||||
|
||||
## HookContribution
|
||||
|
||||
|
||||
@@ -208,9 +208,9 @@
|
||||
},
|
||||
"events": {
|
||||
"default": [],
|
||||
"description": "Events delivered to the plugin worker. At most 4.",
|
||||
"description": "Events delivered to the plugin worker. At most 5.",
|
||||
"x-orca-since": "1.4.160",
|
||||
"maxItems": 4,
|
||||
"maxItems": 5,
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/EventContribution"
|
||||
@@ -736,7 +736,8 @@
|
||||
"workspace.created",
|
||||
"workspace.removed",
|
||||
"agent.status.changed",
|
||||
"workspace.changed"
|
||||
"workspace.changed",
|
||||
"editor.typography.changed"
|
||||
],
|
||||
"description": "Event delivered to the plugin worker.",
|
||||
"x-orca-since": "1.4.160",
|
||||
@@ -744,7 +745,8 @@
|
||||
"workspace.created": "1.4.245",
|
||||
"workspace.removed": "1.4.245",
|
||||
"agent.status.changed": "1.4.160",
|
||||
"workspace.changed": "1.4.246"
|
||||
"workspace.changed": "1.4.246",
|
||||
"editor.typography.changed": "1.4.256"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -752,7 +754,7 @@
|
||||
"on"
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"description": "An event subscription. Requires `main`, the `trusted-worker` execution profile and the capability of the event's domain: `workspace:read` for workspace events, `agent:read` for agent events."
|
||||
"description": "An event subscription. Requires `main`, the `trusted-worker` execution profile and the capability of the event's domain: `workspace:read` for workspace events, `agent:read` for agent events. Editor events need no capability."
|
||||
},
|
||||
"HookContribution": {
|
||||
"type": "object",
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
} from '../src/notifications/push-receive'
|
||||
import { startPushTokenSync } from '../src/notifications/push-registration'
|
||||
import { ensureDesktopNotificationChannel } from '../src/notifications/desktop-notification-channel'
|
||||
import { loadHostCatalog } from '../src/transport/hosts/host-store'
|
||||
import { loadHostCatalog } from '../src/host-catalog/host-store'
|
||||
import { usePairingLinks } from '../src/navigation/use-pairing-links'
|
||||
import { consumeInitialLaunchIntent } from '../src/navigation/initial-launch-intent'
|
||||
import { recoverMobileRelayPairing } from '../src/pairing/mobile-relay-pairing-recovery'
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from
|
||||
import { View, Text, Pressable } from 'react-native'
|
||||
import { useLocalSearchParams, useRouter } from 'expo-router'
|
||||
import * as Clipboard from 'expo-clipboard'
|
||||
import { loadHosts } from '../src/transport/hosts/host-store'
|
||||
import { loadHosts } from '../src/host-catalog/host-store'
|
||||
import { connectionLogStore } from '../src/diagnostics/connection/persisted-connection-log-store'
|
||||
import { useRpcClientContext } from '../src/transport/connection/client-context'
|
||||
import { useHostClient } from '../src/transport/connection/host-client-hooks'
|
||||
@@ -22,7 +22,7 @@ import { connectionDiagnosticsScreenStyles as styles } from '../src/diagnostics/
|
||||
import { useMobileColorScheme } from '../src/theme/use-mobile-color-scheme'
|
||||
import { NATIVE_APP_LOG_ID } from '../src/diagnostics/native-render-log'
|
||||
import type { ConnectionLogEntry } from '../src/diagnostics/connection/connection-log-types'
|
||||
import type { HostProfile } from '../src/transport/hosts/host-profile'
|
||||
import type { HostProfile } from '../src/host-catalog/host-profile'
|
||||
import { pressedStyle } from '../src/theme/mobile-theme'
|
||||
|
||||
// Keep empty snapshot identity stable or useSyncExternalStore rerenders forever.
|
||||
|
||||
@@ -18,7 +18,7 @@ import { NavBar } from '../../../src/components/nav-bar/NavBar'
|
||||
import { NavBarButton } from '../../../src/components/nav-bar/NavBarButton'
|
||||
import { themedStyleSheet } from '../../../src/theme/themed-styles'
|
||||
import { useMobileColorScheme } from '../../../src/theme/use-mobile-color-scheme'
|
||||
import { loadHosts, updateHostNameAndEndpoint } from '../../../src/transport/hosts/host-store'
|
||||
import { loadHosts, updateHostNameAndEndpoint } from '../../../src/host-catalog/host-store'
|
||||
import { displayHostEndpoint } from '../../../src/transport/hosts/host-endpoint'
|
||||
import { resolveHostEndpointEdit } from '../../../src/transport/hosts/host-endpoint-edit'
|
||||
import {
|
||||
@@ -26,12 +26,12 @@ import {
|
||||
usePrimeHosts,
|
||||
useRefreshHostClient
|
||||
} from '../../../src/transport/connection/host-client-hooks'
|
||||
import { removeHostAndCloseClient } from '../../../src/transport/hosts/host-removal-lifecycle'
|
||||
import { useHostDisplay } from '../../../src/transport/hosts/use-host-display'
|
||||
import { removeHostAndCloseClient } from '../../../src/host-catalog/host-removal-lifecycle'
|
||||
import { useHostDisplay } from '../../../src/host-descriptors/use-host-display'
|
||||
import { leaveHostRoute } from '../../../src/host-route-exit'
|
||||
import { ConfirmModal } from '../../../src/components/ConfirmModal'
|
||||
import { ListGroup, ListRow } from '../../../src/components/list/ListGroup'
|
||||
import type { HostProfile } from '../../../src/transport/hosts/host-profile'
|
||||
import type { HostProfile } from '../../../src/host-catalog/host-profile'
|
||||
import { hostOs } from '../../../src/platform/host-os'
|
||||
import { translate } from '../../../src/i18n/mobile-i18n'
|
||||
import { useMobileTranslation } from '../../../src/i18n/use-mobile-translation'
|
||||
|
||||
@@ -12,8 +12,8 @@ import { colors, spacing } from '../src/theme/mobile-theme'
|
||||
import { useMobileColorScheme } from '../src/theme/use-mobile-color-scheme'
|
||||
import type { Translate } from '../src/i18n/mobile-i18n'
|
||||
import { useMobileTranslation } from '../src/i18n/use-mobile-translation'
|
||||
import { loadHosts, peekHosts } from '../src/transport/hosts/host-store'
|
||||
import type { HostProfile } from '../src/transport/hosts/host-profile'
|
||||
import { loadHosts, peekHosts } from '../src/host-catalog/host-store'
|
||||
import type { HostProfile } from '../src/host-catalog/host-profile'
|
||||
import { useFocusedSettingsHostClients } from '../src/settings/settings-host-client-connections'
|
||||
import type { RpcClient } from '../src/transport/rpc/rpc-client-contract'
|
||||
import { LIST_LEADING_INSET, ListRow } from '../src/components/list/ListGroup'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useRouter } from 'expo-router'
|
||||
import { loadHosts, peekHosts } from '../src/transport/hosts/host-store'
|
||||
import type { HostProfile } from '../src/transport/hosts/host-profile'
|
||||
import { loadHosts, peekHosts } from '../src/host-catalog/host-store'
|
||||
import type { HostProfile } from '../src/host-catalog/host-profile'
|
||||
import { useFocusedSettingsHostClients } from '../src/settings/settings-host-client-connections'
|
||||
import VoiceSettingsScreen from '../src/settings/voice-settings-screen'
|
||||
import { nativeVoiceSettingsOperations } from '../src/settings/native-voice-settings-operations'
|
||||
|
||||
@@ -16601,7 +16601,7 @@
|
||||
"id": "notifications-push-registered",
|
||||
"operation": "notifications.push-registration",
|
||||
"family": "notifications.push-registration",
|
||||
"sites": ["mobile/src/notifications/push-registration.ts"],
|
||||
"sites": ["mobile/src/notifications/mobile-push-registration-operations.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -16650,7 +16650,7 @@
|
||||
"id": "notifications-push-gateway-rejected",
|
||||
"operation": "notifications.push-registration",
|
||||
"family": "notifications.push-registration",
|
||||
"sites": ["mobile/src/notifications/push-registration.ts"],
|
||||
"sites": ["mobile/src/notifications/mobile-push-registration-operations.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18029,7 +18029,7 @@
|
||||
"id": "native-chat-write-accepted",
|
||||
"operation": "nativeChat.terminal-write",
|
||||
"family": "nativeChat.terminal-write",
|
||||
"sites": ["mobile/src/session/native-chat/mobile-native-chat-send.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-send.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18065,7 +18065,7 @@
|
||||
"id": "native-chat-write-rejected",
|
||||
"operation": "nativeChat.terminal-write",
|
||||
"family": "nativeChat.terminal-write",
|
||||
"sites": ["mobile/src/session/native-chat/mobile-native-chat-send.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-send.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18101,7 +18101,7 @@
|
||||
"id": "native-chat-write-delivery-unknown",
|
||||
"operation": "nativeChat.terminal-write",
|
||||
"family": "nativeChat.terminal-write",
|
||||
"sites": ["mobile/src/session/native-chat/mobile-native-chat-send.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-send.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18133,7 +18133,7 @@
|
||||
"id": "native-chat-write-clear-line",
|
||||
"operation": "nativeChat.terminal-write",
|
||||
"family": "nativeChat.terminal-write",
|
||||
"sites": ["mobile/src/session/native-chat/mobile-native-chat-send.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-send.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18169,7 +18169,7 @@
|
||||
"id": "native-chat-write-typed-command",
|
||||
"operation": "nativeChat.terminal-write",
|
||||
"family": "nativeChat.terminal-write",
|
||||
"sites": ["mobile/src/session/native-chat/mobile-native-chat-send.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/mobile-native-chat-send.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18840,7 +18840,9 @@
|
||||
"id": "structured-launch-unsupported",
|
||||
"operation": "agentSession.structured-launch",
|
||||
"family": "agentSession.structured-launch",
|
||||
"sites": ["mobile/src/session/mobile-structured-agent-session-launch.ts"],
|
||||
"sites": [
|
||||
"mobile/src/session/native-chat/agent-session/mobile-structured-agent-session-launch.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18870,7 +18872,9 @@
|
||||
"id": "structured-launch-support-refused",
|
||||
"operation": "agentSession.structured-launch",
|
||||
"family": "agentSession.structured-launch",
|
||||
"sites": ["mobile/src/session/mobile-structured-agent-session-launch.ts"],
|
||||
"sites": [
|
||||
"mobile/src/session/native-chat/agent-session/mobile-structured-agent-session-launch.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18900,7 +18904,9 @@
|
||||
"id": "structured-launch-created",
|
||||
"operation": "agentSession.structured-launch",
|
||||
"family": "agentSession.structured-launch",
|
||||
"sites": ["mobile/src/session/mobile-structured-agent-session-launch.ts"],
|
||||
"sites": [
|
||||
"mobile/src/session/native-chat/agent-session/mobile-structured-agent-session-launch.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -18951,7 +18957,9 @@
|
||||
"id": "structured-launch-definitive-refusal",
|
||||
"operation": "agentSession.structured-launch",
|
||||
"family": "agentSession.structured-launch",
|
||||
"sites": ["mobile/src/session/mobile-structured-agent-session-launch.ts"],
|
||||
"sites": [
|
||||
"mobile/src/session/native-chat/agent-session/mobile-structured-agent-session-launch.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -19003,7 +19011,9 @@
|
||||
"id": "structured-launch-replays-dropped-create",
|
||||
"operation": "agentSession.structured-launch",
|
||||
"family": "agentSession.structured-launch",
|
||||
"sites": ["mobile/src/session/mobile-structured-agent-session-launch.ts"],
|
||||
"sites": [
|
||||
"mobile/src/session/native-chat/agent-session/mobile-structured-agent-session-launch.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -19443,7 +19453,7 @@
|
||||
"id": "native-chat-stop-accepted",
|
||||
"operation": "session.native-chat-stop",
|
||||
"family": "session.native-chat-stop",
|
||||
"sites": ["mobile/src/session/native-chat/use-mobile-native-chat-stop.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/use-mobile-native-chat-stop.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -19504,7 +19514,7 @@
|
||||
"id": "native-chat-stop-both-rejected",
|
||||
"operation": "session.native-chat-stop",
|
||||
"family": "session.native-chat-stop",
|
||||
"sites": ["mobile/src/session/native-chat/use-mobile-native-chat-stop.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/use-mobile-native-chat-stop.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -19562,7 +19572,7 @@
|
||||
"id": "native-chat-stop-delivery-unknown",
|
||||
"operation": "session.native-chat-stop",
|
||||
"family": "session.native-chat-stop",
|
||||
"sites": ["mobile/src/session/native-chat/use-mobile-native-chat-stop.ts"],
|
||||
"sites": ["mobile/src/session/native-chat/composer/use-mobile-native-chat-stop.ts"],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
@@ -19962,7 +19972,7 @@
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-comment-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-git-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-send-actions.ts",
|
||||
"mobile/src/session/native-chat/mobile-native-chat-stale-input.ts"
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-stale-input.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
@@ -20039,7 +20049,7 @@
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-comment-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-git-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-send-actions.ts",
|
||||
"mobile/src/session/native-chat/mobile-native-chat-stale-input.ts"
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-stale-input.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
@@ -20117,7 +20127,7 @@
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-comment-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-git-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-send-actions.ts",
|
||||
"mobile/src/session/native-chat/mobile-native-chat-stale-input.ts"
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-stale-input.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
@@ -20152,7 +20162,7 @@
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-comment-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-git-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-send-actions.ts",
|
||||
"mobile/src/session/native-chat/mobile-native-chat-stale-input.ts"
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-stale-input.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
@@ -20188,7 +20198,7 @@
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-comment-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-git-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-send-actions.ts",
|
||||
"mobile/src/session/native-chat/mobile-native-chat-stale-input.ts"
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-stale-input.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
@@ -20224,7 +20234,7 @@
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-comment-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-git-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-send-actions.ts",
|
||||
"mobile/src/session/native-chat/mobile-native-chat-stale-input.ts"
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-stale-input.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
@@ -20280,7 +20290,7 @@
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-comment-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-git-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-send-actions.ts",
|
||||
"mobile/src/session/native-chat/mobile-native-chat-stale-input.ts"
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-stale-input.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
@@ -24889,7 +24899,7 @@
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-comment-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-git-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-send-actions.ts",
|
||||
"mobile/src/session/native-chat/mobile-native-chat-stale-input.ts"
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-stale-input.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
@@ -24944,7 +24954,7 @@
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-comment-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-git-actions.ts",
|
||||
"mobile/src/source-control/review/use-mobile-diff-review-send-actions.ts",
|
||||
"mobile/src/session/native-chat/mobile-native-chat-stale-input.ts"
|
||||
"mobile/src/session/native-chat/composer/mobile-native-chat-stale-input.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
@@ -25018,7 +25028,9 @@
|
||||
"id": "structured-agent-session-created",
|
||||
"operation": "agentSession.structured-launch",
|
||||
"family": "agentSession.structured-create",
|
||||
"sites": ["mobile/src/session/mobile-structured-agent-session-launch.ts"],
|
||||
"sites": [
|
||||
"mobile/src/session/native-chat/agent-session/mobile-structured-agent-session-launch.ts"
|
||||
],
|
||||
"schedules": [],
|
||||
"steps": [
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ import { View, Text, ScrollView, ActivityIndicator } from 'react-native'
|
||||
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import { useFocusEffect, useLocalSearchParams } from 'expo-router'
|
||||
import { ChevronLeft, RefreshCw, User } from 'lucide-react-native'
|
||||
import { loadHosts, peekHosts } from '../transport/hosts/host-store'
|
||||
import { loadHosts, peekHosts } from '../host-catalog/host-store'
|
||||
import { useForceReconnect, useHostClient } from '../transport/connection/host-client-hooks'
|
||||
import { useHostConnectionInputs } from '../transport/connection/client-context-connection-metrics'
|
||||
import { classifyConnection, isConnectionOutage } from '../transport/connection/connection-health'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { openMobileAgentHistoryChat } from './open-mobile-agent-history-chat'
|
||||
import { mobileStructuredSessionOpenMessage } from '../session/mobile-structured-session-open-message'
|
||||
import { mobileStructuredSessionOpenMessage } from '../session/native-chat/agent-session/mobile-structured-session-open-message'
|
||||
import { prepareMobileHistoryResumeTarget } from './mobile-history-resume-target-preparation'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { View } from 'react-native'
|
||||
|
||||
@@ -16,7 +16,7 @@ import type { TuiAgent } from '../../../src/shared/agent-launch/catalog/tui-agen
|
||||
import { parseWslUncPath } from '../../../src/shared/wsl-paths'
|
||||
import { resolveWindowsShellStartupFamily } from '../../../src/shared/windows-terminal-shell'
|
||||
import { RESUME_RPC_TIMEOUT_MS } from './ai-vault-resume-preparation'
|
||||
import type { RpcOperationSender } from '../transport/rpc/rpc-operation-sender'
|
||||
import type { UnvalidatedRpcRequestPort } from '../transport/rpc/unvalidated-rpc-request-port'
|
||||
import { interpretOrThrowRefusalMessage } from '../transport/rpc/rpc-refusal-message'
|
||||
import {
|
||||
reviewTerminalCreateRun,
|
||||
@@ -78,7 +78,7 @@ export function buildMobileAiVaultResumeLaunch(args: {
|
||||
}
|
||||
|
||||
export async function resumeAiVaultSessionInTerminal(
|
||||
client: RpcOperationSender,
|
||||
client: UnvalidatedRpcRequestPort,
|
||||
worktreeId: string,
|
||||
launch: MobileAiVaultResumeLaunch & {
|
||||
clientMutationId?: string
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from '../../../src/shared/ai-vault/resume/ai-vault-resume-preparation'
|
||||
import { LOCAL_EXECUTION_HOST_ID } from '../../../src/shared/execution-host'
|
||||
import { aiVaultResumePreparationRun } from './mobile-ai-vault-resume-operations'
|
||||
import type { RpcOperationSender } from '../transport/rpc/rpc-operation-sender'
|
||||
import type { UnvalidatedRpcRequestPort } from '../transport/rpc/unvalidated-rpc-request-port'
|
||||
import { translate } from '../i18n/mobile-i18n'
|
||||
|
||||
// Why: without an explicit timeout, a socket drop mid-resume parks the request
|
||||
@@ -14,7 +14,7 @@ import { translate } from '../i18n/mobile-i18n'
|
||||
export const RESUME_RPC_TIMEOUT_MS = 30_000
|
||||
|
||||
export async function prepareMobileAiVaultSessionResume(
|
||||
client: RpcOperationSender,
|
||||
client: UnvalidatedRpcRequestPort,
|
||||
session: AiVaultSession
|
||||
): Promise<AiVaultSession> {
|
||||
// Why: per-account repinning runs on the serving host, whose account
|
||||
|
||||
@@ -4,7 +4,6 @@ import '../files/mobile-file-preview-operations'
|
||||
import { aiVaultResumePreparationSchema } from './mobile-ai-vault-resume-reply-schema'
|
||||
import '../browser/mobile-session-browser-reply-schema'
|
||||
import '../files/session-documents/mobile-file-tap-reply-schema'
|
||||
import '../transport/rpc/rpc-uninterpreted-reply-schemas'
|
||||
|
||||
// Legacy resume reads unsupported-method refusals raw to fall back to shared home.
|
||||
export const aiVaultResumePreparationRun = bindDeferredRpcOperation(
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { RpcClient } from '../transport/rpc/rpc-client-contract'
|
||||
import {
|
||||
openMobileStructuredSession,
|
||||
mobileStructuredSessionHref
|
||||
} from '../session/open-mobile-structured-session'
|
||||
} from '../session/native-chat/agent-session/open-mobile-structured-session'
|
||||
|
||||
/** Consume native opens and ambiguous failures; only an explicit pre-effect refusal resumes in a terminal. */
|
||||
export async function openMobileAgentHistoryChat(args: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { mobileStructuredSessionStatusFeed } from '../session/mobile-structured-session-status-feed'
|
||||
import { mobileStructuredSessionStatusFeed } from '../session/native-chat/agent-session/mobile-structured-session-status-feed'
|
||||
import type { AgentSessionConversationNames } from '../../../src/shared/agent-session/agent-session-conversation-names'
|
||||
import { useForceReconnect } from '../transport/connection/host-client-hooks'
|
||||
import { useWorkspaceClient } from '../worktree/use-workspace-client'
|
||||
|
||||
@@ -12,8 +12,8 @@ import { triggerMediumImpact } from '../platform/haptics'
|
||||
import { colors, spacing } from '../theme/mobile-theme'
|
||||
import { themedStyleSheet } from '../theme/themed-styles'
|
||||
import { useMobileColorScheme } from '../theme/use-mobile-color-scheme'
|
||||
import type { HostProfile } from '../transport/hosts/host-profile'
|
||||
import { useHostDisplay } from '../transport/hosts/use-host-display'
|
||||
import type { HostProfile } from '../host-catalog/host-profile'
|
||||
import { useHostDisplay } from '../host-descriptors/use-host-display'
|
||||
import { agentStateLabel, formatTimeAgo, type AgentDotState } from '../worktree/agent-row-display'
|
||||
import { isDisclosureOpen, toggleDisclosure } from '../worktree/agent-child-disclosure'
|
||||
import { areStructurallyEqual } from '../worktree/structural-equality'
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { ConnectionState } from '../transport/connection/connection-state'
|
||||
import type { HostWorktreeInfo } from '../worktree/home-worktree-info'
|
||||
import { buildAgentList, type AgentListSection } from './agent-list-model'
|
||||
import {
|
||||
selectActiveAgents,
|
||||
selectAgentsNeedingYou,
|
||||
type AgentListInput,
|
||||
type AgentListRow,
|
||||
@@ -79,24 +80,22 @@ const statusView = (showWorkers: boolean, unreadOnly = false) => ({
|
||||
|
||||
describe('buildAgentList by status', () => {
|
||||
it('buckets agents by what they ask of the user, newest first, and folds idle ones', () => {
|
||||
const list = buildAgentList(
|
||||
input({
|
||||
mac: {
|
||||
state: 'connected',
|
||||
info: {
|
||||
agents: entries([
|
||||
agent('asking', 'waiting'),
|
||||
agent('older-run', 'working', { stateStartedAt: NOW - 5 * MINUTE }),
|
||||
agent('newer-run', 'working', { stateStartedAt: NOW - 2 * MINUTE }),
|
||||
agent('finished', 'done'),
|
||||
// Silent past the 30-minute freshness window.
|
||||
agent('quiet', 'working', { updatedAt: NOW - 31 * MINUTE })
|
||||
])
|
||||
}
|
||||
const host = input({
|
||||
mac: {
|
||||
state: 'connected',
|
||||
info: {
|
||||
agents: entries([
|
||||
agent('asking', 'waiting'),
|
||||
agent('older-run', 'working', { stateStartedAt: NOW - 5 * MINUTE }),
|
||||
agent('newer-run', 'working', { stateStartedAt: NOW - 2 * MINUTE }),
|
||||
agent('finished', 'done'),
|
||||
// Silent past the 30-minute freshness window.
|
||||
agent('quiet', 'working', { updatedAt: NOW - 31 * MINUTE })
|
||||
])
|
||||
}
|
||||
}),
|
||||
statusView(true)
|
||||
)
|
||||
}
|
||||
})
|
||||
const list = buildAgentList(host, statusView(true))
|
||||
expect(shape(list.sections)).toEqual([
|
||||
{ kind: 'needs-you', rows: ['asking'], workers: [[]], idle: undefined },
|
||||
{
|
||||
@@ -107,6 +106,7 @@ describe('buildAgentList by status', () => {
|
||||
},
|
||||
{ kind: 'done', rows: ['finished'], workers: [[]], idle: ['quiet'] }
|
||||
])
|
||||
expect(panes(selectActiveAgents(host))).toEqual(['asking', 'newer-run', 'older-run'])
|
||||
})
|
||||
|
||||
it('nests workers under their coordinator and still lists the one that needs the user', () => {
|
||||
|
||||
@@ -21,7 +21,14 @@ function oneLine(text: string | null | undefined): string {
|
||||
return text?.replace(/\s+/g, ' ').trim() ?? ''
|
||||
}
|
||||
|
||||
function lastMessage(agent: RuntimeWorktreeAgentRow): string {
|
||||
// A worktree agent row or a session tab's AgentStatusEntry, which leaves these optional.
|
||||
type AgentPreviewSource = Pick<RuntimeWorktreeAgentRow, 'prompt'> & {
|
||||
lastAssistantMessage?: string | null
|
||||
toolName?: string | null
|
||||
toolInput?: string | null
|
||||
}
|
||||
|
||||
function lastMessage(agent: AgentPreviewSource): string {
|
||||
const message = agent.lastAssistantMessage
|
||||
return message ? oneLine(withoutNativeChatVisualDirectiveLines(message)) : ''
|
||||
}
|
||||
@@ -31,7 +38,7 @@ function lastMessage(agent: RuntimeWorktreeAgentRow): string {
|
||||
* (`group` null) shows no tool, since the tool call is long over.
|
||||
*/
|
||||
export function agentListPreview(
|
||||
agent: RuntimeWorktreeAgentRow,
|
||||
agent: AgentPreviewSource,
|
||||
group: AgentStatusGroup | null,
|
||||
title: string
|
||||
): string {
|
||||
|
||||
@@ -159,6 +159,18 @@ export function selectAgentsNeedingYou(input: AgentListInput): AgentListRow[] {
|
||||
.sort(byStatusThenRecent)
|
||||
}
|
||||
|
||||
/** Live agents that need the user or are working, workers included: Feed's Active rows. */
|
||||
export function selectActiveAgents(input: AgentListInput): AgentListRow[] {
|
||||
return input.hosts
|
||||
.flatMap((host) => everyRow(hostAgents(input, host.id).roots))
|
||||
.filter((row) => {
|
||||
const group = agentStatusGroup(row.dotState)
|
||||
return !row.stale && (group === 'needs-you' || group === 'working')
|
||||
})
|
||||
.map(asTopLevel)
|
||||
.sort(byStatusThenRecent)
|
||||
}
|
||||
|
||||
export function countAgentsNeedingYouByHost(
|
||||
rows: readonly AgentListRow[]
|
||||
): Readonly<Record<string, number>> {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { TransientToast, useTransientToast } from '../components/TransientToast'
|
||||
import { useMobileTranslation } from '../i18n/use-mobile-translation'
|
||||
import { useClipboardWriter } from '../platform/clipboard'
|
||||
import { useOpenMobileSession } from '../session/use-open-mobile-session'
|
||||
import type { HostProfile } from '../transport/hosts/host-profile'
|
||||
import type { HostProfile } from '../host-catalog/host-profile'
|
||||
import type { AgentActivityChange, AgentListRow } from './agent-list-rows'
|
||||
import type { AgentListRowHandlers } from './MobileAgentListRows'
|
||||
import type { AgentActivityFailure } from './use-agent-activity-writes'
|
||||
|
||||
@@ -9,8 +9,8 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import { firstParam } from '../navigation/route-param-reader'
|
||||
import { useRouteHandoff } from '../navigation/route-handoff'
|
||||
import { useHostClient } from '../transport/connection/host-client-hooks'
|
||||
import { useHostDisplay } from '../transport/hosts/use-host-display'
|
||||
import { useHostProfile } from '../transport/hosts/use-host-profile'
|
||||
import { useHostDisplay } from '../host-descriptors/use-host-display'
|
||||
import { useHostProfile } from '../host-catalog/use-host-profile'
|
||||
import { useHostProtocolGates } from '../components/host-protocol-gates-context'
|
||||
import { NavBar, NavBarTitleButton } from '../components/nav-bar/NavBar'
|
||||
import { NavBarButton } from '../components/nav-bar/NavBarButton'
|
||||
|
||||
@@ -12,7 +12,8 @@ import type { ExecutionHostId } from '../../../src/shared/execution-host'
|
||||
import type { RpcClient } from '../transport/rpc/rpc-client-contract'
|
||||
import { hostStatusProbe } from '../transport/connection/host-status-probe-operations'
|
||||
import { hostConnectionEpoch, readHostStatusReply } from '../query/host-status-query'
|
||||
import { defineHostQuery, useHostEventRouter, useHostQuery } from '../query/host-query'
|
||||
import { defineHostQuery, useHostQuery } from '../query/host-query'
|
||||
import { useHostEventRouter } from '../query/host-event-router'
|
||||
import { hostQueryKey, type HostQueryTarget } from '../query/host-query-key'
|
||||
import { isHostNotConnectedError } from '../query/host-query-errors'
|
||||
import { readViewBase } from '../query/host-read-client'
|
||||
|
||||
@@ -4,7 +4,6 @@ import '../files/mobile-file-preview-operations'
|
||||
import { browserTabCreatedSchema } from './mobile-session-browser-reply-schema'
|
||||
import '../agent-history/mobile-ai-vault-resume-reply-schema'
|
||||
import '../files/session-documents/mobile-file-tap-reply-schema'
|
||||
import '../transport/rpc/rpc-uninterpreted-reply-schemas'
|
||||
|
||||
export const sessionBrowserTabCreate = bindDeferredRpcOperation(
|
||||
defineRpcOperation({
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
import { probe, publishLayout, mounted, positions } from './drag-reorder-test-harness.test-fixture'
|
||||
import { createElement } from 'react'
|
||||
import { act, create } from 'react-test-renderer'
|
||||
import Animated, { useAnimatedRef, useSharedValue } from 'react-native-reanimated'
|
||||
import { probe, mounted, positions } from './drag-reorder-test-harness.test-fixture'
|
||||
import { act } from 'react-test-renderer'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { DragReorderList } from './DragReorderList'
|
||||
import { GripVertical } from 'lucide-react-native'
|
||||
|
||||
import { queuedMessageStyles } from '../session/native-chat/input/mobile-native-chat-queued-message-styles'
|
||||
import { spacing } from '../theme/mobile-theme'
|
||||
|
||||
describe('drag completion and cancellation', () => {
|
||||
it('restores original positions and writes nothing when an active drag is cancelled', async () => {
|
||||
@@ -204,74 +197,3 @@ describe('late gesture callbacks', () => {
|
||||
expect(fixture.onReorder).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
it('stops scrolling at the viewport edge when rows are replaced', async () => {
|
||||
const fixture = await mounted()
|
||||
probe.viewport = { pageY: 0, height: 100 }
|
||||
await act(async () => {
|
||||
fixture.gesture.start!({ absoluteY: 90, translationY: 0 }, true)
|
||||
probe.frame!({ timeSincePreviousFrame: 16 })
|
||||
})
|
||||
expect(probe.scroll).toHaveBeenCalledTimes(1)
|
||||
await fixture.updateItems(['b', 'c'])
|
||||
await act(async () => probe.frame!({ timeSincePreviousFrame: 16 }))
|
||||
expect(probe.scroll).toHaveBeenCalledTimes(1)
|
||||
expect(probe.frameActive).toHaveBeenLastCalledWith(false)
|
||||
await act(async () => fixture.root.unmount())
|
||||
})
|
||||
|
||||
it('keeps measured rows still on hold, restores cancellation, and drops by moved ID plus neighbor', async () => {
|
||||
const move = vi.fn()
|
||||
function Harness() {
|
||||
return createElement(DragReorderList<string>, {
|
||||
items: ['a', 'b', 'c'],
|
||||
itemKey: (item) => item,
|
||||
rowPresentation: 'plain',
|
||||
renderRow: (item, handle) => createElement('Text', null, item, handle),
|
||||
onMove: move,
|
||||
scrollRef: useAnimatedRef<Animated.ScrollView>(),
|
||||
scrollOffsetY: useSharedValue(0),
|
||||
scrollContentHeight: useSharedValue(140)
|
||||
})
|
||||
}
|
||||
let root: ReturnType<typeof create>
|
||||
await act(async () => {
|
||||
root = create(createElement(Harness))
|
||||
})
|
||||
const handle = root!.root.findAllByType(Animated.View).find((node) => node.props.hitSlop)!
|
||||
const handleStyle = Object.assign({}, ...handle.props.style)
|
||||
const gripWidth = handle.findByType(GripVertical).props.size
|
||||
const width = gripWidth + 2 * handleStyle.paddingHorizontal
|
||||
const left = queuedMessageStyles.row.paddingLeft - handle.props.hitSlop.left
|
||||
const right = queuedMessageStyles.row.paddingLeft + width + handle.props.hitSlop.right
|
||||
expect(handleStyle.paddingHorizontal).toBe(spacing.xs)
|
||||
expect([left, right]).toEqual([4, 62])
|
||||
expect(right - Math.max(0, left)).toBe(58)
|
||||
const rows = root!.root.findAll(
|
||||
(node) => node.type === Animated.View && typeof node.props.onLayout === 'function'
|
||||
)
|
||||
await act(async () =>
|
||||
rows.forEach((row, index) =>
|
||||
row.props.onLayout({ nativeEvent: { layout: { height: index === 0 ? 100 : 20 } } })
|
||||
)
|
||||
)
|
||||
await publishLayout()
|
||||
const gesture = probe.gestures.at(-3)!
|
||||
const at = (translationY: number) => ({ absoluteY: 100 + translationY, translationY })
|
||||
await act(async () => {
|
||||
gesture.start!(at(0), true)
|
||||
gesture.update!(at(0), true)
|
||||
gesture.finalize!(at(0), true)
|
||||
gesture.start!(at(0), true)
|
||||
gesture.update!(at(35), true)
|
||||
gesture.finalize!(at(35), false)
|
||||
})
|
||||
expect(move).not.toHaveBeenCalled()
|
||||
await act(async () => {
|
||||
gesture.start!(at(0), true)
|
||||
gesture.update!(at(35), true)
|
||||
gesture.finalize!(at(35), true)
|
||||
})
|
||||
expect(move).toHaveBeenCalledExactlyOnceWith({ movedId: 'a', afterId: 'c' })
|
||||
await act(async () => root!.unmount())
|
||||
})
|
||||
|
||||
@@ -62,9 +62,9 @@ vi.mock('../host-screen/host-list-queries', () => ({
|
||||
(hostId && cachedRepos.get(hostId)) || null
|
||||
}))
|
||||
|
||||
import '../transport/hosts/host-descriptor-store'
|
||||
import '../host-descriptors/host-descriptor-store'
|
||||
import { FakeSession } from '../transport/connection/mobile-endpoint-supervisor-test-fakes'
|
||||
import { markRpcDeliveryUnknown } from '../transport/rpc/rpc-delivery-ambiguity'
|
||||
|
||||
import '../../../src/shared/execution-host'
|
||||
import type { ExecutionHostId } from '../../../src/shared/execution-host'
|
||||
|
||||
@@ -231,72 +231,6 @@ describe('NewWorktreeModal project targets', () => {
|
||||
expect(runTargetPicker(renderer).props.selectedId).toBe('runtime:env-1')
|
||||
})
|
||||
|
||||
async function submitFromFolder(createReply: () => Promise<RpcResponse>) {
|
||||
const serverRepo = { ...repos[0]!, path: '/srv/orca' }
|
||||
const server = requestsOnly(
|
||||
vi.fn((method: string) =>
|
||||
method === 'repo.list'
|
||||
? replied({ repos: [serverRepo] })
|
||||
: method === 'worktree.create'
|
||||
? createReply()
|
||||
: Promise.reject(new Error(`unexpected ${method}`))
|
||||
)
|
||||
)
|
||||
const settle = vi.fn()
|
||||
|
||||
await act(async () => {
|
||||
renderer = create(
|
||||
createElement(NewWorktreeModal, {
|
||||
visible: true,
|
||||
client: requestsOnly(() => new Promise<never>(() => {})),
|
||||
serverClients: new Map<ExecutionHostId, RpcClient>([['runtime:env-1', server]]),
|
||||
hostId: 'host-1',
|
||||
onCreated: () => {},
|
||||
onClose: () => {},
|
||||
openExternalUrl: () => {},
|
||||
folderLaunch: {
|
||||
repoId: 'repo-1',
|
||||
executionHostId: 'runtime:env-1',
|
||||
name: 'payments',
|
||||
parentWorkspace: 'folder:f-1',
|
||||
submit: { begin: () => ({ settle }), presenting: () => true }
|
||||
}
|
||||
})
|
||||
)
|
||||
})
|
||||
await flushUpdates()
|
||||
const form = renderer.root.find((node) => typeof node.props.onCreate === 'function')
|
||||
await act(async () => form.props.onCreate())
|
||||
await flushUpdates()
|
||||
|
||||
const creates = vi
|
||||
.mocked(server.sendRequest)
|
||||
.mock.calls.filter(([method]) => method === 'worktree.create')
|
||||
return { creates: creates.map(([, params]) => params), settle }
|
||||
}
|
||||
|
||||
it('creates from a folder attached to that folder, on its host', async () => {
|
||||
const { creates, settle } = await submitFromFolder(() =>
|
||||
replied({ worktree: { id: 'repo-1::/srv/w/payments', displayName: 'payments' } })
|
||||
)
|
||||
expect(creates).toEqual([
|
||||
expect.objectContaining({
|
||||
repo: 'id:repo-1',
|
||||
parentWorkspace: 'folder:f-1',
|
||||
parentWorkspaceOrigin: 'manual'
|
||||
})
|
||||
])
|
||||
expect(settle).toHaveBeenCalledWith('created')
|
||||
})
|
||||
|
||||
it("doesn't try another name when a folder create's reply is lost", async () => {
|
||||
const { creates, settle } = await submitFromFolder(() =>
|
||||
Promise.reject(markRpcDeliveryUnknown(new Error('connection lost')))
|
||||
)
|
||||
expect(creates).toHaveLength(1)
|
||||
expect(settle).toHaveBeenCalledWith('uncertain')
|
||||
})
|
||||
|
||||
it('ignores a stale repo list after the client changes', async () => {
|
||||
let resolveOldList: ((value: unknown) => void) | undefined
|
||||
const oldList = new Promise((resolve) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { deriveRepoSlug, type PasteRepoCandidate } from '../tasks/smart-source-p
|
||||
import { useMobileComposerSource } from '../tasks/use-mobile-composer-source'
|
||||
import { useNewWorktreeRuntimeCapabilities } from '../tasks/worktree-create-capability'
|
||||
import { useWorktreeCreateBasePrefetch } from '../tasks/use-worktree-create-base-prefetch'
|
||||
import { useHostDescriptor } from '../transport/hosts/host-descriptor-store'
|
||||
import { useHostDescriptor } from '../host-descriptors/host-descriptor-store'
|
||||
import { isSameMobileWorkspaceRepo } from '../worktree/new-workspace-dialog-repo-selection'
|
||||
import {
|
||||
buildRetiredWorktreeNamesRefreshKey,
|
||||
|
||||
@@ -84,6 +84,8 @@ export function SwipeRowActions({
|
||||
})
|
||||
// Web has no worklet plugin; mapper hooks need this explicit dependency list.
|
||||
const rowStyle = useAnimatedStyle(() => ({ transform: [{ translateX: offset.value }] }), [offset])
|
||||
// Hidden at rest, so the action can't show through a rounded group's antialiased corners.
|
||||
const actionsStyle = useAnimatedStyle(() => ({ opacity: offset.value === 0 ? 0 : 1 }), [offset])
|
||||
// A tap on an open row closes it rather than pressing the row.
|
||||
const guardPress = (onPress: () => void) => () => {
|
||||
// The click a drag release produces belongs to the drag, not to the row.
|
||||
@@ -124,8 +126,10 @@ export function SwipeRowActions({
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
{leading ? renderAction(leading, 'leading') : null}
|
||||
{trailing ? renderAction(trailing, 'trailing') : null}
|
||||
<Animated.View pointerEvents="box-none" style={[styles.actions, actionsStyle]}>
|
||||
{leading ? renderAction(leading, 'leading') : null}
|
||||
{trailing ? renderAction(trailing, 'trailing') : null}
|
||||
</Animated.View>
|
||||
{/* pan-y keeps the page scrolling vertically over the row on the web. */}
|
||||
<GestureDetector gesture={pan} touchAction="pan-y">
|
||||
<Animated.View style={rowStyle}>{children(guardPress)}</Animated.View>
|
||||
@@ -144,6 +148,7 @@ const styles = themedStyleSheet(() => ({
|
||||
justifyContent: 'center',
|
||||
gap: 2
|
||||
},
|
||||
actions: { position: 'absolute', top: 0, right: 0, bottom: 0, left: 0 },
|
||||
leading: { left: 0 },
|
||||
trailing: { right: 0 },
|
||||
actionPressed: { opacity: feedback.pressedOpacity },
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createElement } from 'react'
|
||||
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { HostProfile } from '../transport/hosts/host-profile'
|
||||
import type { HostProfile } from '../host-catalog/host-profile'
|
||||
import { useConnectedHostPicker } from './use-connected-host-picker'
|
||||
|
||||
function host(id: string, name: string, endpoint: string): HostProfile {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useRef, useState } from 'react'
|
||||
import { hostEndpointLabel } from '../transport/hosts/host-endpoint-label'
|
||||
import type { HostProfile } from '../transport/hosts/host-profile'
|
||||
import type { HostProfile } from '../host-catalog/host-profile'
|
||||
|
||||
/** Picker rows for desktops, telling apart two that share a name and endpoint. */
|
||||
export function hostPickerOptions(hosts: HostProfile[]) {
|
||||
|
||||
@@ -44,31 +44,25 @@ afterEach(async () => {
|
||||
})
|
||||
|
||||
describe('useNewWorkspaceRepositories initial repo', () => {
|
||||
it.each([
|
||||
{ order: 'desktop first', desktopFirst: true },
|
||||
{ order: 'server first', desktopFirst: false }
|
||||
])(
|
||||
'picks the named host’s copy of a repo id two hosts share ($order)',
|
||||
async ({ desktopFirst }) => {
|
||||
const client = desktopListing(desktopFirst ? [repo()] : [])
|
||||
let picked: MobileWorkspaceRepo | null = null
|
||||
mounted = hookMount(() => {
|
||||
picked = useNewWorkspaceRepositories({
|
||||
client,
|
||||
hostId: 'host-1',
|
||||
visible: true,
|
||||
initialRepo: { id: 'api', executionHostId: SERVER }
|
||||
}).selectedRepo
|
||||
})
|
||||
mounted.mount()
|
||||
await settleQueryNotifications()
|
||||
// The desktop's same-id repo must not stand in while the server's listing is on its way.
|
||||
expect(picked).toBeNull()
|
||||
it('picks the named host’s copy of a repo id two hosts share', async () => {
|
||||
const client = desktopListing([repo()])
|
||||
let picked: MobileWorkspaceRepo | null = null
|
||||
mounted = hookMount(() => {
|
||||
picked = useNewWorkspaceRepositories({
|
||||
client,
|
||||
hostId: 'host-1',
|
||||
visible: true,
|
||||
initialRepo: { id: 'api', executionHostId: SERVER }
|
||||
}).selectedRepo
|
||||
})
|
||||
mounted.mount()
|
||||
await settleQueryNotifications()
|
||||
// The desktop's same-id repo must not stand in while the server's listing is on its way.
|
||||
expect(picked).toBeNull()
|
||||
|
||||
servers.repos = new Map([[SERVER, [repo(SERVER)]]])
|
||||
act(() => mounted?.update())
|
||||
await settleQueryNotifications()
|
||||
expect(picked).toMatchObject({ id: 'api', executionHostId: SERVER })
|
||||
}
|
||||
)
|
||||
servers.repos = new Map([[SERVER, [repo(SERVER)]]])
|
||||
act(() => mounted?.update())
|
||||
await settleQueryNotifications()
|
||||
expect(picked).toMatchObject({ id: 'api', executionHostId: SERVER })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -7,11 +7,11 @@ import type { AESEncryptionKey } from 'expo-crypto'
|
||||
import { Directory, Paths } from 'expo-file-system'
|
||||
import { AppState } from 'react-native'
|
||||
import { createExpoGenerationFileSystem } from '../mobile-web-shell/generation-store-file-system'
|
||||
import { loadStoredHostProfiles } from '../transport/hosts/host-metadata-store'
|
||||
import { loadStoredHostProfiles } from '../host-catalog/host-metadata-store'
|
||||
import {
|
||||
readPairingKeychainItem,
|
||||
writePairingKeychainItem
|
||||
} from '../transport/hosts/pairing-keychain'
|
||||
} from '../host-credentials/pairing-keychain'
|
||||
import {
|
||||
createRootIndex,
|
||||
DEVICE_STORE_CAPS,
|
||||
|
||||
@@ -5,7 +5,7 @@ import type {
|
||||
MobileConnectionDiagnosticPath
|
||||
} from './connection/connection-log-types'
|
||||
import type { ConnectionState } from '../transport/connection/connection-state'
|
||||
import { normalizeHostAppVersion } from '../transport/hosts/host-app-version'
|
||||
import { normalizeHostAppVersion } from '../host-descriptors/host-app-version'
|
||||
import { formatEndpoint } from './host-reachability'
|
||||
import { diagnoseConnection } from './connection-diagnostics-analysis'
|
||||
import { redactConnectionLogEntry, redactConnectionLogText } from './connection-log-redaction'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { resolveDiagnosticsHostId } from './connection-diagnostics-screen-data'
|
||||
|
||||
import type { HostProfile } from '../transport/hosts/host-profile'
|
||||
import type { HostProfile } from '../host-catalog/host-profile'
|
||||
|
||||
const host = (id: string): HostProfile => ({
|
||||
id,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ConnectionLogStore } from './connection/connection-log-buffer'
|
||||
import type { ConnectionLogEntry } from './connection/connection-log-types'
|
||||
import type { HostProfile } from '../transport/hosts/host-profile'
|
||||
import type { HostProfile } from '../host-catalog/host-profile'
|
||||
import type { RpcClientContextValue } from '../transport/connection/rpc-client-context-contract'
|
||||
|
||||
/** Route identity token: compared by reference to detect navigating away and back, never read. */
|
||||
|
||||