Fix project instructions review findings
This commit is contained in:
@@ -526,19 +526,25 @@ function instructionDisplayPathsFromContextContent(content: readonly { type: str
|
||||
return paths
|
||||
}
|
||||
|
||||
function visibleInstructionDisplayPaths(agent: Agent): { visible: Set<string>; logged: Set<string> } {
|
||||
function visibleInstructionDisplayPaths(agent: Agent): { visible: Set<string>; logged: Set<string>; visibleTexts: Set<string> } {
|
||||
const visibleSeqs = new Set(agent.session.surface.nodes.map(node => node.seq))
|
||||
const visible = new Set<string>()
|
||||
const logged = new Set<string>()
|
||||
const visibleTexts = new Set<string>()
|
||||
for (const [seq, event] of agent.session.events.entries()) {
|
||||
if (event.type !== 'context/message' || !isProjectInstructionContextSource(event.data.source)) continue
|
||||
if (visibleSeqs.has(seq)) {
|
||||
for (const block of event.data.content) {
|
||||
if (block.type === 'text') visibleTexts.add(block.text)
|
||||
}
|
||||
}
|
||||
const displayPaths = instructionDisplayPathsFromContextContent(event.data.content)
|
||||
for (const displayPath of displayPaths) {
|
||||
logged.add(displayPath)
|
||||
if (visibleSeqs.has(seq)) visible.add(displayPath)
|
||||
}
|
||||
}
|
||||
return { visible, logged }
|
||||
return { visible, logged, visibleTexts }
|
||||
}
|
||||
|
||||
function loadedNestedInstructionDisplayPaths(agent: Agent, pendingDisplayPaths: Set<string>): Set<string> {
|
||||
@@ -606,9 +612,10 @@ export function apply(ctx: Context, config: Config): void {
|
||||
cache,
|
||||
}, fileSystem)
|
||||
if (instructions === undefined) return
|
||||
const visibleDisplayPaths = visibleInstructionDisplayPaths(agent).visible
|
||||
const visibleInstructions = visibleInstructionDisplayPaths(agent)
|
||||
const baselineDisplayPaths = instructionDisplayPathsFromText(instructions.text)
|
||||
if (baselineDisplayPaths.length > 0 && baselineDisplayPaths.every(path => visibleDisplayPaths.has(path))) return
|
||||
if (baselineDisplayPaths.length > 0 && baselineDisplayPaths.every(path => visibleInstructions.visible.has(path))) return
|
||||
if (baselineDisplayPaths.length === 0 && visibleInstructions.visibleTexts.has(instructions.text)) return
|
||||
agent.inject(workspaceContextHook(instructions.text).content, { source: PLUGIN_SOURCE })
|
||||
})
|
||||
ctx.on('tools/post-execute', async (exec: ToolExecution, result: ToolExecutionResult, next): Promise<PostToolDecision> => {
|
||||
|
||||
@@ -719,6 +719,29 @@ describe('project instruction request injection', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('does not duplicate markerless baseline workspace context on later pre-step checks', async () => {
|
||||
const root = await tempRepo()
|
||||
const home = await tempRepo()
|
||||
try {
|
||||
await mkdir(join(root, '.git'), { recursive: true })
|
||||
await write(join(root, 'AGENTS.md'), 'repo rule')
|
||||
const ctx = new Context()
|
||||
await mountProjectInstructions(ctx, { dshHome: home, baselineMaxBytes: 10 })
|
||||
const agent = stubAgent(root)
|
||||
|
||||
await runBaselinePreStep(ctx, agent)
|
||||
await runBaselinePreStep(ctx, agent)
|
||||
|
||||
const messages = agent.session.events.filter(event => event.type === 'context/message')
|
||||
expect(messages).toHaveLength(1)
|
||||
expect(blocksText(messages[0]?.type === 'context/message' ? messages[0].data.content : undefined))
|
||||
.not.toContain('project-instruction-files:path=')
|
||||
} finally {
|
||||
await rm(root, { recursive: true, force: true })
|
||||
await rm(home, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
it('loads instruction file content through ctx.fs instead of direct node reads', async () => {
|
||||
const root = await tempRepo()
|
||||
const home = await tempRepo()
|
||||
|
||||
@@ -40,9 +40,9 @@ const acpBin = join(repoRoot, 'packages/ui/acp-agent/lib/bin.js')
|
||||
const dshPackages = [
|
||||
'core/agent-core', 'core/agent', 'core/session', 'core/system-prompt',
|
||||
'core/tools', 'core/agent-loop', 'llm/llm', 'llm/llm-deepseek', 'bash/bash',
|
||||
'bash/bash-local', 'bash/tool-bash', 'support/invariants', 'ui/app-boot',
|
||||
'bash/bash-local', 'bash/tool-bash', 'prompt/project-instructions', 'support/invariants', 'ui/app-boot',
|
||||
'session-persistence/session-persistence',
|
||||
'session-persistence/session-persistence-jsonl', 'ui/acp', 'ui/acp-agent',
|
||||
'session-persistence/session-persistence-jsonl', 'ui/acp', 'ui/acp-agent', 'util/paths',
|
||||
]
|
||||
const vendorPackages = [
|
||||
'cordis', 'loader', 'include', 'timer', 'hmr', 'logger-console',
|
||||
|
||||
@@ -35,9 +35,9 @@ const stdioBin = join(repoRoot, 'packages/ui/stdio-agent/lib/bin.js')
|
||||
const dshPackages = [
|
||||
'core/agent-core', 'core/agent', 'core/session', 'core/system-prompt',
|
||||
'core/tools', 'core/agent-loop', 'llm/llm', 'bash/bash', 'bash/bash-local',
|
||||
'bash/tool-bash', 'support/invariants', 'ui/app-boot',
|
||||
'bash/tool-bash', 'prompt/project-instructions', 'support/invariants', 'ui/app-boot',
|
||||
'session-persistence/session-persistence',
|
||||
'session-persistence/session-persistence-jsonl', 'ui/stdio-agent',
|
||||
'session-persistence/session-persistence-jsonl', 'ui/stdio-agent', 'util/paths',
|
||||
]
|
||||
const vendorPackages = [
|
||||
'cordis', 'loader', 'include', 'timer', 'hmr', 'logger-console',
|
||||
|
||||
Reference in New Issue
Block a user