Fix project instructions review findings
This commit is contained in:
@@ -526,19 +526,25 @@ function instructionDisplayPathsFromContextContent(content: readonly { type: str
|
|||||||
return paths
|
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 visibleSeqs = new Set(agent.session.surface.nodes.map(node => node.seq))
|
||||||
const visible = new Set<string>()
|
const visible = new Set<string>()
|
||||||
const logged = new Set<string>()
|
const logged = new Set<string>()
|
||||||
|
const visibleTexts = new Set<string>()
|
||||||
for (const [seq, event] of agent.session.events.entries()) {
|
for (const [seq, event] of agent.session.events.entries()) {
|
||||||
if (event.type !== 'context/message' || !isProjectInstructionContextSource(event.data.source)) continue
|
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)
|
const displayPaths = instructionDisplayPathsFromContextContent(event.data.content)
|
||||||
for (const displayPath of displayPaths) {
|
for (const displayPath of displayPaths) {
|
||||||
logged.add(displayPath)
|
logged.add(displayPath)
|
||||||
if (visibleSeqs.has(seq)) visible.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> {
|
function loadedNestedInstructionDisplayPaths(agent: Agent, pendingDisplayPaths: Set<string>): Set<string> {
|
||||||
@@ -606,9 +612,10 @@ export function apply(ctx: Context, config: Config): void {
|
|||||||
cache,
|
cache,
|
||||||
}, fileSystem)
|
}, fileSystem)
|
||||||
if (instructions === undefined) return
|
if (instructions === undefined) return
|
||||||
const visibleDisplayPaths = visibleInstructionDisplayPaths(agent).visible
|
const visibleInstructions = visibleInstructionDisplayPaths(agent)
|
||||||
const baselineDisplayPaths = instructionDisplayPathsFromText(instructions.text)
|
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 })
|
agent.inject(workspaceContextHook(instructions.text).content, { source: PLUGIN_SOURCE })
|
||||||
})
|
})
|
||||||
ctx.on('tools/post-execute', async (exec: ToolExecution, result: ToolExecutionResult, next): Promise<PostToolDecision> => {
|
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 () => {
|
it('loads instruction file content through ctx.fs instead of direct node reads', async () => {
|
||||||
const root = await tempRepo()
|
const root = await tempRepo()
|
||||||
const home = await tempRepo()
|
const home = await tempRepo()
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ const acpBin = join(repoRoot, 'packages/ui/acp-agent/lib/bin.js')
|
|||||||
const dshPackages = [
|
const dshPackages = [
|
||||||
'core/agent-core', 'core/agent', 'core/session', 'core/system-prompt',
|
'core/agent-core', 'core/agent', 'core/session', 'core/system-prompt',
|
||||||
'core/tools', 'core/agent-loop', 'llm/llm', 'llm/llm-deepseek', 'bash/bash',
|
'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',
|
||||||
'session-persistence/session-persistence-jsonl', 'ui/acp', 'ui/acp-agent',
|
'session-persistence/session-persistence-jsonl', 'ui/acp', 'ui/acp-agent', 'util/paths',
|
||||||
]
|
]
|
||||||
const vendorPackages = [
|
const vendorPackages = [
|
||||||
'cordis', 'loader', 'include', 'timer', 'hmr', 'logger-console',
|
'cordis', 'loader', 'include', 'timer', 'hmr', 'logger-console',
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ const stdioBin = join(repoRoot, 'packages/ui/stdio-agent/lib/bin.js')
|
|||||||
const dshPackages = [
|
const dshPackages = [
|
||||||
'core/agent-core', 'core/agent', 'core/session', 'core/system-prompt',
|
'core/agent-core', 'core/agent', 'core/session', 'core/system-prompt',
|
||||||
'core/tools', 'core/agent-loop', 'llm/llm', 'bash/bash', 'bash/bash-local',
|
'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',
|
||||||
'session-persistence/session-persistence-jsonl', 'ui/stdio-agent',
|
'session-persistence/session-persistence-jsonl', 'ui/stdio-agent', 'util/paths',
|
||||||
]
|
]
|
||||||
const vendorPackages = [
|
const vendorPackages = [
|
||||||
'cordis', 'loader', 'include', 'timer', 'hmr', 'logger-console',
|
'cordis', 'loader', 'include', 'timer', 'hmr', 'logger-console',
|
||||||
|
|||||||
Reference in New Issue
Block a user