fix: address review round next

- subagents.history computes its projections best-effort on both arms
  (a hostile unit's fold rejection serves the page without the block,
  matching the session-list precedent) with dual-arm coverage
- the lifecycle-witness spec probes every field of the seven-key
  witness, protecting the key list itself
- list-children's own module docs catch up with the seq-gate contract,
  and the design note records the rung-two later-event window as an
  accepted, self-healing deviation of the corruption class
This commit is contained in:
imccyu
2026-08-07 00:37:25 +08:00
parent c98a754ccb
commit 3216150ae0
7 changed files with 75 additions and 12 deletions

View File

@@ -5,9 +5,10 @@
* durable `origin: 'subagent'` under the parent; each child's mode/label is
* the registered `subagent` projection unit's value, resolved down a
* three-rung ladder: the registry's watermark cache for a live child, a
* durable projection-cache row when the optional cache already serves the
* identity, and one persistence inspection folded through the registry
* otherwise. The projection fold is the single
* durable projection-cache row when it serves an own-suffix identity (the
* seq gate), and one persistence inspection folded through the registry
* otherwise, validated against the enumerated lifecycle. The projection
* fold is the single
* classification authority — this module parses no descriptor itself. Absent
* persistence, enumeration is live-only: a cold child is unreachable for
* resume anyway, so its absence is capability absence, not an error. The
@@ -92,7 +93,7 @@ export type SubagentListEntry =
* live-preferred merge of `ctx.sessions` and optional session persistence,
* serving each identity from the `subagent` projection unit: the registry's
* watermark snapshot for a live child; for a cold one, a durable
* projection-cache row when the optional cache already serves the identity,
* projection-cache row when it serves an own-suffix identity (the seq gate),
* else one bounded-concurrency persistence inspection folded through the
* registry.
* @see SubagentService.listChildren for the public cancellation and failure contract.

View File

@@ -461,7 +461,12 @@ describe('SubagentService.listChildren', () => {
})
it.each([
['version', (meta: SessionHeader): SessionHeader => ({ ...meta, version: meta.version + 1 })],
['id', (meta: SessionHeader): SessionHeader => ({ ...meta, id: SessionId('another-lifecycle') })],
['createdAt', (meta: SessionHeader): SessionHeader => ({ ...meta, createdAt: meta.createdAt + 1 })],
['cwd', (meta: SessionHeader): SessionHeader => ({ ...meta, cwd: '/elsewhere' })],
['parentSession', (meta: SessionHeader): SessionHeader => ({ ...meta, parentSession: SessionId('another-parent') })],
['seedLength', (meta: SessionHeader): SessionHeader => ({ ...meta, seedLength: (meta.seedLength ?? 0) + 1 })],
['delegationDepth', (meta: SessionHeader): SessionHeader => ({ ...meta, delegationDepth: (meta.delegationDepth ?? 0) + 1 })],
] as const)('diagnoses an inspection returning another lifecycle (%s) as corrupt', async (_field, mutate) => {
const { ctx, parent } = await setup([textResponse('done')])