Files
dsh-context/tests/host/fold-surface.spec.ts
T
bowenliang123 87a2893190 refactor(comments): clean up the test-suite comments to the guideline
Apply the AGENTS.md comments guideline to every .ts under tests/: remove
what the code already expresses, keep only what it cannot.

Removed: spec-header coverage inventories the describe/test tree already
names; comments restating the next line's assertion or its message; helper
JSDoc whose body already says it; within-file duplicates; five stale
claims (trendChart's "six aggregated turns" against agg.length === 8,
agentGraph's "six categories" against CATS' seven, fold-timing's "cheapest
call LAST" against a loop that feeds it first, fold-surface's unreachable
plain-JSON note, contextView's "two turns" for a one-turn fixture).

Kept and condensed: the projection-freeze class, strict wire/state-schema
hazards, retention and pricing windows, pairing rules, hostile-input
rationale, fixture and expectation-array ground truth, jsdom mechanics,
and issue-numbered regressions.

Comment lines 2604 -> 2014 (-22%); 85 module headers kept, 30 coverage
inventories dropped; every surviving comment line is within the 140-column
limit, with 36 wrapped lines joined onto fuller ones.

No logic, string, identifier, import or directive changed: a comment-strip
gate proves each file's comment-free code is byte-identical to HEAD, and a
line-level proof pairs all 845 changed lines with an unchanged code part.
pnpm run lint && pnpm run test (106 files / 2061 tests, per-file 100%
coverage) && pnpm run build all pass.
2026-10-10 00:50:55 +08:00

305 lines
14 KiB
TypeScript

// applySurface paths of the fold (src/host/fold.ts): per-category node projection, the callNames
// consume-once lifecycle, the shadow-price claim protocol, and every surfaceOp variant. No mocks: the real fold runs.
import assert from 'node:assert/strict'
import { describe, test } from 'vitest'
import type { TimelineEvent, TimelineState } from '../../src/host/fold'
import { assistantMessage, at, compaction, toolCall, toolResult, userMessage } from './helpers/events'
import { assertPlainJson, driveTimeline, timelineDef } from './helpers/projection'
const text = (t: string) => [{ type: 'text', text: t }]
describe('applySurface assistant branch', () => {
test('assistant text lands on the node preview', () => {
const { state } = driveTimeline([assistantMessage(1, { content: text('hello world') })])
assert.equal(state.surface.at(-1)?.text, 'hello world')
assert.equal(state.surface.at(-1)?.cat, 'assistant')
})
test('a text-less assistant message lists its tool-call names, capped at three', () => {
const { state } = driveTimeline([assistantMessage(1, {
content: [
{ type: 'tool-call', name: 'bash', arguments: '{}' },
{ type: 'tool-call', name: 'read', arguments: '{}' },
{ type: 'tool-call', name: 'edit', arguments: '{}' },
{ type: 'tool-call', name: 'grep', arguments: '{}' },
],
})])
const node = state.surface.at(-1)
assert.equal(node?.text, undefined)
assert.deepEqual(node?.calls, ['bash', 'read', 'edit'])
})
test('a text-less assistant message without call names carries neither preview', () => {
const { state } = driveTimeline([assistantMessage(1, { content: [{ type: 'tool-call', arguments: '{}' }] })])
const node = state.surface.at(-1)
assert.equal(node?.text, undefined)
assert.equal(node?.calls, undefined)
})
})
describe('applySurface tool/result branch', () => {
test('a source callId armed by tool/call names the node and is consumed', () => {
const { state } = driveTimeline([
toolCall(1, { callId: 'c1', name: 'bash' }),
toolResult(2, { callId: 'c1', content: text('ok') }),
])
const node = state.surface.at(-1)
assert.equal(node?.tool, 'bash')
assert.equal(node?.err, undefined, 'no error flag without the message mark')
assert.deepEqual(state.callNames, {}, 'the consumed entry leaves the persisted map')
})
test('an unknown source callId pairs nothing (a replay window where the tool/call event is gone)', () => {
const { state } = driveTimeline([toolResult(1, { callId: 'ghost', content: text('ok') })])
assert.equal(state.surface.at(-1)?.tool, undefined)
assert.deepEqual(state.callNames, {})
})
test('consume-once rebuild keeps the other pending calls', () => {
const { state } = driveTimeline([
toolCall(1, { callId: 'c1', name: 'bash' }),
toolCall(2, { callId: 'c2', name: 'read' }),
toolResult(3, { callId: 'c1', content: text('ok') }),
])
assert.equal(state.callNames.c2?.name, 'read', 'the unanswered call stays armed')
})
test('a result without the source callId pairs nothing and leaves callNames untouched', () => {
// A hostile/foreign envelope: the admission validation requires the
// source callId, so a source-less row can only arrive hostile — it folds to an unnamed node instead of throwing.
const ev: TimelineEvent = {
type: 'tool/result', seq: 2, time: at(),
data: { message: { role: 'tool', toolCallId: 'keep', content: text('ok') } },
surfaceOp: 'append',
}
const { state } = driveTimeline([toolCall(1, { callId: 'keep', name: 'read' }), ev])
assert.equal(state.surface.at(-1)?.tool, undefined)
assert.equal(state.callNames.keep?.name, 'read')
})
test('the message isError flags the node', () => {
const { state } = driveTimeline([
toolCall(1, { callId: 'c1', name: 'bash' }),
toolResult(2, { callId: 'c1', content: text('boom'), error: true }),
])
const node = state.surface.at(-1)
assert.equal(node?.err, true)
assert.equal(node?.tool, 'bash', 'the source callId still pairs the node')
})
test('the retired envelope-only error mark no longer flags the node', () => {
// The pre-V4 spelling (an event-level `data.error` with no message mark)
// is unreachable through the supported harnesses' admission validation;
// a hostile replay carrying it degrades to an unflagged node, never a throw.
const ev: TimelineEvent = {
type: 'tool/result', seq: 2, time: at(),
data: {
error: true,
message: { role: 'tool', toolCallId: 'c1', source: { kind: 'tool', callId: 'c1' }, content: text('boom') },
},
surfaceOp: 'append',
}
const { state } = driveTimeline([toolCall(1, { callId: 'c1', name: 'bash' }), ev])
const node = state.surface.at(-1)
assert.equal(node?.err, undefined)
assert.equal(node?.tool, 'bash')
})
})
describe('applySurface user-message previews', () => {
test('skill-invocation sources carry the skill name under the skill bucket', () => {
const { state } = driveTimeline([userMessage(1, text('run it'), { kind: 'skill-invocation', name: 'pdf' })])
assert.equal(state.surface.at(-1)?.skill, 'pdf')
assert.equal(state.surface.at(-1)?.cat, 'skill')
})
test('skill-catalog sources join the skill bucket', () => {
const { state } = driveTimeline([userMessage(1, text('<available_skills>'), { kind: 'skill-catalog', form: 'catalog' })])
const node = state.surface.at(-1)
assert.equal(node?.cat, 'skill')
assert.equal(node?.skill, undefined)
assert.equal(node?.form, 'catalog')
})
test('a nameless skill-invocation falls back to ?', () => {
const { state } = driveTimeline([userMessage(1, text('run it'), { kind: 'skill-invocation' })])
assert.equal(state.surface.at(-1)?.skill, '?')
})
test('plugin notice sources preview the summary', () => {
const { state } = driveTimeline([
userMessage(1, text('injected'), { kind: 'plugin', form: 'notice', plugin: 'dsh-x', summary: 'Skill injected (pdf)' }),
])
const node = state.surface.at(-1)
assert.equal(node?.text, 'Skill injected (pdf)')
assert.equal(node?.form, 'notice')
})
test('plugin snapshot sources join section names, skipping nulls, truncated to 80', () => {
const sections = [{ name: 'a'.repeat(50) }, null, { name: 'b'.repeat(50) }, {}]
const { state } = driveTimeline([
userMessage(1, text('snapshot'), { kind: 'plugin', form: 'snapshot', sections }),
])
const expected = `${'a'.repeat(50)}, ${'b'.repeat(50)}`.slice(0, 80)
assert.equal(expected.length, 80, 'fixture must actually exceed the truncation bound')
assert.equal(state.surface.at(-1)?.text, expected)
})
test('plugin sources of other forms preview the first text', () => {
const { state } = driveTimeline([
userMessage(1, text('plain body'), { kind: 'plugin', form: 'instructions' }),
])
assert.equal(state.surface.at(-1)?.text, 'plain body')
})
test('plugin sources without text carry no preview', () => {
const { state } = driveTimeline([userMessage(1, [], { kind: 'plugin', form: 'instructions' })])
assert.equal(state.surface.at(-1)?.text, undefined)
})
test('a plain user message previews its text', () => {
const { state } = driveTimeline([userMessage(1, text('hi there'))])
const node = state.surface.at(-1)
assert.equal(node?.text, 'hi there')
assert.equal(node?.cat, 'user')
assert.equal(node?.form, undefined, 'no source, no form stamp')
})
test('a plain user message without text carries no preview', () => {
const { state } = driveTimeline([userMessage(1, [])])
assert.equal(state.surface.at(-1)?.text, undefined)
})
test('image blocks ride the node as imgs', () => {
const { state } = driveTimeline([
userMessage(1, [{ type: 'image', attachment: { width: 800, height: 600 } }]),
])
assert.equal(state.surface.at(-1)?.imgs, 1)
})
})
describe('shadow-price claim lifecycle', () => {
test('the next surface event consumes and DELETES the armed claim', () => {
const { state } = driveTimeline([
compaction(1, 'summary', { shadowedTokenCount: 10, shadowedSeqs: [1] }),
userMessage(2, text('after')),
])
assert.ok(!('pendingShadowedSeqs' in state), 'consumed claims are deleted, not undefined-valued')
assert.ok(!('pendingShadowEventSeq' in state))
assertPlainJson(state)
})
})
describe('surfaceOp variants', () => {
const big = 'a'.repeat(16) // 12 tokens: ceil(16/4) + 4 block + 4 role
test('a null surfaceOp appends', () => {
const ev: TimelineEvent = { type: 'user/message', seq: 1, time: at(), data: { content: text('x') }, surfaceOp: null }
const { state } = driveTimeline([ev])
assert.equal(state.surface.length, 1)
})
test('a non-object surfaceOp appends', () => {
const { state } = driveTimeline([userMessage(1, text('x'))]) // builder default: 'append'
assert.equal(state.surface.length, 1)
})
test('a non-replace op object appends', () => {
const { state } = driveTimeline([
userMessage(1, text('x'), undefined, { surfaceOp: { op: 'insert', startSeq: 0, endSeq: 0 } }),
])
assert.equal(state.surface.length, 1)
})
test('a replace with an armed claim removes by seqs and rewrites the metering event net-freed', () => {
const { state } = driveTimeline([
userMessage(1, text(big)), // 12 tokens
userMessage(2, text(big)), // 12 tokens
userMessage(3, text(big)), // 12 tokens — NOT shadowed, survives the replace
compaction(4, 'summary', { shadowedTokenCount: 100, shadowedSeqs: [1, 2] }),
userMessage(5, text('bbbbbbbb'), undefined, { surfaceOp: { op: 'replace', startSeq: 1, endSeq: 2 } }), // 10 tokens
])
assert.deepEqual(state.surface.map(n => n.seq), [3, 5])
assert.equal(state.sums.user, 22)
assert.deepEqual(state.archived.map(n => [n.seq, n.gone]), [[1, 5], [2, 5]], 'removed nodes archived as stamped copies')
// Gross 100 rewritten to the net freed amount: 24 removed - 10 re-added.
assert.equal(state.events[0].tokens, 14)
assertPlainJson(state)
})
test('the net-freed rewrite clamps at zero when the replacement outweighs the shadow', () => {
const { state } = driveTimeline([
userMessage(1, text(big)), // 12 tokens
compaction(2, 'prune', { shadowedTokenCount: 12, shadowedSeqs: [1] }),
userMessage(3, text('x'.repeat(400)), undefined, { surfaceOp: { op: 'replace', startSeq: 1, endSeq: 1 } }), // 108 tokens
])
assert.equal(state.events[0].tokens, 0)
assert.equal(state.sums.user, 108)
})
test('an armed EMPTY claim falls through to the range path', () => {
const { state } = driveTimeline([
userMessage(1, text('aaaa')), // 9 tokens
userMessage(2, text('bbbb')), // 9 tokens
compaction(3, 'summary', { shadowedTokenCount: 50, shadowedSeqs: [] }),
userMessage(4, text('cccc'), undefined, { surfaceOp: { op: 'replace', startSeq: 1, endSeq: 2 } }),
])
assert.deepEqual(state.surface.map(n => n.seq), [4], 'range replace splices the node in place')
assert.equal(state.sums.user, 9)
assert.deepEqual(state.archived.map(n => n.seq), [1, 2])
assert.equal(state.events[0].tokens, 50, 'the range path never rewrites the metering event')
assert.ok(!('pendingShadowedSeqs' in state))
})
test('a single-node range replace (start === end)', () => {
const { state } = driveTimeline([
userMessage(1, text('aaaa')),
userMessage(2, text('bbbb')),
userMessage(3, text('cccc')),
userMessage(4, text('dddddddd'), undefined, { surfaceOp: { op: 'replace', startSeq: 2, endSeq: 2 } }),
])
assert.deepEqual(state.surface.map(n => n.seq), [1, 4, 3])
assert.deepEqual(state.archived.map(n => [n.seq, n.gone]), [[2, 4]])
})
test('a replace whose start seq is missing appends', () => {
const { state } = driveTimeline([
userMessage(1, text('aaaa')),
userMessage(2, text('bbbb'), undefined, { surfaceOp: { op: 'replace', startSeq: 99, endSeq: 100 } }),
])
assert.deepEqual(state.surface.map(n => n.seq), [1, 2])
})
test('a replace whose end seq is missing appends', () => {
const { state } = driveTimeline([
userMessage(1, text('aaaa')),
userMessage(2, text('bbbb'), undefined, { surfaceOp: { op: 'replace', startSeq: 1, endSeq: 99 } }),
])
assert.deepEqual(state.surface.map(n => n.seq), [1, 2])
})
test('restored state: claim without pendingShadowEventSeq skips the rewrite', () => {
// A checkpoint restore may carry the claim fields partially — def.apply accepts any TimelineState.
const def = timelineDef({})
const base = driveTimeline([userMessage(1, text(big))]).state
const restored: TimelineState = { ...base, pendingShadowedSeqs: [1] }
const next = def.apply(restored, userMessage(2, text('bbbb'), undefined, { surfaceOp: { op: 'replace', startSeq: 1, endSeq: 1 } }))
assert.deepEqual(next.surface.map(n => n.seq), [2])
assert.equal(next.archived.length, 1)
assert.equal(next.events.length, 0, 'no event to rewrite, no crash')
assert.ok(!('pendingShadowedSeqs' in next))
assertPlainJson(next)
})
test('restored state: a claim whose event seq matches no event skips the rewrite', () => {
const def = timelineDef({})
const base = driveTimeline([userMessage(1, text(big))]).state
const restored: TimelineState = { ...base, pendingShadowedSeqs: [1], pendingShadowEventSeq: 999 }
const next = def.apply(restored, userMessage(2, text('bbbb'), undefined, { surfaceOp: { op: 'replace', startSeq: 1, endSeq: 1 } }))
assert.deepEqual(next.surface.map(n => n.seq), [2])
assert.equal(next.events.length, 0)
assert.ok(!('pendingShadowEventSeq' in next))
})
})