diff --git a/.github/workflows/skillsync.yml b/.github/workflows/skillsync.yml index 83b7908..c22c060 100644 --- a/.github/workflows/skillsync.yml +++ b/.github/workflows/skillsync.yml @@ -10,6 +10,7 @@ on: - ".claude/skills/**" - ".cursor/skills/**" - "src/**" + - "browser/**" - "desktop/**" - "scripts/**" - "tests/**" @@ -55,6 +56,7 @@ jobs: - run: npm test - run: npm test -- --run tests/integration/product-trust-loop.test.ts tests/integration/live-runtime-preparation.test.ts tests/docs/documentation.test.ts - run: npm run type-check + - run: npm run build:browser - run: npm run lint - run: npm pack --dry-run - name: Generate SBOM preview (non-blocking) diff --git a/browser/main.ts b/browser/main.ts index 0113c82..e914ba8 100644 --- a/browser/main.ts +++ b/browser/main.ts @@ -54,4 +54,9 @@ function check() { input.value = example; input.addEventListener("input",clear); document.querySelector("#check")!.addEventListener("click",check); -document.querySelector("#example")!.addEventListener("click",()=>{input.value=example;clear();input.focus()}); +document.querySelector("#example")!.addEventListener("click", () => { + if (input.value.trim() && input.value !== example && !window.confirm("用示例替换当前文档?")) return; + input.value = example; + clear(); + input.focus(); +}); diff --git a/browser/tsconfig.json b/browser/tsconfig.json new file mode 100644 index 0000000..13a8347 --- /dev/null +++ b/browser/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "rootDir": "..", + "lib": ["ES2022", "DOM"], + "types": [], + "module": "ESNext", + "moduleResolution": "Bundler", + "noEmit": true + }, + "include": ["main.ts"] +} diff --git a/package.json b/package.json index 3394369..2ee9488 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "check": "npm test && npm run type-check && npm run lint && npm run build", "prepack": "npm run build", "pretest": "npm run build", - "build:browser": "vite build browser --base ./ --outDir ../browser-dist --emptyOutDir" + "build:browser": "tsc -p browser/tsconfig.json && vite build browser --base ./ --outDir ../browser-dist --emptyOutDir" }, "dependencies": { "commander": "^13.1.0", diff --git a/tests/cli/test.test.ts b/tests/cli/test.test.ts index cda3f1c..2f0e706 100644 --- a/tests/cli/test.test.ts +++ b/tests/cli/test.test.ts @@ -2,7 +2,8 @@ import { mkdir, mkdtemp, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { describe, expect, it } from "vitest"; +import { describe, expect, it, vi } from "vitest"; +import { SpawnCommandRunner } from "../../src/sandbox/command"; import { runCli } from "../../src/cli/index"; import { publicAvailabilityFinding } from "../../src/cli/commands/test-v2"; @@ -320,20 +321,30 @@ describe("skillsync test", () => { it("blocks Docker explicitly without fallback", async () => { const root = await mkdtemp(join(tmpdir(), "skillsync-behavior-v2-docker-")); const fixtureRoot = await createV2Fixture(root, "docker"); - const result = await runCli([ - "test", - "--fixture", - fixtureRoot, - "--execute", - "--backend", - "docker", - "--format", - "json", - ]); - - expect(result.exitCode).toBe(4); - expect(result.stdout).toMatch(/sandbox\.backend-unavailable/); - expect(JSON.parse(result.stdout).execution.status).toBe("blocked"); + const hostCommand = vi.spyOn(SpawnCommandRunner.prototype, "run").mockResolvedValue({ + exitCode: null, stdout: "", stderr: "", timedOut: true, outputLimitExceeded: false, + }); + try { + const result = await runCli([ + "test", + "--fixture", + fixtureRoot, + "--execute", + "--backend", + "docker", + "--format", + "json", + ]); + + expect(result.exitCode).toBe(4); + expect(result.stdout).toMatch(/sandbox\.backend-unavailable/); + expect(JSON.parse(result.stdout).execution.status).toBe("blocked"); + expect(hostCommand.mock.calls.map(([spec]) => [spec.executable, ...spec.args])).toEqual([ + ["docker", "version", "--format", "{{.Server.Version}}"], + ]); + } finally { + hostCommand.mockRestore(); + } }); it("returns code 2 for an invalid v2 manifest", async () => {