Revert "fix: resolve remaining review findings — explicit turnBoundary dependency and uniform missing-key handling"

This reverts commit 3a664c73e131d073025c5c3041e3f4a3cebb3889.
This commit is contained in:
_Kerman committed 2026-08-19 18:01:11 +08:00
1 parent 5ef3f0bd94
commit 842f42d7ea
6 files changed
+5 -28

No files matched your search

@@ -188,7 +188,6 @@ function visibleInstructionChanges(
const visibleSeqs = new Set(agent.session.surface.nodes)
const visible = new Map<string, AgentInstructionChange>()
const folded = agent.ctx.get('sessionProjections')?.stateOf(agent.session, 'workspaceInstructions')
/* v8 ignore next -- agent-instructions registers its own workspaceInstructions unit, so the key is always present */
if (folded === undefined) throw new Error('workspaceInstructions projection is not registered')
for (const [scope, history] of Object.entries(folded)) {
// History is newest-first; the latest visible record restores the previous
+3 -3
View File
@@ -188,14 +188,14 @@ export function apply(ctx: Context, config: Config): void {
if (decision.kind === 'reject' || signal.aborted) return decision
const now = Date.now()
const state = ctx.sessionProjections.stateOf(agent.session, 'timeContext')
/* v8 ignore next -- time-context registers its own unit in apply, so the key is always present */
if (state === undefined) throw new Error('timeContext projection is not registered')
if (refreshIntervalMs !== undefined && refreshIntervalMs > 0) {
if (state !== undefined && refreshIntervalMs !== undefined && refreshIntervalMs > 0) {
const lastInjection = state.lastInjectionTime
if (lastInjection != null
&& now >= lastInjection
&& now - lastInjection < refreshIntervalMs) return decision
}
/* v8 ignore next 2 -- time-context registers its own unit in apply, so the key is always present */
if (state === undefined) return decision
/* v8 ignore next 6 -- an injection always records a time, so the lastInjectionTime nullish fallback is unreachable */
const previous = step === 1
? state.lastMessageTime ?? undefined
@@ -38,7 +38,6 @@
"license": "MIT",
"peerDependencies": {
"@deepseek-ai/dsh-agent": "workspace:^",
"@deepseek-ai/dsh-agent-loop": "workspace:^",
"@deepseek-ai/dsh-brand": "workspace:^",
"@deepseek-ai/dsh-invariants": "workspace:^",
"@deepseek-ai/dsh-llm": "workspace:^",
@@ -282,14 +282,7 @@ export class ApprovalService extends Service {
*/
async request(req: ApprovalRequest): Promise<ApprovalOutcome> {
const session = req.agent.session
const boundary = this.ctx.sessionProjections.stateOf(session, 'turnBoundary')
if (boundary === undefined) {
throw new Error(
'approval.request() requires the turnBoundary projection, which @deepseek-ai/dsh-agent-loop '
+ 'registers; mount the agent loop next to the projection registry',
)
}
if (boundary.openTurn === null) {
if ((this.ctx.sessionProjections.stateOf(session, 'turnBoundary')?.openTurn ?? null) === null) {
throw new Error(
'approval.request() outside an open turn: the approval/asked + approval/decided audit pair '
+ 'must be turn-enclosed (a bare event between turns is crash-tail garbage on reload). '
@@ -59,18 +59,6 @@ describe('ApprovalService.request', () => {
expect(appended).toHaveLength(0)
})
it('names the missing agent loop when no turnBoundary unit is registered, even with turn events logged', async () => {
const ctx = new Context()
await ctx.plugin(SessionProjectionRegistry)
await ctx.plugin(ApprovalService)
const { agent, appended } = fakeAgent([
{ type: 'turn/start', seq: 0, data: { turn: 1 } },
])
await expect(ctx.approval.request(requestOf(agent))).rejects.toThrow(/requires the turnBoundary projection/)
expect(appended).toHaveLength(0)
})
it('throws between turns — a closed turn does not satisfy the enclosure precondition', async () => {
const ctx = await mounted()
const { agent, appended } = fakeAgent([
+1 -3
View File
@@ -712,10 +712,8 @@ export class SessionTitleService extends Service {
}
private titleInputOf(session: Session): TitleInputState {
const state = this.ctx.sessionProjections.stateOf(session, 'titleInput')
/* v8 ignore next -- session-title registers its own titleInput unit, so the key is always present */
if (state === undefined) throw new Error('titleInput projection is not registered')
return state
return this.ctx.sessionProjections.stateOf(session, 'titleInput') ?? EMPTY_TITLE_INPUT
}
/** Queue detached service work and retain it through service disposal. */