@@ -177,6 +177,11 @@ import { listAllWorkspaceFiles } from '@/lib/workspace-files/application/list-wo
177177import { readWorkspaceFileContent } from '@/lib/workspace-files/application/read-workspace-file-content'
178178import { listWorkspaceFileFoldersOperation } from '@/lib/workspace-files/application/workspace-file-folders'
179179import { parseWorkspaceFileFolderDisplayPath } from '@/lib/workspace-files/folder-display-path'
180+ import {
181+ collectSimPageDiagnostics ,
182+ isSimPageSource ,
183+ SIM_PAGE_CONTENT_TYPE ,
184+ } from '@/lib/workspace-files/page-compile'
180185import { getWorkspaceHostContextForViewer } from '@/lib/workspaces/host-context'
181186import {
182187 assertActiveWorkspaceAccess ,
@@ -1549,7 +1554,12 @@ export class WorkspaceVFS {
15491554 const e2bFmt = isDocSandboxEnabled ? await getE2BDocFormat ( record . name ) : null
15501555 const taskId = BINARY_DOC_TASKS [ ext ]
15511556 const isMermaidFile = ext === 'mmd' || ext === 'mermaid'
1552- if ( ! e2bFmt && ! taskId && ! isMermaidFile ) return null
1557+ // Sim pages (and legacy .html-named page source) compile-check too:
1558+ // this is the only way an agent can retrieve the "block skipped"
1559+ // diagnostics for an ALREADY-written page — without it, "find the
1560+ // malformed table" degenerates into guessing.
1561+ const maybeSimPage = record . type === SIM_PAGE_CONTENT_TYPE || ext === 'html'
1562+ if ( ! e2bFmt && ! taskId && ! isMermaidFile && ! maybeSimPage ) return null
15531563 const { content : buffer } = await readWorkspaceFileContent . execute ( {
15541564 principal : this . requireFilePrincipal ( ) ,
15551565 input : {
@@ -1565,6 +1575,37 @@ export class WorkspaceVFS {
15651575 totalLines : 1 ,
15661576 } )
15671577 }
1578+ if ( maybeSimPage && isSimPageSource ( code ) ) {
1579+ const diagnostics = collectSimPageDiagnostics ( code )
1580+ const result =
1581+ diagnostics . length === 0
1582+ ? { ok : true }
1583+ : {
1584+ ok : false ,
1585+ error : `${ diagnostics . length } block(s) fail to compile and are omitted from the rendered page: ${ diagnostics . join ( '; ' ) } ` ,
1586+ }
1587+ return bindWorkspaceFileResult ( record , {
1588+ content : JSON . stringify ( result ) ,
1589+ totalLines : 1 ,
1590+ } )
1591+ }
1592+ if ( maybeSimPage && ! e2bFmt && ! taskId && ! isMermaidFile ) {
1593+ if ( record . type === SIM_PAGE_CONTENT_TYPE ) {
1594+ // A page-typed file whose bytes are not page source (e.g. a crash
1595+ // between upload registration and source restore) — report it
1596+ // rather than pretending the path does not exist.
1597+ return bindWorkspaceFileResult ( record , {
1598+ content : JSON . stringify ( {
1599+ ok : false ,
1600+ error :
1601+ 'Stored content is not page source (no YAML frontmatter with a title) — the file renders as raw HTML' ,
1602+ } ) ,
1603+ totalLines : 1 ,
1604+ } )
1605+ }
1606+ // Bespoke raw HTML has no compiler to check.
1607+ return null
1608+ }
15681609 if ( isMermaidFile ) {
15691610 const result = await validateMermaidSource ( code )
15701611 const json = JSON . stringify ( result )
0 commit comments