fix(native-chat): refresh invalid full work projections

Use the existing SQL authority and context validation before preserving a
full projection, so refreshed narrow work can be reused after row-free
invalidation. Preserve a valid full projection arriving during a narrow
read and extend the existing owner scenario for both transitions.

Correct the description in b98a2544bf: the report698 strict misses are
small measured overhead, not proven noise. Empty warm currentWork p50 is
3.542 to 3.709 us (+0.167 us, 60/80 pairs slower, ratio 1.04715, 95% CI
1.02291-1.07259). Empty/2-subscriber/changed writer ack p50 rises 5.5%,
0.259459 to 0.273833 ms, with its CI excluding parity, on an unchanged
writer path; completion falls 1.546834 to 0.657125 ms. The coordinator
accepts these marginal costs; the strict FAILs remain disclosed.

Frozen714 patch 6a4ded1ee72e8c0134a9a2121fb39bde618213e3f740b4888fd13c8900274620.
Owning 53 tests pass on both configured entries; static gates pass. Private
point attribution verifies repeated narrow reuse and all 92 serving/frame
outputs match. Focused714 against pre-P7 base still measures a small warm
currentWork median overhead; report716 preserves raw samples and CIs.
This commit is contained in:
Brennan Benson
2026-11-12 10:39:43 -08:00
parent a281079585
commit 12d479e640
2 changed files with 29 additions and 2 deletions
@@ -141,7 +141,7 @@ export class StructuredAgentSessionJournalProjections {
) {
continue
}
if (this.currentEntry(journal)?.kind !== 'full') {
if (!this.currentSql(journal, recaptured)) {
this.byJournal.set(journal, {
kind: 'work-only',
answer: result,
@@ -122,6 +122,7 @@ it('discards row-free authority changes before publishing an asynchronous observ
const journal = await openJournal()
const projections = new StructuredAgentSessionJournalProjections()
let revision = 0
let contextId: string | null = null
let attached = true
const held: string[] = []
const capture = () => {
@@ -144,7 +145,7 @@ it('discards row-free authority changes before publishing an asynchronous observ
stopRevision: 0,
stop: null
}
return { authority, contextId: null }
return { authority, contextId }
}
const narrow = await projections.readWorkSql(journal, capture)
expect(narrow?.result.kind).toBe('state')
@@ -206,9 +207,18 @@ it('discards row-free authority changes before publishing an asynchronous observ
expect(projections.savedStop(journal, null)).toEqual({ value: null })
held.push('later-owner')
expect(current?.authority?.child?.heldSends).toEqual(['new-live-owner'])
const refreshedWork = await projections.readWorkSql(journal, capture)
expect(await projections.readWorkSql(journal, capture)).toEqual(refreshedWork)
expect(projections.savedStop(journal, null)).toBeUndefined()
expect(await projections.readSql(journal, capture, () => {})).toMatchObject({
authority: { child: { heldSends: ['later-owner', 'new-live-owner'] } }
})
contextId = 'reopened-context'
const contextWork = await projections.readWorkSql(journal, capture)
expect(await projections.readWorkSql(journal, capture)).toEqual(contextWork)
expect(projections.currentSql(journal, capture())).toBeNull()
expect(projections.savedStop(journal, contextId)).toBeUndefined()
await projections.readSql(journal, capture, () => {})
revision = 2
const failed = Promise.withResolvers<Awaited<ReturnType<typeof read>>>()
const failure = new Error('observer read failed')
@@ -223,4 +233,21 @@ it('discards row-free authority changes before publishing an asynchronous observ
{ status: 'rejected', reason: failure }
])
expect(await projections.readSql(journal, capture, () => {})).toMatchObject({ workRevision: 2 })
revision = 3
const workEntered = Promise.withResolvers<void>()
const workRelease = Promise.withResolvers<void>()
const workRead = journal.reads.work.bind(journal.reads)
vi.spyOn(journal.reads, 'work').mockImplementationOnce(async (input) => {
const answer = await workRead(input)
workEntered.resolve()
await workRelease.promise
return answer
})
const pendingWork = projections.readWorkSql(journal, capture)
await workEntered.promise
const published = await projections.readSql(journal, capture, () => {})
workRelease.resolve()
await pendingWork
expect(projections.currentSql(journal, capture())).toBe(published)
expect(projections.savedStop(journal, contextId)).toEqual({ value: null })
})