diff --git a/config/scripts/generate-bundled-skill-guides.test.mjs b/config/scripts/generate-bundled-skill-guides.test.mjs index 6e5da34b6e5..7ce3d5d2d78 100644 --- a/config/scripts/generate-bundled-skill-guides.test.mjs +++ b/config/scripts/generate-bundled-skill-guides.test.mjs @@ -11,6 +11,7 @@ import { STUB_TOPICS, assertAliasContract, buildArtifacts, + composeStubProjection, frontmatterBlock, normalizeMarkdown, parseFrontmatter, @@ -72,16 +73,19 @@ afterEach(async () => { describe('bundled skill guide generator', () => { it('projects stub topics as hybrid discovery stubs that reuse the guide frontmatter', async () => { expect(STUB_TOPICS.length).toBeGreaterThan(0) + const sharedBlocks = await readSharedStubBlocks(projectDir) for (const name of STUB_TOPICS) { const source = await readFile(path.join(projectDir, 'skill-guides', `${name}.md`), 'utf8') const projection = await readFile(path.join(projectDir, 'skills', name, 'SKILL.md'), 'utf8') + const stubBody = await readFile(path.join(projectDir, 'skill-stubs', `${name}.md`), 'utf8') // The routing frontmatter is the unchanged discovery surface. expect(projection.startsWith(frontmatterBlock(source, `${name}.md`))).toBe(true) - // The stub is a thin hybrid pointer, not the full guide. + // Shared CLI resolution can be longer than a short topic's full guide. expect(projection).not.toEqual(source) - expect(projection.length).toBeLessThan(source.length) - expect(projection).toContain('discovery stub') + expect(projection).toEqual( + composeStubProjection(source, stubBody, `skill-stubs/${name}.md`, { sharedBlocks }) + ) expect(projection).toContain(`skills get ${name}`) } }) diff --git a/config/scripts/headless-detector-compiler-cache.test.mjs b/config/scripts/headless-detector-compiler-cache.test.mjs index 69d29189cd9..55bf9f03a92 100644 --- a/config/scripts/headless-detector-compiler-cache.test.mjs +++ b/config/scripts/headless-detector-compiler-cache.test.mjs @@ -195,9 +195,7 @@ it('uses exact optional restores, seeds only main and retains full dependency fa ).toBe( "steps.scope.outputs.graph_required == 'true' && steps.compiler.outputs.available != 'true'" ) - for (const event of ['push', 'pull_request']) { - expect(workflow.on[event].paths).toContain('.github/actions/prepare-headless-compiler/**') - } + expect(workflow.on.pull_request.paths).toContain('.github/actions/prepare-headless-compiler/**') const warmer = parse(readFileSync('.github/workflows/ci-cache-warmup.yml', 'utf8')) const warmSteps = warmer.jobs.warm.steps expect( diff --git a/src/main/startup/main-process-ready-identity-write.test.ts b/src/main/startup/main-process-ready-identity-write.test.ts index 8498ed39142..907b2457bb8 100644 --- a/src/main/startup/main-process-ready-identity-write.test.ts +++ b/src/main/startup/main-process-ready-identity-write.test.ts @@ -3,6 +3,7 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' import type * as DurableFileWrite from '../durable-file-write' +import { JIRA_IMAGE_SCHEME } from '../../shared/jira-attachment-image' const ORCA_PROFILE_ID = 'local-default' const RETIRED_PROFILE_ID = '11111111-1111-4111-8111-111111111111' @@ -22,6 +23,7 @@ const mocks = vi.hoisted(() => ({ store: null }, openMainWindow: vi.fn(), + handleProtocol: vi.fn(), runtimeRpcStart: vi.fn(async () => {}), // The identity record's only writer. Watching this is what makes the pin real: asserting on // writeFileAtomically watched a function the identity store never calls. @@ -42,6 +44,7 @@ vi.mock('../durable-file-write', async (importOriginal) => { }) vi.mock('electron', () => ({ + protocol: { handle: mocks.handleProtocol }, app: { on: vi.fn(), setName: vi.fn(), @@ -283,6 +286,10 @@ async function runReady(): Promise { openMainWindow: mocks.openMainWindow, handleMacAppActivation: vi.fn() }) + expect(mocks.handleProtocol).toHaveBeenCalledExactlyOnceWith( + JIRA_IMAGE_SCHEME, + expect.any(Function) + ) } function identityRecordWrites(): unknown[] { @@ -300,6 +307,7 @@ describe('ready-phase browser identity authority', () => { beforeEach(() => { vi.resetModules() mocks.openMainWindow.mockClear() + mocks.handleProtocol.mockClear() mocks.runtimeRpcStart.mockClear() mocks.writeFileDurableSync.mockClear() mocks.state.isServeMode = false diff --git a/src/renderer/src/components/NewWorkspaceComposerCard.test.tsx b/src/renderer/src/components/NewWorkspaceComposerCard.test.tsx index fa16bc7d247..feae366dbcb 100644 --- a/src/renderer/src/components/NewWorkspaceComposerCard.test.tsx +++ b/src/renderer/src/components/NewWorkspaceComposerCard.test.tsx @@ -899,7 +899,7 @@ describe('NewWorkspaceComposerCard folder task source mode', () => { expect(builderItem).toBeTruthy() act(() => builderItem?.click()) - expect(hostChanges).toEqual(['setup-builder']) + expect(hostChanges).toEqual(['["setup-builder","ssh:builder"]']) expect(recipeChanges).toEqual([null]) }) }) diff --git a/src/renderer/src/components/__mocks__/jira-issue-workspace-edit-fixture.tsx b/src/renderer/src/components/__mocks__/jira-issue-workspace-edit-fixture.tsx index 87b46bff8a3..a4ca282ba3e 100644 --- a/src/renderer/src/components/__mocks__/jira-issue-workspace-edit-fixture.tsx +++ b/src/renderer/src/components/__mocks__/jira-issue-workspace-edit-fixture.tsx @@ -98,8 +98,22 @@ export function jiraIssue(title: string, overrides: Partial = {}): Ji export const otherIssue = jiraIssue('Other issue', { id: '10002', key: 'ENG-2' }) -export let selectIssue = (_issue: JiraIssue | null): void => undefined -export let selectSource = (_source: TaskSourceContext): void => undefined +let selectIssueImplementation: ((issue: JiraIssue | null) => void) | null = null +let selectSourceImplementation: ((source: TaskSourceContext) => void) | null = null + +export function selectIssue(issue: JiraIssue | null): void { + if (!selectIssueImplementation) { + throw new Error('Render StoreBackedWorkspace before selecting an issue') + } + selectIssueImplementation(issue) +} + +export function selectSource(source: TaskSourceContext): void { + if (!selectSourceImplementation) { + throw new Error('Render StoreBackedWorkspace before selecting a source') + } + selectSourceImplementation(source) +} export const initialSource: TaskSourceContext = { kind: 'task-source', provider: 'jira', @@ -124,8 +138,12 @@ export function StoreBackedWorkspace({ initial }: { initial: JiraIssue }): React ) ) useLayoutEffect(() => { - selectIssue = setIssue - selectSource = setSource + selectIssueImplementation = setIssue + selectSourceImplementation = setSource + return () => { + selectIssueImplementation = null + selectSourceImplementation = null + } }, []) return ( diff --git a/src/shared/wsl-move/wsl-move-storage-dispositions.ts b/src/shared/wsl-move/wsl-move-storage-dispositions.ts index 49b42c217e4..d50d1535b74 100644 --- a/src/shared/wsl-move/wsl-move-storage-dispositions.ts +++ b/src/shared/wsl-move/wsl-move-storage-dispositions.ts @@ -53,6 +53,9 @@ export const LOCAL_STORAGE_MODULE_DISPOSITIONS: Record