Complete Phase 8 deterministic validators
This commit is contained in:
@@ -361,7 +361,7 @@ func runProcess(args []string, stdout, stderr io.Writer) int {
|
||||
hasSkippedCorrections := false
|
||||
if runOutput != nil {
|
||||
for _, mr := range runOutput.ModuleResults {
|
||||
if len(mr.SkippedChanges) > 0 {
|
||||
if len(mr.SkippedChanges) > 0 || len(mr.ValidatorRejected) > 0 {
|
||||
hasSkippedCorrections = true
|
||||
break
|
||||
}
|
||||
@@ -395,7 +395,7 @@ func extractErrorPhase(err error) (phase string, message string) {
|
||||
|
||||
func buildProcessReport(status string, inv processInvocation, runDir *diagnostics.RunDirectory, startedAt, completedAt time.Time, errorMessage string, errorPhase string, normalizationSummary *normalization.NormalizationSummary, chunkingSummary *chunking.Summary, runOutput *runner.RunOutput) reporting.ProcessReport {
|
||||
report := reporting.ProcessReport{
|
||||
Phase: "phase7-runner",
|
||||
Phase: "phase8-validators",
|
||||
Status: status,
|
||||
Operation: "process",
|
||||
TranscriptPath: inv.TranscriptPath,
|
||||
@@ -461,19 +461,21 @@ func buildModuleReporting(runOutput *runner.RunOutput) (*reporting.ModulesSummar
|
||||
startedAt := r.StartedAt
|
||||
completedAt := r.CompletedAt
|
||||
moduleReports = append(moduleReports, reporting.ModuleReport{
|
||||
ModuleKey: r.ModuleKey,
|
||||
ModuleInstance: r.ModuleInstance,
|
||||
ReplacementPolicy: string(r.ReplacementPolicy),
|
||||
Status: r.Status,
|
||||
ProposalCount: r.ProposalCount,
|
||||
AppliedChanges: r.AppliedChanges,
|
||||
SkippedChanges: r.SkippedChanges,
|
||||
ErrorMessage: r.ErrorMessage,
|
||||
StartedAt: &startedAt,
|
||||
CompletedAt: &completedAt,
|
||||
ModuleKey: r.ModuleKey,
|
||||
ModuleInstance: r.ModuleInstance,
|
||||
ReplacementPolicy: string(r.ReplacementPolicy),
|
||||
Status: r.Status,
|
||||
ProposalCount: r.ProposalCount,
|
||||
ValidatorDecisions: mapValidatorDecisions(r.ValidatorDecisions),
|
||||
ValidatorRejected: mapValidatorRejected(r.ValidatorRejected),
|
||||
AppliedChanges: r.AppliedChanges,
|
||||
SkippedChanges: r.SkippedChanges,
|
||||
ErrorMessage: r.ErrorMessage,
|
||||
StartedAt: &startedAt,
|
||||
CompletedAt: &completedAt,
|
||||
})
|
||||
summary.TotalAppliedChanges += len(r.AppliedChanges)
|
||||
summary.TotalSkippedChanges += len(r.SkippedChanges)
|
||||
summary.TotalSkippedChanges += len(r.SkippedChanges) + len(r.ValidatorRejected)
|
||||
if r.Status == runner.ModuleStatusFailed && summary.FailedModuleInstance == "" {
|
||||
summary.FailedModuleInstance = r.ModuleInstance
|
||||
}
|
||||
@@ -482,6 +484,44 @@ func buildModuleReporting(runOutput *runner.RunOutput) (*reporting.ModulesSummar
|
||||
return summary, moduleReports
|
||||
}
|
||||
|
||||
func mapValidatorDecisions(in []runner.ValidatorDecisionRecord) []reporting.ValidatorDecisionReport {
|
||||
if len(in) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := make([]reporting.ValidatorDecisionReport, len(in))
|
||||
for i, d := range in {
|
||||
out[i] = reporting.ValidatorDecisionReport{
|
||||
ValidatorName: d.ValidatorName,
|
||||
ProposalIndex: d.ProposalIndex,
|
||||
Approved: d.Approved,
|
||||
ReasonCode: d.ReasonCode,
|
||||
Message: d.Message,
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func mapValidatorRejected(in []runner.ValidatorRejectedChange) []reporting.ValidatorRejectedReport {
|
||||
if len(in) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := make([]reporting.ValidatorRejectedReport, len(in))
|
||||
for i, d := range in {
|
||||
out[i] = reporting.ValidatorRejectedReport{
|
||||
ValidatorName: d.ValidatorName,
|
||||
ProposalIndex: d.ProposalIndex,
|
||||
ModuleKey: d.ModuleKey,
|
||||
ModuleInstance: d.ModuleInstance,
|
||||
TargetSegmentID: d.TargetSegmentID,
|
||||
OriginalText: d.OriginalText,
|
||||
CorrectedText: d.CorrectedText,
|
||||
ReasonCode: d.ReasonCode,
|
||||
Message: d.Message,
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
type processFlags struct {
|
||||
glossaryPath *string
|
||||
outputPath *string
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"gitea.maximumdirect.net/eric/audita/internal/core/schema"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/contracts"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/proposals"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/validators"
|
||||
)
|
||||
|
||||
func TestRunRootHelp(t *testing.T) {
|
||||
@@ -613,8 +614,8 @@ func TestRunProcessReportJSONIncludesChunkingSummary(t *testing.T) {
|
||||
if report.Chunking.MaxSectionTokens == 0 {
|
||||
t.Errorf("expected max_section_tokens in report")
|
||||
}
|
||||
if report.Phase != "phase7-runner" {
|
||||
t.Errorf("expected phase 'phase7-runner', got %q", report.Phase)
|
||||
if report.Phase != "phase8-validators" {
|
||||
t.Errorf("expected phase 'phase8-validators', got %q", report.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,14 +632,15 @@ func (f fakeModuleFactory) ModuleForSpec(spec contracts.ModuleRunSpec) (contract
|
||||
}
|
||||
|
||||
type fakeModule struct {
|
||||
key string
|
||||
policy proposals.ReplacementPolicy
|
||||
proposeF func(req contracts.ProposalRequest) ([]proposals.CorrectionProposal, error)
|
||||
key string
|
||||
policy proposals.ReplacementPolicy
|
||||
validators []contracts.Validator
|
||||
proposeF func(req contracts.ProposalRequest) ([]proposals.CorrectionProposal, error)
|
||||
}
|
||||
|
||||
func (m fakeModule) Key() string { return m.key }
|
||||
func (m fakeModule) ReplacementPolicy() proposals.ReplacementPolicy { return m.policy }
|
||||
func (m fakeModule) Validators() []contracts.Validator { return nil }
|
||||
func (m fakeModule) Validators() []contracts.Validator { return m.validators }
|
||||
func (m fakeModule) Propose(ctx context.Context, req contracts.ProposalRequest) ([]proposals.CorrectionProposal, error) {
|
||||
if m.proposeF == nil {
|
||||
return nil, nil
|
||||
@@ -646,14 +648,32 @@ func (m fakeModule) Propose(ctx context.Context, req contracts.ProposalRequest)
|
||||
return m.proposeF(req)
|
||||
}
|
||||
|
||||
type fakeValidator struct {
|
||||
name string
|
||||
validateF func(req contracts.ValidationRequest) (validators.Result, error)
|
||||
}
|
||||
|
||||
func (v fakeValidator) Name() string { return v.name }
|
||||
func (v fakeValidator) Validate(ctx context.Context, req contracts.ValidationRequest) (validators.Result, error) {
|
||||
_ = ctx
|
||||
return v.validateF(req)
|
||||
}
|
||||
|
||||
func TestRunProcessInjectedFactoryExecutesRunnerAndReportsModules(t *testing.T) {
|
||||
allow := fakeValidator{name: "allow", validateF: func(req contracts.ValidationRequest) (validators.Result, error) {
|
||||
decisions := make([]validators.Decision, len(req.CandidateProposal))
|
||||
for i, p := range req.CandidateProposal {
|
||||
decisions[i] = validators.Decision{ProposalIndex: p.ProposalIndex, Approved: true, ReasonCode: validators.ReasonApproved, Message: "approved"}
|
||||
}
|
||||
return validators.Result{ValidatorName: "allow", Decisions: decisions}, nil
|
||||
}}
|
||||
processModuleFactory = fakeModuleFactory{modules: map[string]contracts.TranscriptModule{
|
||||
"m1": fakeModule{key: "m1", policy: proposals.ReplacementPolicyRequireUnique, proposeF: func(req contracts.ProposalRequest) ([]proposals.CorrectionProposal, error) {
|
||||
"m1": fakeModule{key: "m1", policy: proposals.ReplacementPolicyRequireUnique, validators: []contracts.Validator{allow}, proposeF: func(req contracts.ProposalRequest) ([]proposals.CorrectionProposal, error) {
|
||||
return []proposals.CorrectionProposal{
|
||||
{TargetSegmentID: 1, OriginalText: "Hello", CorrectedText: "Hi", Confidence: 1},
|
||||
}, nil
|
||||
}},
|
||||
"m2": fakeModule{key: "m2", policy: proposals.ReplacementPolicyRequireUnique, proposeF: func(req contracts.ProposalRequest) ([]proposals.CorrectionProposal, error) {
|
||||
"m2": fakeModule{key: "m2", policy: proposals.ReplacementPolicyRequireUnique, validators: []contracts.Validator{allow}, proposeF: func(req contracts.ProposalRequest) ([]proposals.CorrectionProposal, error) {
|
||||
if req.WorkingTranscript.Segments[0].Text != "Hi world" {
|
||||
t.Fatalf("expected module 2 to see module 1 changes, got %q", req.WorkingTranscript.Segments[0].Text)
|
||||
}
|
||||
@@ -711,11 +731,17 @@ func TestRunProcessInjectedFactoryExecutesRunnerAndReportsModules(t *testing.T)
|
||||
if len(report.ModuleResults[1].SkippedChanges) != 1 {
|
||||
t.Fatalf("expected skipped change for module 2, got %+v", report.ModuleResults[1].SkippedChanges)
|
||||
}
|
||||
if len(report.ModuleResults[0].ValidatorDecisions) == 0 {
|
||||
t.Fatalf("expected validator decisions in module report")
|
||||
}
|
||||
|
||||
runDirReport := readProcessReport(t, filepath.Join(onlyRunDir(t, workDir), "report.json"))
|
||||
if len(runDirReport.ModuleResults) != 2 {
|
||||
t.Fatalf("expected module results in run-dir report")
|
||||
}
|
||||
if len(runDirReport.ModuleResults[1].ValidatorDecisions) == 0 {
|
||||
t.Fatalf("expected validator decisions in run-dir report")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunProcessInjectedFactorySkippedKeepsAutoRetention(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user