Files
deepseek-harness/packages/experimental/webworker-runtime/tests/vfs-example-fixture.ts
T
ZiyaandMagolor 341ea6eea4 feat(schedule): integrate standalone tasks with the existing WebUI (#6189)
* feat(schedule): manage Host tasks with typed timing and delivery targets

* fix(schedule): align task creation button halves

* refactor(schedule): remove obsolete Session reminder runtime

* refactor(schedule): simplify task UI and preserve keyboard navigation

* fix(schedule): address task delivery and interface review findings

* test(schedule): normalize bundle module paths on Windows

* fix(schedule): cover reserved targets and trim unrelated changes

* refactor(schedule): minimize task management changes after rebase

* test(schedule): align rebased fixtures and documentation records

* test(schedule): refresh SDK scenarios added on master

---------

Co-authored-by: Magolor <[email protected]>
2026-10-29 18:11:48 +08:00

758 lines
29 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** Deterministic source for the filesystem tree bundled into the WebWorker preview. */
import { fileURLToPath } from 'node:url'
import {
SESSION_FORMAT_VERSION,
SessionId,
SessionLogOffset,
SessionSeq,
type SessionEvent,
type SessionHeader,
type SessionLogOffset as SessionLogOffsetType,
type SessionSeq as SessionSeqType,
} from '@deepseek-ai/dsh-session'
import {
eventLines, generationLogFilename, projectKey, toHeaderLine,
} from '@deepseek-ai/dsh-session-persistence-jsonl/src/format.ts'
import { projectionCacheDomainSpec } from '@deepseek-ai/dsh-session-projection-cache'
import { scheduleDomain } from '@deepseek-ai/dsh-schedule'
import { snapshotSubagentDescriptor, SUBAGENT_DESCRIPTOR_VERSION } from '@deepseek-ai/dsh-subagent'
import { SUBAGENT_CATALOG_VERSION } from '@deepseek-ai/dsh-subagent/src/catalog.ts'
/** Root copied by the preview image's repository adapter. */
export const VFS_EXAMPLE_ROOT = fileURLToPath(new URL('./fixtures/vfs-example', import.meta.url))
/** Durable ids used by browser assertions and subagent parent links. */
export const VFS_EXAMPLE_SESSION_IDS = {
main: SessionId('preview-showcase'),
oneShot: SessionId('preview-architecture-review'),
continuable: SessionId('preview-follow-up-builder'),
spacing: SessionId('preview-turn-spacing'),
} as const
/** Stable title rendered in the root Session list. */
export const VFS_EXAMPLE_TITLE = 'WebWorker Preview Showcase'
/** Title of the multi-Turn spacing sample in the root Session list. */
export const VFS_EXAMPLE_SPACING_TITLE = 'Turn spacing sample'
/** Oldest prompt, intentionally outside the first 50-message history page. */
export const VFS_EXAMPLE_OLDEST_MESSAGE = 'History checkpoint 01: verify deterministic preview state.'
/** Settled tail marker used by browser acceptance and the demonstration GIF. */
export const VFS_EXAMPLE_TAIL_MESSAGE = 'Preview tour complete'
/** Non-empty reasoning bodies surrounded by empty and whitespace-only fixture blocks. */
export const VFS_EXAMPLE_REASONING = [
'I will inspect the deterministic workspace and collect each preview surface.',
'Check the Chat presentation\n\nI will inspect the wrapped command, its first-line status, and the parent-path file link.',
] as const
/** Authored long command and a second line for wrapping and status-dot acceptance. */
export const VFS_EXAMPLE_WRAPPED_COMMAND = `printf 'preview command fixture\\n' # ${'wrapped-argument-'.repeat(28)}\nprintf 'wrap complete\\n'\n`
/** Durable task ids for the Host Schedule rows seeded into the preview's `DSH_HOME`. */
export const VFS_EXAMPLE_SCHEDULE_IDS = {
daily: 'preview-daily-digest',
once: 'preview-release-window',
} as const
const WORKSPACE = '/dsh/workspace'
const CREATED_AT = 1_787_472_000_000
const HISTORICAL_TURNS = 28
const PREVIEW_GUIDE = `# Preview Workspace
This deterministic workspace is bundled with the browser-only preview.
- \`src/preview.ts\` is the file changed by the example write result.
- \`data/tasks.json\` mirrors the completed preview checklist.
- \`.agents/skills/preview-tour/SKILL.md\` proves dot directories survive image packing.
Refresh the preview to restore these image bytes.
`
const PREVIEW_SOURCE_BEFORE = 'export const previewStatus = \'draft\'\n'
const PREVIEW_SOURCE = `export const previewStatus = 'ready'
export const previewFeatures = ['tools', 'subagents', 'pagination'] as const
`
const TASKS = `${JSON.stringify({
title: 'Preview verification',
tasks: [
{ name: 'Inspect tool cards', status: 'completed' },
{ name: 'Open both subagents', status: 'completed' },
{ name: 'Load earlier history', status: 'completed' },
],
}, null, 2)}\n`
const SKILL = `---
name: preview-tour
description: Inspect the bundled Preview workspace and its deterministic Session examples.
---
# Preview tour
Read the workspace files, inspect the tool gallery, open both subagent histories, and load the earlier conversation page.
`
interface EventDraft {
readonly type: string
readonly data: unknown
readonly surfaceOp?: 'append'
readonly ignorable?: true
}
class EventLog {
readonly events: SessionEvent[]
private nextTime: number
constructor(time: number, seed: readonly SessionEvent[] = []) {
this.events = seed.map(event => structuredClone(event))
this.nextTime = Math.max(time, (this.events.at(-1)?.time ?? time - 1) + 1)
}
add(draft: EventDraft): SessionSeqType {
const seq = SessionSeq(this.events.length)
this.events.push({ ...draft, seq, time: this.nextTime++ } as unknown as SessionEvent)
return seq
}
}
function userMessage(id: string, text: string): EventDraft {
return {
type: 'user/message',
data: {
id,
role: 'user',
content: [{ type: 'text', text }],
source: { kind: 'user' },
},
surfaceOp: 'append',
}
}
function assistantStream(content: readonly unknown[]): unknown[] {
const stream: unknown[] = []
let toolCalls = false
for (const [index, value] of content.entries()) {
const block = value as Record<string, unknown>
stream.push({ type: 'chunk', time: 0, chunk: { type: 'block-start', index, blockType: block.type } })
if (block.type === 'text') {
stream.push({ type: 'text-chunks', time0: 0, index, dt: [], texts: [block.text] })
} else if (block.type === 'reasoning') {
stream.push({ type: 'reasoning-chunks', time0: 0, index, dt: [], texts: [block.text] })
} else if (block.type === 'tool-call') {
toolCalls = true
stream.push({
type: 'tool-call-chunks',
time0: 0,
index,
dt: [],
id: block.id,
name: block.name,
args: [block.arguments],
})
}
stream.push({ type: 'chunk', time: 0, chunk: { type: 'block-end', index, block } })
}
stream.push({
type: 'chunk',
time: 0,
chunk: { type: 'finish', reason: { kind: toolCalls ? 'tool-calls' : 'stop' } },
})
return stream
}
function assistantMessage(id: string, turn: number, step: number, content: unknown[]): EventDraft {
return {
type: 'assistant/message',
data: {
turn,
step,
message: {
id,
role: 'assistant',
content,
source: { kind: 'model', provider: 'preview-fixture', model: 'deterministic' },
},
stream: assistantStream(content),
},
surfaceOp: 'append',
}
}
interface GalleryCall {
readonly id: string
readonly name: string
readonly args: Record<string, unknown>
readonly result: string
readonly meta?: unknown
readonly error?: { readonly name: string; readonly code: string }
readonly todos?: Array<{ readonly content: string; readonly status: 'pending' | 'in_progress' | 'completed' }>
}
function readResult(): { text: string; meta: unknown } {
const lines = PREVIEW_GUIDE.trimEnd().split('\n').map((text, index) => ({ number: index + 1, text }))
return {
text: `<path>PREVIEW.md</path>\n<type>file</type>\n<content>\n${lines.map(line => `${String(line.number)}: ${line.text}`).join('\n')}\n\n(End of file - total ${String(lines.length)} lines)\n</content>`,
meta: { path: 'PREVIEW.md', offset: 1, lines, totalLines: lines.length, lang: 'md' },
}
}
/** Render the workspace task file the way a `read` result shows it. */
function tasksReadResult(): string {
const lines = TASKS.trimEnd().split('\n')
return `<path>data/tasks.json</path>\n<type>file</type>\n<content>\n${lines.map((text, index) => `${String(index + 1)}: ${text}`).join('\n')}\n\n(End of file - total ${String(lines.length)} lines)\n</content>`
}
function galleryCalls(): GalleryCall[] {
const read = readResult()
return [
{
id: 'preview-read',
name: 'read',
args: { file_path: 'PREVIEW.md' },
result: read.text,
meta: read.meta,
},
{
id: 'preview-write',
name: 'write',
args: { file_path: 'src/preview.ts', content: PREVIEW_SOURCE },
result: '<path>src/preview.ts</path>\n<type>file</type>\n<content>\nUpdated file\n</content>',
meta: { diffs: [{ path: 'src/preview.ts', oldText: PREVIEW_SOURCE_BEFORE, newText: PREVIEW_SOURCE }] },
},
{
id: 'preview-bash',
name: 'bash',
args: { command: "printf 'preview ready\\n'", description: 'Print the preview readiness marker' },
result: 'preview ready\n',
},
{
id: 'preview-wrapped-bash',
name: 'bash',
args: { command: VFS_EXAMPLE_WRAPPED_COMMAND, description: 'Show wrapped command and first-line status' },
result: 'preview command fixture\nwrap complete\n[exit code: 0]',
},
{
id: 'preview-glob',
name: 'glob',
args: { pattern: '**/*', path: '.' },
result: 'PREVIEW.md\ndata/tasks.json\nsrc/preview.ts',
meta: {
shape: 'paths',
paths: ['PREVIEW.md', 'data/tasks.json', 'src/preview.ts'],
truncated: false,
total: 3,
},
},
{
id: 'preview-grep',
name: 'grep',
args: { pattern: 'preview', path: '.', include: '*.{md,ts,json}' },
result: 'PREVIEW.md:3:This deterministic workspace is bundled with the browser-only preview.\nsrc/preview.ts:1:export const previewStatus = \'ready\'',
meta: {
shape: 'matches',
files: [
{ path: 'PREVIEW.md', matches: [{ lineNumber: 3, line: 'This deterministic workspace is bundled with the browser-only preview.' }] },
{ path: 'src/preview.ts', matches: [{ lineNumber: 1, line: "export const previewStatus = 'ready'" }] },
],
truncated: false,
total: 2,
},
},
{
id: 'preview-web-search',
name: 'web_search',
args: { queries: ['Web Worker filesystem compatibility'] },
result: 'Browser workers can host deterministic in-memory filesystems.\n\nSources:\n1. MDN Web Workers API — https://developer.mozilla.org/docs/Web/API/Web_Workers_API',
meta: {
sources: [{
url: 'https://developer.mozilla.org/docs/Web/API/Web_Workers_API',
title: 'Web Workers API',
snippet: 'Web Workers run scripts in background threads.',
}],
truncated: false,
answer: 'Browser workers can host deterministic in-memory filesystems.',
},
},
{
id: 'preview-todo',
name: 'todo_write',
args: {
todos: [
{ content: 'Inspect tool cards', status: 'completed' },
{ content: 'Open both subagents', status: 'completed' },
{ content: 'Load earlier history', status: 'in_progress' },
],
},
result: 'Updated todo list: 0 pending, 1 in progress, 2 completed.',
todos: [
{ content: 'Inspect tool cards', status: 'completed' },
{ content: 'Open both subagents', status: 'completed' },
{ content: 'Load earlier history', status: 'in_progress' },
],
},
{
id: 'preview-subagent',
name: 'subagent',
args: { description: 'Continue preview verification', prompt: 'Check the remaining preview cases.', run_in_background: true },
result: `started subagent ${VFS_EXAMPLE_SESSION_IDS.continuable}`,
},
{
id: 'preview-subagent-fork',
name: 'subagent_fork',
args: { description: 'Review preview architecture', prompt: 'Review the fixture architecture.', run_in_background: false },
result: 'The preview fixture remains separate from user-owned WebFS data.',
},
{
id: 'preview-failure',
name: 'read',
args: { file_path: 'missing.txt' },
result: 'Error: ENOENT: no such file, open missing.txt',
error: { name: 'FsError', code: 'ENOENT' },
},
]
}
function addClosedTextTurn(log: EventLog, turn: number): void {
const checkpoint = String(turn).padStart(2, '0')
log.add({ type: 'turn/start', data: { turn } })
log.add(userMessage(`preview-user-${checkpoint}`, `History checkpoint ${checkpoint}: verify deterministic preview state.`))
if (turn === 1) {
log.add({
type: 'session/title',
data: { title: VFS_EXAMPLE_TITLE, messageSeqs: [], source: { kind: 'user' } },
})
}
log.add({ type: 'step/start', data: { turn, step: 1 } })
log.add(assistantMessage(
`preview-assistant-${checkpoint}`,
turn,
1,
[{ type: 'text', text: `Checkpoint ${checkpoint} is recorded.` }],
))
log.add({ type: 'step/end', data: { turn, step: 1 } })
log.add({ type: 'turn/end', data: { turn, reason: { kind: 'completed' } } })
}
function mainLog(): {
readonly events: SessionEvent[]
readonly forkSeedLength: SessionLogOffsetType
} {
const log = new EventLog(CREATED_AT)
for (let turn = 1; turn <= HISTORICAL_TURNS; turn++) addClosedTextTurn(log, turn)
const forkSeedLength = SessionLogOffset(log.events.length)
const turn = HISTORICAL_TURNS + 1
const calls = galleryCalls()
log.add({ type: 'turn/start', data: { turn } })
log.add(userMessage('preview-gallery-user', 'Show the seeded workspace, tool cards, subagents, and pagination in one tour.'))
log.add({ type: 'step/start', data: { turn, step: 1 } })
log.add(assistantMessage('preview-gallery-tools', turn, 1, [
...['', ' \t\n', VFS_EXAMPLE_REASONING[0], '', VFS_EXAMPLE_REASONING[1], '\n ']
.map(text => ({ type: 'reasoning', text })),
...calls.map(call => ({ type: 'tool-call', id: call.id, name: call.name, arguments: JSON.stringify(call.args) })),
]))
for (const call of calls) {
log.add({
type: 'tool/call',
data: { turn, step: 1, callId: call.id, name: call.name, arguments: JSON.stringify(call.args) },
})
if (call.todos !== undefined) log.add({ type: 'todo/write', data: { todos: call.todos } })
log.add({
type: 'tool/result',
data: {
turn,
step: 1,
message: {
id: `${call.id}-result`,
role: 'tool',
toolCallId: call.id,
source: { kind: 'tool', callId: call.id },
content: [{ type: 'text', text: call.result }],
isError: call.error !== undefined,
},
...call.meta === undefined ? {} : { meta: call.meta },
...call.error === undefined ? {} : { error: call.error },
},
surfaceOp: 'append',
})
}
for (const child of [
{ childId: VFS_EXAMPLE_SESSION_IDS.oneShot, childCreatedAt: CREATED_AT + 100_000, mode: 'one-shot', label: 'Review preview architecture' },
{ childId: VFS_EXAMPLE_SESSION_IDS.continuable, childCreatedAt: CREATED_AT + 200_000, mode: 'continuable', label: 'Continue preview verification' },
] as const) {
log.add({ type: 'subagent/catalog', data: { version: SUBAGENT_CATALOG_VERSION, ...child } })
}
log.add({ type: 'step/end', data: { turn, step: 1 } })
log.add({ type: 'step/start', data: { turn, step: 2 } })
log.add(assistantMessage('preview-gallery-final', turn, 2, [{
type: 'text',
text: `## ${VFS_EXAMPLE_TAIL_MESSAGE}\n\nThe workspace, specialized tool cards, two subagent histories, and an earlier history page are ready to inspect.\n\nThis is fixture-authored demonstration data, not a live model run. Open [Parent workspace guide:1–8](<../workspace/PREVIEW.md#L1-L8>) to inspect the same workspace file through a parent path.`,
}]))
log.add({ type: 'step/end', data: { turn, step: 2 } })
log.add({ type: 'turn/end', data: { turn, reason: { kind: 'completed' } } })
return { events: log.events, forkSeedLength }
}
function oneShotLog(seed: readonly SessionEvent[]): SessionEvent[] {
const log = new EventLog(CREATED_AT + 100_000, seed)
log.add({ type: 'session/end-seed', data: { inherited: true } })
const turn = HISTORICAL_TURNS + 1
log.add({ type: 'turn/start', data: { turn } })
log.add(userMessage('preview-review-user', 'Review whether the preview fixture is isolated from future WebFS data.'))
log.add({
type: 'subagent/descriptor',
data: {
version: SUBAGENT_DESCRIPTOR_VERSION,
mode: 'one-shot', provider: 'fork', label: 'Review preview architecture',
},
})
log.add({ type: 'step/start', data: { turn, step: 1 } })
log.add(assistantMessage('preview-review-assistant', turn, 1, [{
type: 'text',
text: 'The bundled fixture is static image content; future WebFS state remains user-owned.',
}]))
log.add({ type: 'step/end', data: { turn, step: 1 } })
log.add({ type: 'turn/end', data: { turn, reason: { kind: 'completed' } } })
return log.events
}
function continuableLog(): SessionEvent[] {
const log = new EventLog(CREATED_AT + 200_000)
log.add({ type: 'turn/start', data: { turn: 1 } })
log.add(userMessage('preview-builder-user', 'Check that the Preview workspace can support follow-up tasks.'))
log.add({
type: 'subagent/descriptor',
data: snapshotSubagentDescriptor({
mode: 'continuable', provider: 'spawn', label: 'Continue preview verification',
}),
})
log.add({ type: 'step/start', data: { turn: 1, step: 1 } })
log.add(assistantMessage('preview-builder-assistant', 1, 1, [{
type: 'text',
text: 'This child is continuable and ready for another verification turn.',
}]))
log.add({ type: 'step/end', data: { turn: 1, step: 1 } })
log.add({ type: 'turn/end', data: { turn: 1, reason: { kind: 'completed' } } })
return log.events
}
/** One step of the multi-Turn spacing sample: reasoning, tool calls, or a closing body. */
interface SpacingStep {
/** Assistant message id. */
readonly id: string
/** Reasoning text shown in the step's Think row. */
readonly reasoning?: string
/** Tool calls issued in this step, each with its recorded result. */
readonly calls?: readonly GalleryCall[]
/** Closing Markdown body for a step without tool calls. */
readonly body?: string
}
function addSpacingTurn(
log: EventLog,
turn: number,
prompt: { readonly id: string; readonly text: string },
steps: readonly SpacingStep[],
): void {
log.add({ type: 'turn/start', data: { turn } })
log.add(userMessage(prompt.id, prompt.text))
if (turn === 1) {
log.add({
type: 'session/title',
data: { title: VFS_EXAMPLE_SPACING_TITLE, messageSeqs: [], source: { kind: 'user' } },
})
}
for (const [index, step] of steps.entries()) {
const stepNumber = index + 1
log.add({ type: 'step/start', data: { turn, step: stepNumber } })
const content: unknown[] = []
if (step.reasoning !== undefined) content.push({ type: 'reasoning', text: step.reasoning })
for (const call of step.calls ?? []) {
content.push({ type: 'tool-call', id: call.id, name: call.name, arguments: JSON.stringify(call.args) })
}
if (step.body !== undefined) content.push({ type: 'text', text: step.body })
log.add(assistantMessage(step.id, turn, stepNumber, content))
for (const call of step.calls ?? []) {
log.add({
type: 'tool/call',
data: { turn, step: stepNumber, callId: call.id, name: call.name, arguments: JSON.stringify(call.args) },
})
log.add({
type: 'tool/result',
data: {
turn,
step: stepNumber,
message: {
id: `${call.id}-result`,
role: 'tool',
toolCallId: call.id,
source: { kind: 'tool', callId: call.id },
content: [{ type: 'text', text: call.result }],
isError: false,
},
},
surfaceOp: 'append',
})
}
log.add({ type: 'step/end', data: { turn, step: stepNumber } })
}
log.add({ type: 'turn/end', data: { turn, reason: { kind: 'completed' } } })
}
/**
* Three Turns with multi-step processes and multi-paragraph bodies, so the
* preview shows the tightened process-row gap beside the reply clearance.
*/
function spacingLog(): SessionEvent[] {
const log = new EventLog(CREATED_AT + 300_000)
addSpacingTurn(log, 1, {
id: 'preview-spacing-user-1',
text: 'Show how multiple Turns and their process steps sit on the tightened spacing.',
}, [
{
id: 'preview-spacing-1-tools',
reasoning: 'Read the workspace guide, then list the files this sample references.',
calls: [
{ id: 'preview-spacing-read', name: 'read', args: { file_path: 'PREVIEW.md' }, result: readResult().text },
{
id: 'preview-spacing-glob', name: 'glob', args: { pattern: '**/*', path: '.' },
result: 'PREVIEW.md\ndata/tasks.json\nsrc/preview.ts',
},
],
},
{
id: 'preview-spacing-1-command',
reasoning: 'Confirm the sample command result before writing the body.',
calls: [{
id: 'preview-spacing-bash', name: 'bash',
args: { command: "printf 'spacing sample 1\\n'", description: 'Print the first spacing sample marker' },
result: 'spacing sample 1\n',
}],
},
{
id: 'preview-spacing-1-body',
body: '## Turn 1 — setup\n\nThis Turn has three steps: two process steps and one closing body. Inside an expanded group the process rows use the tightened gap, while this body keeps the reply clearance from the rows above.\n\nExpand the Turn control above to compare the tightened process rhythm with the reply rhythm.',
},
])
addSpacingTurn(log, 2, {
id: 'preview-spacing-user-2',
text: 'Continue the sample with a second body and a shorter process.',
}, [
{
id: 'preview-spacing-2-tools',
reasoning: 'Search the sample workspace for the spacing note.',
calls: [{
id: 'preview-spacing-grep', name: 'grep',
args: { pattern: 'preview', path: '.', include: '*.{md,ts,json}' },
result: 'PREVIEW.md:3:This deterministic workspace is bundled with the browser-only preview.\nsrc/preview.ts:1:export const previewStatus = \'ready\'',
}],
},
{
id: 'preview-spacing-2-body',
body: '## Turn 2 — follow-up\n\nA shorter Turn still separates its process group from this body by the reply clearance, so consecutive Turns stay readable.\n\nThe gap between the previous Turn and this user message is the ordinary flow gap.',
},
])
addSpacingTurn(log, 3, {
id: 'preview-spacing-user-3',
text: 'Finish the sample with one more multi-step Turn.',
}, [
{
id: 'preview-spacing-3-tools',
reasoning: 'Read the task list and print the final sample marker.',
calls: [
{
id: 'preview-spacing-tasks', name: 'read', args: { file_path: 'data/tasks.json' },
result: tasksReadResult(),
},
{
id: 'preview-spacing-final-bash', name: 'bash',
args: { command: "printf 'spacing sample complete\\n'", description: 'Print the final spacing sample marker' },
result: 'spacing sample complete\n',
},
],
},
{
id: 'preview-spacing-3-body',
body: '## Turn 3 — closing\n\nThe last Turn has a two-step shape: one process step and one closing body.\n\nSpacing sample complete: compare these process rows with the reply clearance around each Turn body.',
},
])
return log.events
}
function header(
id: SessionHeader['id'],
createdAt: number,
child?: {
readonly parentSession: SessionHeader['id']
readonly mode: 'one-shot' | 'continuable'
readonly seedLength?: SessionLogOffsetType
},
): { readonly meta: SessionHeader; readonly inheritedEventCount: SessionLogOffsetType } {
const inheritedEventCount = child?.seedLength ?? SessionLogOffset(0)
return {
meta: {
version: SESSION_FORMAT_VERSION,
id,
createdAt,
cwd: WORKSPACE,
isSeeded: child?.seedLength !== undefined,
delegationDepth: child === undefined ? 0 : 1,
agentPreset: 'standard',
...child === undefined ? {} : {
parentSession: child.parentSession,
origin: 'subagent' as const,
},
},
inheritedEventCount,
}
}
function renderLog(
storage: { readonly meta: SessionHeader; readonly inheritedEventCount: SessionLogOffsetType },
events: readonly SessionEvent[],
): string {
return `${JSON.stringify(toHeaderLine(storage.meta, storage.inheritedEventCount))}\n${eventLines(events)}\n`
}
/**
* Host Schedule task rows the preview's `DSH_HOME` carries, keyed by durable
* task id.
*
* The schedule domain opens these per-record documents at Host startup and
* rejects the complete domain on any malformed row, so the fixture spec decodes
* every stored task through the production schema. Targets sit in 2099:
* the Session row mark, the header clock entry, and the tasks page render them
* as scheduled, while the timer clamp (`MAX_TIMER_DELAY_MS`) keeps a preview
* session from dispatching them. The daily row carries a saved delivery so the
* detail's records tab renders retained content.
* @returns Task rows for the schedule domain's `tasks` table.
*/
function scheduleTasks(): Readonly<Record<string, unknown>> {
const sessionId = VFS_EXAMPLE_SESSION_IDS.main
const dailyPrompt = 'Summarize the preview workspace changes and their verification status.'
const dailyReceipt = {
scheduledAt: '2098-12-31T01:00:00.000Z',
deliveredAt: '2098-12-31T01:00:01.000Z',
messageId: 'preview-daily-digest-receipt',
targetSessionId: sessionId,
}
const common = {
target: { kind: 'session', sessionId },
involvedSessionIds: [sessionId],
status: 'active',
createdAt: new Date(CREATED_AT).toISOString(),
updatedAt: new Date(CREATED_AT).toISOString(),
}
return {
[VFS_EXAMPLE_SCHEDULE_IDS.daily]: {
...common,
record: {
kind: 'rrule',
id: VFS_EXAMPLE_SCHEDULE_IDS.daily,
title: 'Daily preview digest',
prompt: dailyPrompt,
rrule: 'DTSTART;TZID=Asia/Shanghai:20990101T090000\nRRULE:FREQ=DAILY',
scheduledAt: '2099-01-01T01:00:00.000Z',
},
deliveryHistory: {
earlierRecordsUnavailable: false,
earlierRecordsPruned: false,
records: [{ ...dailyReceipt, prompt: dailyPrompt }],
},
lastDelivery: dailyReceipt,
},
[VFS_EXAMPLE_SCHEDULE_IDS.once]: {
...common,
record: {
kind: 'rrule',
id: VFS_EXAMPLE_SCHEDULE_IDS.once,
title: 'Preview release window',
prompt: 'Remind the preview owner that the release window opens.',
rrule: 'DTSTART:20990102T000000Z\nRRULE:FREQ=DAILY;COUNT=1',
scheduledAt: '2099-01-02T00:00:00.000Z',
},
deliveryHistory: { records: [], earlierRecordsUnavailable: false, earlierRecordsPruned: false },
},
}
}
/** Build current-generation fixture files as fixture-relative UTF-8 text; committed predecessors remain untouched. */
export function buildVfsExampleFiles(): ReadonlyMap<string, string> {
const main = mainLog()
const spacing = spacingLog()
const project = projectKey(WORKSPACE)
const sessionPath = (id: string): string =>
`home/sessions/${project}/${id}/${generationLogFilename(SESSION_FORMAT_VERSION, 'none')}`
const scheduleFile = `home/storages/${scheduleDomain.name}.json`
const projectionCache = `${JSON.stringify({
unit: { name: 'session_projcache', version: projectionCacheDomainSpec.version },
global: null,
tables: {
sessions: {
[VFS_EXAMPLE_SESSION_IDS.main]: {
identity: {
formatVersion: SESSION_FORMAT_VERSION,
createdAt: CREATED_AT,
cwd: WORKSPACE,
isSeeded: false,
inheritedEventCount: 0,
},
rows: {
title: { ver: 1, seq: main.events.at(-1)?.seq ?? -1, val: VFS_EXAMPLE_TITLE },
},
},
[VFS_EXAMPLE_SESSION_IDS.spacing]: {
identity: {
formatVersion: SESSION_FORMAT_VERSION,
createdAt: CREATED_AT + 300_000,
cwd: WORKSPACE,
isSeeded: false,
inheritedEventCount: 0,
},
rows: {
title: { ver: 1, seq: spacing.at(-1)?.seq ?? -1, val: VFS_EXAMPLE_SPACING_TITLE },
},
},
},
},
}, null, 2)}\n`
return new Map([
['workspace/PREVIEW.md', PREVIEW_GUIDE],
['workspace/src/preview.ts', PREVIEW_SOURCE],
['workspace/data/tasks.json', TASKS],
['workspace/.agents/skills/preview-tour/SKILL.md', SKILL],
['home/storages/session_projcache.json', projectionCache],
[sessionPath(VFS_EXAMPLE_SESSION_IDS.main), renderLog(
header(VFS_EXAMPLE_SESSION_IDS.main, CREATED_AT),
main.events,
)],
[sessionPath(VFS_EXAMPLE_SESSION_IDS.spacing), renderLog(
header(VFS_EXAMPLE_SESSION_IDS.spacing, CREATED_AT + 300_000),
spacing,
)],
[sessionPath(VFS_EXAMPLE_SESSION_IDS.oneShot), renderLog(
header(VFS_EXAMPLE_SESSION_IDS.oneShot, CREATED_AT + 100_000, {
parentSession: VFS_EXAMPLE_SESSION_IDS.main,
mode: 'one-shot',
seedLength: main.forkSeedLength,
}),
oneShotLog(main.events.slice(0, main.forkSeedLength)),
)],
[sessionPath(VFS_EXAMPLE_SESSION_IDS.continuable), renderLog(
header(VFS_EXAMPLE_SESSION_IDS.continuable, CREATED_AT + 200_000, {
parentSession: VFS_EXAMPLE_SESSION_IDS.main,
mode: 'continuable',
}),
continuableLog(),
)],
[scheduleFile, `${JSON.stringify({ unit: { name: scheduleDomain.name, version: scheduleDomain.version },
global: null, tables: { tasks: scheduleTasks() } }, null, 2)}\n`],
])
}