-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathplan-adjust.ts
More file actions
50 lines (42 loc) · 3 KB
/
Copy pathplan-adjust.ts
File metadata and controls
50 lines (42 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { tool } from '@opencode-ai/plugin'
import type { ToolContext } from './types'
import { MAX_TOTAL_SECTIONS } from '../constants/loop'
const z = tool.schema
const nonBlankString = z.string().refine((value) => value.trim().length > 0, { error: 'must not be blank or whitespace-only' })
export function createPlanAdjustTool(ctx: ToolContext): ReturnType<typeof tool> {
const loop = ctx.loop
return tool({
description: 'Adjust the active loop plan during a section audit; unavailable in the final audit. Only callable by the loop auditor. Revises the executable section instructions — the section currently being audited (currentSection) and/or the pending suffix (sections). The stored master plan row is unchanged, so the master objective and top-level Verification remain authoritative. Amendments are logged; the tool does not semantically validate the adjusted instructions.',
args: {
sections: z.array(z.object({
title: nonBlankString,
content: nonBlankString,
})).min(0).max(MAX_TOTAL_SECTIONS).optional().describe(`Replacement list for the pending sections after the current one (from current index + 1 onwards). This replaces the entire pending suffix — omissions delete milestones, so include every later milestone you intend to retain. Omit to leave future sections unchanged; pass an empty array to remove the entire pending suffix. The resulting total (completed + current + replacements) may not exceed ${MAX_TOTAL_SECTIONS} sections.`),
currentSection: z.object({
title: nonBlankString,
content: nonBlankString,
}).optional().describe('Revised plan for the section currently under audit, edited in place (its progress is preserved). If the revision requires code, write severity: bug findings in the same audit so it is re-coded. Revisions must not weaken acceptance criteria or verification merely to obtain a clean audit.'),
rationale: z.string().min(1).describe('Why the plan needs adjustment. Revisions must not weaken acceptance criteria or verification merely to obtain a clean audit.'),
},
execute: async (args, toolCtx) => {
const sessionId = toolCtx?.sessionID ?? ''
const loopName = loop.service.resolveLoopName(sessionId)
if (!loopName) {
return JSON.stringify({ error: 'Not in a loop session. This tool can only be used within an active loop session.' })
}
// Guards (loop exists, active, auditing phase, session authorization,
// section cap) are enforced authoritatively inside adjustRemainingSections
// under its write lock; the tool only resolves the loop and surfaces errors.
const result = await loop.service.adjustRemainingSections(loopName, {
sections: args.sections,
currentSection: args.currentSection,
rationale: args.rationale,
auditorSessionId: sessionId,
})
if (!result.ok) {
return JSON.stringify({ error: result.error })
}
return JSON.stringify({ ok: true, total_sections: result.totalSections })
},
})
}