Carry proposal exchanges into repair replay

This commit is contained in:
2026-11-11 04:18:05 +00:00
parent eb45d0b623
commit 00848203d7
10 changed files with 267 additions and 41 deletions

View File

@@ -62,6 +62,7 @@ type Request struct {
Variables map[string]string `json:"variables"`
StageName string `json:"stage_name,omitempty"`
StartIndex int `json:"start_index"`
CaptureExchange bool
LLMClient contracts.StructuredLLMClient
DiagnosticsDir string
DiagnosticsWriter InteractionDiagnosticsWriter
@@ -69,6 +70,7 @@ type Request struct {
// Result contains generated candidate proposals and optional diagnostics paths.
type Result struct {
Exchange *structuredoutput.Exchange `json:"-"`
Corrections []proposals.CorrectionProposal `json:"corrections"`
Enriched []proposals.EnrichedCorrectionProposal `json:"enriched"`
Operations []outcomes.Operation `json:"operations,omitempty"`
@@ -106,8 +108,9 @@ func GenerateCandidates(ctx context.Context, req Request) (Result, error) {
artifacts InteractionArtifacts
)
completion, callErr = req.LLMClient.CompleteStructured(ctx, contracts.StructuredCompletionRequest{
PromptID: req.PromptID,
Variables: req.Variables, Schema: responseschema.CorrectionSetKey,
CaptureExchange: req.CaptureExchange,
PromptID: req.PromptID,
Variables: req.Variables, Schema: responseschema.CorrectionSetKey,
Context: structuredoutput.DiagnosticContext{StageIndex: req.StageIndex, StageID: req.StageID, Role: "proposal", ModuleKey: req.ModuleKey, ModuleInstance: req.ModuleInstance, SectionIndex: sectionIndexPtr(req.Section)},
}, &response)
sectionIndex := 0
@@ -216,6 +219,7 @@ func GenerateCandidates(ctx context.Context, req Request) (Result, error) {
return Result{
Corrections: corrections,
Exchange: completion.Exchange,
Enriched: enriched,
Operations: []outcomes.Operation{operation},
Artifacts: artifacts,

View File

@@ -63,6 +63,7 @@ func ExecuteModuleProposal(ctx context.Context, req ModuleProposalRequest) (cont
Variables: variables,
StageName: stagename.ModuleProposal(req.ProposalRequest.RunSpec.InstanceName, sectionIndexPtr(req.ProposalRequest.Section)),
StartIndex: 0,
CaptureExchange: req.ProposalRequest.RunSpec.CaptureProposalExchange,
LLMClient: req.ProposalRequest.LLMClient,
DiagnosticsDir: req.ProposalRequest.DiagnosticsDir,
ReportDiagnosticError: req.ProposalRequest.ReportDiagnosticError,
@@ -73,6 +74,7 @@ func ExecuteModuleProposal(ctx context.Context, req ModuleProposalRequest) (cont
return contracts.ProposalResult{
Proposals: generated.Corrections,
Exchange: generated.Exchange,
Operations: generated.Operations,
}, nil
}

View File

@@ -18,7 +18,9 @@ import (
)
func TestExecuteModuleProposalBuildsMessagesFromSectionAndDescription(t *testing.T) {
exchange := &structuredoutput.Exchange{PromptID: "captured", FinalContent: "response"}
client := &fakeStructuredClient{
completion: structuredoutput.Response{Exchange: exchange},
responses: []StructuredCorrectionSet{
{Corrections: []StructuredCorrectionProposal{{SegmentReference: 1, OriginalText: "teh", CorrectedText: "the", Confidence: 0.9}}},
},
@@ -39,9 +41,10 @@ func TestExecuteModuleProposalBuildsMessagesFromSectionAndDescription(t *testing
Section: &section,
},
RunSpec: contracts.ModuleRunSpec{
ModuleKey: "grammar",
InstanceName: "grammar",
ReplacementPolicy: proposals.ReplacementPolicyRequireUnique,
CaptureProposalExchange: true,
ModuleKey: "grammar",
InstanceName: "grammar",
ReplacementPolicy: proposals.ReplacementPolicyRequireUnique,
},
LLMClient: client,
},
@@ -53,6 +56,9 @@ func TestExecuteModuleProposalBuildsMessagesFromSectionAndDescription(t *testing
if len(client.calls) != 1 || client.calls[0].PromptID != prompts.PromptIDModuleGrammarProposal || client.calls[0].Context.SectionIndex == nil || *client.calls[0].Context.SectionIndex != 7 {
t.Fatalf("unexpected stage name calls: %+v", client.calls)
}
if !client.calls[0].CaptureExchange || out.Exchange != exchange {
t.Fatalf("exchange was not passed through: %+v", out.Exchange)
}
variables := client.calls[0].Variables
if !strings.Contains(variables["SectionJSON"], `"section_index": 7`) ||
!strings.Contains(variables["SectionJSON"], "teh") ||