Skip to content

Commit e4fa282

Browse files
GiniGini
authored andcommitted
feat: validate OneComputer sandbox artifacts
1 parent ebc62b3 commit e4fa282

3 files changed

Lines changed: 11 additions & 1 deletion

File tree

‎docs/MANUS-PARITY.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ This is the implementation gate, not a marketing checklist. **I** means behavior
116116

117117
## Validation, delivery, and reuse
118118

119-
91. **P** Production-build validation and portability — ONEVibe ZIPs source and writes a versioned per-task static contract report. Generated React/Vite projects now validate their portable dependency/scripts contract and output semantics, but are not yet dependency-installed or built in an attested sandbox.
119+
91. **P** Production-build validation and portability — ONEVibe ZIPs source and writes a versioned per-task static contract report. Native Claude SDK and ONEComputer sandbox runs now both emit that bounded report after workspace delivery; generated React/Vite projects validate their portable dependency/scripts contract and output semantics, but are not yet dependency-installed or built in an attested sandbox.
120120
92. **P** Accessibility-validation step — static preview semantics plus generated Website landmarks, native FAQ disclosure, compact layout, reduced-motion, and keyboard-focus affordances are checked. Automated accessibility scans remain pending.
121121
93. **P** Live-preview delivery and agent browser validation — isolated local preview works, and an attested sandbox may surface server-proxied X11 PNG frames. For Website, App, and Game outputs, a gateway-enforced browser runtime now additionally renders `file://` `index.html` inside the sandbox into a preserved artifact-rail screenshot with hostname resolution blocked. Allowlisted agent browser activity remains separately recorded; managed HTTPS and a deployed microVM proof remain pending.
122122
94. **P** Publish control — external approval is required and publication is withheld; approved deployment is pending.

‎server/onecomputer-sandbox-runner.test.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ describe('OneComputerSandboxRuntimeAdapter', () => {
108108
expect(commands.some((command) => command.includes('onevibe-browser-review.png'))).toBe(true)
109109
expect(store.listEvents(task.id).some((event) => event.label === 'Sandbox browser review observed' && event.payload.generatedArtifactPreview === true)).toBe(true)
110110
expect(frames.at(-1)?.payload.uri).toContain(`/api/tasks/${task.id}/file?path=evidence%2Fvisual%2Fbrowser-review-`)
111+
expect(store.listEvents(task.id).some((event) => event.label === 'Static artifact contract needs review' && event.content === 'validation-report.json')).toBe(true)
112+
expect(await store.readWorkspaceFile(task.id, 'validation-report.json')).toContain('Static contract validation only')
111113
expect(store.listEvents(task.id).at(-1)?.type).toBe('run_completed')
112114
expect(store.verifyChain(task.id)).toBe(true)
113115
})

‎server/onecomputer-sandbox-runner.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createHash } from 'node:crypto'
22
import path from 'node:path'
33
import type { OneComputerClient } from './onecomputer-client.js'
44
import type { RuntimeAdapter, RuntimeContext } from './runtime-adapter.js'
5+
import { validateModeArtifacts } from './artifact-validation.js'
56

67
const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])
78
const isPng = (bytes: Buffer) => bytes.byteLength >= PNG_SIGNATURE.byteLength && bytes.subarray(0, PNG_SIGNATURE.byteLength).equals(PNG_SIGNATURE)
@@ -434,6 +435,13 @@ export class OneComputerSandboxRuntimeAdapter implements RuntimeAdapter {
434435
})
435436
}
436437
await store.setPlanStep(task.id, 'build', 'completed')
438+
await store.setPlanStep(task.id, 'verify', 'running')
439+
const validation = await validateModeArtifacts(store.getTask(task.id), store)
440+
await store.appendEvent(task.id, {
441+
type: 'artifact_created', lane: 'artifact', label: validation.passed ? 'Static artifact contract passed' : 'Static artifact contract needs review',
442+
content: 'validation-report.json',
443+
payload: { executionRoute: 'onecomputer_sandbox', kind: 'validation_report', passed: validation.passed, checkCount: validation.checks.length, limitation: validation.limitation },
444+
})
437445
await store.setPlanStep(task.id, 'verify', 'completed')
438446
await store.setPlanStep(task.id, 'deliver', 'running')
439447
await destroy()

0 commit comments

Comments
 (0)