feat(context): render retry repair mandate as final user turn (#293)
buildRetryFeedbackEntry was L1/SYSTEM, so PromptRenderer folded it into the leading system block — far from the assistant/tool transcript and weaker than the original stage task. Flip it to USER role and give the renderer an explicit trailing repair-mandate slot (a sourceType set, extensible for recovery later): repair mandates are lifted out of the inline flow and emitted once as the final message, after the tool evidence and the steering anchor. retryFeedback is already in REQUIRED_SOURCE_TYPES so it stays unprunable. Golden renderer test proves the final message is the repair USER mandate and leading system no longer carries it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -50,7 +50,7 @@ class ContextFeedbackTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `latest retry event for the stage becomes a labeled L1 system entry`() {
|
||||
fun `latest retry event for the stage becomes a labeled L1 user repair mandate`() {
|
||||
val events = listOf(
|
||||
stored(payload = RetryAttemptedEvent(SessionId("s"), StageId("impl"), 1, 3, "old reason")),
|
||||
stored(payload = RetryAttemptedEvent(SessionId("s"), StageId("other"), 1, 3, "other stage")),
|
||||
@@ -59,7 +59,8 @@ class ContextFeedbackTest {
|
||||
val entry = buildRetryFeedbackEntry(events, StageId("impl"))!!
|
||||
assertEquals("retryFeedback", entry.sourceType)
|
||||
assertEquals(ContextLayer.L1, entry.layer)
|
||||
assertEquals(EntryRole.SYSTEM, entry.role)
|
||||
// #293: USER role so it renders as the trailing repair mandate, not folded into leading system.
|
||||
assertEquals(EntryRole.USER, entry.role)
|
||||
assertTrue(entry.content.contains("Attempt 2 of 3"), "content: ${entry.content}")
|
||||
assertTrue(entry.content.contains("tests failed: NPE in FooTest"), "content: ${entry.content}")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user