feat(context): inject CLAUDE.md / AGENTS.md as L0 standing context

On session start, discover CLAUDE.md and AGENTS.md at the bound workspace root and inject
their (concatenated, header-labeled) contents as an L0 system context entry for every stage —
mirroring the .correx/project.toml ProjectProfile path end to end. Recorded as
AgentInstructionsBoundEvent (invariant #9) so replay reads the recorded fact, not the live
file; folded into SessionState.boundAgentInstructions and rendered by buildAgentInstructionsEntry
right after the project profile. AgentInstructionsLoader reads root-only, both files if present.
Bound via ServerModule.bindAgentInstructions alongside bindProjectProfile.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 10:45:43 +00:00
parent 04d7e26482
commit c616982b7b
14 changed files with 269 additions and 1 deletions
@@ -0,0 +1,7 @@
package com.correx.core.sessions
/** Snapshot of standing agent instructions (CLAUDE.md / AGENTS.md) bound at session start. */
data class BoundAgentInstructions(
val sources: List<String>,
val content: String,
)
@@ -1,5 +1,6 @@
package com.correx.core.sessions
import com.correx.core.events.events.AgentInstructionsBoundEvent
import com.correx.core.events.events.OperatorProfileBoundEvent
import com.correx.core.events.events.ProjectProfileBoundEvent
import com.correx.core.events.events.SessionWorkspaceBoundEvent
@@ -61,6 +62,14 @@ class DefaultSessionReducer : SessionReducer {
else -> state.boundProjectProfile
}
val boundAgentInstructions = when (payload) {
is AgentInstructionsBoundEvent -> BoundAgentInstructions(
sources = payload.sources,
content = payload.content,
)
else -> state.boundAgentInstructions
}
return state.copy(
status = newStatus,
createdAt = createdAt,
@@ -68,6 +77,7 @@ class DefaultSessionReducer : SessionReducer {
boundWorkspace = boundWorkspace,
boundProfile = boundProfile,
boundProjectProfile = boundProjectProfile,
boundAgentInstructions = boundAgentInstructions,
)
}
}
@@ -10,4 +10,5 @@ data class SessionState(
val boundWorkspace: BoundWorkspace? = null,
val boundProfile: BoundProfile? = null,
val boundProjectProfile: BoundProjectProfile? = null,
val boundAgentInstructions: BoundAgentInstructions? = null,
)