mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
chore(ci): ratchet importers of the deprecated runtime-owner resolvers (#30002)
* chore(ci): ratchet renderer importers of the deprecated runtime-owner resolvers getRuntimeEnvironmentIdForWorktree and resolveRuntimeOwnerForWorktree read a worktree two hosts publish as not-a-runtime, which callers treat as local. The 62 renderer files importing them are grandfathered; the list may only shrink. * ci: register the deprecated runtime-owner ratchet step in the preflight phase map
This commit is contained in:
@@ -386,6 +386,10 @@ jobs:
|
||||
if: needs.code_paths.outputs.static_analysis == 'true'
|
||||
run: bun config/scripts/check-layout-writer-ratchets.mjs
|
||||
|
||||
- name: Enforce deprecated runtime-owner importer ratchet
|
||||
if: needs.code_paths.outputs.static_analysis == 'true'
|
||||
run: node config/scripts/check-deprecated-runtime-owner-ratchet.mjs
|
||||
|
||||
- name: Check Node runtime pin
|
||||
if: needs.code_paths.outputs.static_analysis == 'true'
|
||||
run: node config/scripts/check-node-runtime-pin.mjs
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Renderer files that import getRuntimeEnvironmentIdForWorktree / resolveRuntimeOwnerForWorktree.
|
||||
# This is a RATCHET: the list may only SHRINK. Both resolvers read an ambiguous (two-host)
|
||||
# worktree as "not a runtime", which callers treat as local.
|
||||
# Prune after migrating a file: pnpm check:deprecated-runtime-owner-ratchet --prune
|
||||
src/renderer/src/components/browser-pane/assemble-chrome/browser-workspace-pane.tsx
|
||||
src/renderer/src/components/browser-pane/stream-remote/use-remote-browser-page-lifecycle.ts
|
||||
src/renderer/src/components/browser-pane/workspace-doc/doc-preview-document-actions.ts
|
||||
src/renderer/src/components/browser-pane/workspace-doc/workspace-doc-page-pane.tsx
|
||||
src/renderer/src/components/native-chat/native-chat-file-link.ts
|
||||
src/renderer/src/components/native-chat/native-chat-http-link-source-owner.ts
|
||||
src/renderer/src/components/native-chat/native-chat-runtime-owner.ts
|
||||
src/renderer/src/components/right-sidebar/FileExplorer.tsx
|
||||
src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-controller-state.tsx
|
||||
src/renderer/src/components/right-sidebar/file-explorer-operation-owner.ts
|
||||
src/renderer/src/components/right-sidebar/file-explorer-row-context-menu.tsx
|
||||
src/renderer/src/components/right-sidebar/git-status-file-watch-refresh.ts
|
||||
src/renderer/src/components/right-sidebar/source-control/listing/entry-context-menu.tsx
|
||||
src/renderer/src/components/right-sidebar/use-file-explorer-tree-pane-state.ts
|
||||
src/renderer/src/components/right-sidebar/useFileSearchRunner.ts
|
||||
src/renderer/src/components/right-sidebar/useFileSearchScope.ts
|
||||
src/renderer/src/components/tab-bar/use-tab-bar-runtime-model.ts
|
||||
src/renderer/src/components/tab-bar/web-runtime-tab-move-mirror.ts
|
||||
src/renderer/src/components/tab-group/useTabGroupActivationCommands.ts
|
||||
src/renderer/src/components/tab-group/useTabGroupCreationCommands.ts
|
||||
src/renderer/src/components/terminal-pane/terminal-input-host-platform.ts
|
||||
src/renderer/src/components/terminal-pane/terminal-pane-menu-paste.ts
|
||||
src/renderer/src/components/terminal-pane/terminal-pane-paste-execution.ts
|
||||
src/renderer/src/components/terminal-pane/terminal-pane-paste-listeners.ts
|
||||
src/renderer/src/components/terminal-workspace-model.ts
|
||||
src/renderer/src/hooks/editor-external-watch-targets.ts
|
||||
src/renderer/src/hooks/ipc-events/browser-state-ipc-bridge.ts
|
||||
src/renderer/src/hooks/ipc-events/tab-lifecycle-ipc-bridge.ts
|
||||
src/renderer/src/lib/activate-ai-vault-structured-session.ts
|
||||
src/renderer/src/lib/active-agent-note-send.ts
|
||||
src/renderer/src/lib/active-agent-note-target.ts
|
||||
src/renderer/src/lib/agent-hibernation-coordinator.ts
|
||||
src/renderer/src/lib/client-creation-action-policy.ts
|
||||
src/renderer/src/lib/doc-preview-grants.ts
|
||||
src/renderer/src/lib/execute-open-editor-path-move.ts
|
||||
src/renderer/src/lib/execution-host-facts.ts
|
||||
src/renderer/src/lib/file-preview.ts
|
||||
src/renderer/src/lib/host-mirrored-pane-liveness.ts
|
||||
src/renderer/src/lib/launch-agent-background-session.ts
|
||||
src/renderer/src/lib/launch-agent-in-new-tab.ts
|
||||
src/renderer/src/lib/launch-ai-vault-session.ts
|
||||
src/renderer/src/lib/structured-agent-session-tab-activation.ts
|
||||
src/renderer/src/lib/tab-number-shortcuts.ts
|
||||
src/renderer/src/lib/terminal-tab-owner-activation.ts
|
||||
src/renderer/src/lib/terminal-worktree-route.ts
|
||||
src/renderer/src/lib/web-runtime-worktree-terminal-after-wake.ts
|
||||
src/renderer/src/lib/workspace-browser-tab-close.ts
|
||||
src/renderer/src/lib/workspace-tab-palette-activation.ts
|
||||
src/renderer/src/lib/worktree-activation-pty-inventory.ts
|
||||
src/renderer/src/lib/worktree-activation.ts
|
||||
src/renderer/src/lib/worktree-creation-agent-seeds.ts
|
||||
src/renderer/src/lib/worktree-row-open-in-owner.ts
|
||||
src/renderer/src/lib/worktree-sort-order-host-split.ts
|
||||
src/renderer/src/runtime/close-mirrored-editor-tab.ts
|
||||
src/renderer/src/runtime/web-runtime-terminal-actions.ts
|
||||
src/renderer/src/store/slices/browser/browser-page-conversion-actions.ts
|
||||
src/renderer/src/store/slices/browser/browser-tab-actions.ts
|
||||
src/renderer/src/store/slices/tabs/tabs-host-mirroring.ts
|
||||
src/renderer/src/store/slices/terminal-tab-retirement.ts
|
||||
src/renderer/src/store/terminals/terminal-active-workspace-creation.ts
|
||||
src/renderer/src/store/terminals/terminal-pane-hibernation.ts
|
||||
src/renderer/src/store/terminals/terminal-shutdown.ts
|
||||
@@ -0,0 +1,70 @@
|
||||
import process from 'node:process'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { readTrackedSources, runEntryRatchet } from './ratchet-baseline.mjs'
|
||||
|
||||
// Ratchet on renderer files that import the deprecated runtime-owner resolvers. Both read a
|
||||
// worktree that two hosts publish as "not a runtime", which callers then treat as local, so a stop,
|
||||
// sleep or kill can land on the wrong machine. New code resolves the owner with its host and
|
||||
// ambiguity kept; the importer list may only shrink.
|
||||
|
||||
const BASELINE_PATH = 'config/deprecated-runtime-owner-importers-baseline.txt'
|
||||
const SCAN_ROOT = 'src/renderer/src'
|
||||
const DEPRECATED_NAMES = ['getRuntimeEnvironmentIdForWorktree', 'resolveRuntimeOwnerForWorktree']
|
||||
// The defining module and its own tests are not importers.
|
||||
const DEFINING_FILE = 'src/renderer/src/lib/worktree-runtime-owner.ts'
|
||||
|
||||
// Any reference to a deprecated name in a file that loads the defining module, whatever the import
|
||||
// form (named, aliased, namespace, dynamic, `.then` destructuring, re-export). Simpler than tracking
|
||||
// bindings, and in production code a mention of these names is a use.
|
||||
const DEPRECATED_NAME = new RegExp(`\\b(?:${DEPRECATED_NAMES.join('|')})\\b`)
|
||||
const DEFINING_MODULE_SPECIFIER = /['"`][^'"`]*\/worktree-runtime-owner['"`]/
|
||||
// Block and line comments; `://` inside a string (a URL) is not a line comment.
|
||||
const COMMENT = /\/\*[\s\S]*?\*\/|(?<![:'"`\\])\/\/.*$/gm
|
||||
|
||||
export function isScannedPath(rel) {
|
||||
return (
|
||||
rel.startsWith(`${SCAN_ROOT}/`) &&
|
||||
/\.(ts|tsx)$/.test(rel) &&
|
||||
!/\.(test|spec)(?:-fixture|-support)?\.tsx?$/.test(rel) &&
|
||||
rel !== DEFINING_FILE
|
||||
)
|
||||
}
|
||||
|
||||
/** True when uncommented code loads the defining module and names a deprecated resolver. */
|
||||
export function importsDeprecatedRuntimeOwner(sourceText) {
|
||||
const code = sourceText.replace(COMMENT, ' ')
|
||||
return DEFINING_MODULE_SPECIFIER.test(code) && DEPRECATED_NAME.test(code)
|
||||
}
|
||||
|
||||
export function collectDeprecatedRuntimeOwnerImporters(root = process.cwd()) {
|
||||
const sources = readTrackedSources(root, [SCAN_ROOT], isScannedPath)
|
||||
return [...sources]
|
||||
.filter(([, source]) => importsDeprecatedRuntimeOwner(source))
|
||||
.map(([rel]) => rel)
|
||||
.sort()
|
||||
}
|
||||
|
||||
const RATCHET = {
|
||||
name: 'deprecated-runtime-owner',
|
||||
baselinePath: BASELINE_PATH,
|
||||
header: [
|
||||
'# Renderer files that import getRuntimeEnvironmentIdForWorktree / resolveRuntimeOwnerForWorktree.',
|
||||
'# This is a RATCHET: the list may only SHRINK. Both resolvers read an ambiguous (two-host)',
|
||||
'# worktree as "not a runtime", which callers treat as local.',
|
||||
'# Prune after migrating a file: pnpm check:deprecated-runtime-owner-ratchet --prune'
|
||||
],
|
||||
collect: collectDeprecatedRuntimeOwnerImporters,
|
||||
fix: [
|
||||
'getRuntimeEnvironmentIdForWorktree / resolveRuntimeOwnerForWorktree collapse an owner that two',
|
||||
'hosts publish into "local". Resolve the owner with its host kept and refuse on ambiguity',
|
||||
'instead (see src/renderer/src/lib/resolve-owner.ts).'
|
||||
]
|
||||
}
|
||||
|
||||
export function main(root = process.cwd(), arg = undefined) {
|
||||
return runEntryRatchet(RATCHET, root, arg)
|
||||
}
|
||||
|
||||
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
||||
process.exit(main(process.cwd(), process.argv[2]))
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import {
|
||||
importsDeprecatedRuntimeOwner,
|
||||
isScannedPath
|
||||
} from './check-deprecated-runtime-owner-ratchet.mjs'
|
||||
|
||||
describe('importsDeprecatedRuntimeOwner', () => {
|
||||
it('finds a named import of either deprecated resolver', () => {
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'\n"
|
||||
)
|
||||
).toBe(true)
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"import {\n foo,\n resolveRuntimeOwnerForWorktree\n} from './worktree-runtime-owner'\n"
|
||||
)
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('finds an aliased import, a re-export and a dynamic import', () => {
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"import { getRuntimeEnvironmentIdForWorktree as envFor } from '@/lib/worktree-runtime-owner'"
|
||||
)
|
||||
).toBe(true)
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"export { resolveRuntimeOwnerForWorktree } from './worktree-runtime-owner'"
|
||||
)
|
||||
).toBe(true)
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"const { getRuntimeEnvironmentIdForWorktree } = await import('@/lib/worktree-runtime-owner')"
|
||||
)
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('finds a use through a namespace import or a module-valued dynamic import', () => {
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"import * as owner from '@/lib/worktree-runtime-owner'\nowner.getRuntimeEnvironmentIdForWorktree(s, id)"
|
||||
)
|
||||
).toBe(true)
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"const mod = await import('@/lib/worktree-runtime-owner')\nmod.resolveRuntimeOwnerForWorktree(s, id)"
|
||||
)
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('finds destructuring in a promise-based dynamic import', () => {
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"import('@/lib/worktree-runtime-owner').then(({ resolveRuntimeOwnerForWorktree }) => resolveRuntimeOwnerForWorktree(s, id))"
|
||||
)
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('reads through comments inside an import list, and ignores a commented-out import', () => {
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"import { /* legacy */ getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'"
|
||||
)
|
||||
).toBe(true)
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"import {\n a, // keep\n resolveRuntimeOwnerForWorktree\n} from './worktree-runtime-owner'"
|
||||
)
|
||||
).toBe(true)
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"// import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'\n/* owner.resolveRuntimeOwnerForWorktree() */"
|
||||
)
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('ignores other names from the module, and same-named functions from other modules', () => {
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"import { getExecutionHostIdForWorktree } from '@/lib/worktree-runtime-owner'"
|
||||
)
|
||||
).toBe(false)
|
||||
expect(
|
||||
importsDeprecatedRuntimeOwner(
|
||||
"import { getRuntimeEnvironmentIdForWorktree } from '@/lib/other-owner'"
|
||||
)
|
||||
).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('isScannedPath', () => {
|
||||
it('scans renderer sources only, not tests or the defining module', () => {
|
||||
expect(isScannedPath('src/renderer/src/store/terminals/terminal-shutdown.ts')).toBe(true)
|
||||
expect(isScannedPath('src/renderer/src/store/terminals/terminal-shutdown.test.ts')).toBe(false)
|
||||
expect(isScannedPath('src/renderer/src/store/host-twin.test-fixture.ts')).toBe(false)
|
||||
expect(isScannedPath('src/renderer/src/lib/worktree-runtime-owner.ts')).toBe(false)
|
||||
expect(isScannedPath('src/main/runtime/foo.ts')).toBe(false)
|
||||
})
|
||||
})
|
||||
@@ -242,6 +242,7 @@ it('pins every foreground and background step to its selected phase', () => {
|
||||
['Enforce runtime Electron-import ratchet', staticPhase],
|
||||
['Enforce focus-read ratchet', staticPhase],
|
||||
['Enforce layout-writer ratchets', staticPhase],
|
||||
['Enforce deprecated runtime-owner importer ratchet', staticPhase],
|
||||
['Check Node runtime pin', staticPhase],
|
||||
['Decide whether the orcad terminal smoke runs', staticPhase],
|
||||
['Verify the generated RPC params catalog', staticPhase],
|
||||
|
||||
+2
-1
@@ -14,7 +14,7 @@
|
||||
"audit:perf": "oxlint --config config/oxlint-performance-audit.json --format json src",
|
||||
"test:perf:contracts": "vitest run --config config/vitest.performance.config.ts",
|
||||
"format": "oxfmt --write .",
|
||||
"lint": "oxlint && pnpm run audit:anti-slop && pnpm run audit:code-quality:native && pnpm run audit:code-quality:type-aware && pnpm run check:reliability-gates && pnpm run check:dead-classes && pnpm run check:max-lines-ratchet && pnpm run check:ts-nocheck-ratchet && pnpm run check:runtime-electron-ratchet && pnpm run check:focus-read-ratchet && pnpm run check:layout-writer-ratchets && pnpm run check:readme-local-links && pnpm run check:node-runtime-pin && pnpm run verify:rpc-params-catalog && pnpm run verify:acp-protocol && pnpm run verify:bundled-skill-guides && pnpm run verify:skill-bundle-manifest && pnpm run verify:localization-catalogs && pnpm run verify:localization-extraction && pnpm run verify:localization-coverage && pnpm run check:process-host-imports && pnpm run check:main-sync-spawn-ratchet && pnpm run check:compat-boundary-imports",
|
||||
"lint": "oxlint && pnpm run audit:anti-slop && pnpm run audit:code-quality:native && pnpm run audit:code-quality:type-aware && pnpm run check:reliability-gates && pnpm run check:dead-classes && pnpm run check:max-lines-ratchet && pnpm run check:ts-nocheck-ratchet && pnpm run check:runtime-electron-ratchet && pnpm run check:focus-read-ratchet && pnpm run check:layout-writer-ratchets && pnpm run check:deprecated-runtime-owner-ratchet && pnpm run check:readme-local-links && pnpm run check:node-runtime-pin && pnpm run verify:rpc-params-catalog && pnpm run verify:acp-protocol && pnpm run verify:bundled-skill-guides && pnpm run verify:skill-bundle-manifest && pnpm run verify:localization-catalogs && pnpm run verify:localization-extraction && pnpm run verify:localization-coverage && pnpm run check:process-host-imports && pnpm run check:main-sync-spawn-ratchet && pnpm run check:compat-boundary-imports",
|
||||
"audit:code-quality": "pnpm run audit:code-quality:native && pnpm run audit:code-quality:type-aware && pnpm run audit:react-doctor",
|
||||
"audit:code-quality:native": "oxlint --config config/oxlint-code-quality-native-plugins.json src config tests mobile --deny-warnings",
|
||||
"audit:code-quality:type-aware": "oxlint --type-aware --config config/oxlint-code-quality-type-aware.json src config tests --deny-warnings",
|
||||
@@ -38,6 +38,7 @@
|
||||
"check:reliability-gates": "node config/scripts/check-reliability-gates.mjs",
|
||||
"check:max-lines-ratchet": "node config/scripts/check-max-lines-ratchet.mjs",
|
||||
"check:ts-nocheck-ratchet": "node config/scripts/check-ts-nocheck-ratchet.mjs",
|
||||
"check:deprecated-runtime-owner-ratchet": "node config/scripts/check-deprecated-runtime-owner-ratchet.mjs",
|
||||
"check:runtime-electron-ratchet": "node config/scripts/check-runtime-electron-ratchet.mjs",
|
||||
"check:focus-read-ratchet": "node config/scripts/check-focus-read-ratchet.mjs",
|
||||
"check:layout-writer-ratchets": "node config/scripts/check-layout-writer-ratchets.mjs",
|
||||
|
||||
Reference in New Issue
Block a user