reasoners

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package reasoners ports the 16 router reasoners in src/pr_af/reasoners/harnesses.py (intake_phase … coverage_gate) to Go.

Each reasoner is a plain function

func XxxPhase(ctx context.Context, deps Deps, in XxxInput) (map[string]any, error)

that builds its prompt with the byte-verbatim builders in internal/prompts, invokes the harness through the harnessx.Run choke point (or the AI seam for the two .ai() gates: IntakePhase and CoverageGate), and returns the exact snake_case key set Python's model_dump() emits (design §B.2). The orchestrator (T4.1) calls these in-process; node/register.go (T4.2) wraps them in afx.Bind adapters for control-plane registration.

Parse-failure behavior mirrors Python per reasoner: when the harness could not produce a schema-valid result (Result.Parsed == nil), each reasoner applies the same deterministic fallback its Python counterpart does — a seeded default struct, an empty key set, or a keep-everything index list — never an error (design §C.3 step 4). Harness transport errors and fatal (non-retryable) API errors propagate as Go errors, exactly as Python lets the exception escape the reasoner.

Index

Constants

View Source
const (
	LabelAnatomy        = "anatomy"
	LabelChallenge      = "challenge"
	LabelCoverage       = "coverage"
	LabelCrossRef       = "cross-ref"
	LabelDeepen         = "deepen"
	LabelEvidence       = "evidence"
	LabelIntake         = "intake"
	LabelLens           = "lens"
	LabelObligations    = "obligations"
	LabelPlan           = "plan"
	LabelPostWorthiness = "post worthiness"
	LabelReviewer       = "reviewer"
)

The labels a reasoner's agent session carries (appx.HarnessOptions.Label): what the session is for, in a word. codeaf names the session's thread by it and keys each agent's turn and time limits on it (internal/praf's limits.go), so each is a constant here and written nowhere else.

View Source
const (
	NameIntakePhase         = "intake_phase"
	NameAnatomyPhase        = "anatomy_phase"
	NamePlanningPhase       = "planning_phase"
	NameMetaSemantic        = "meta_semantic"
	NameMetaMechanical      = "meta_mechanical"
	NameMetaSystemic        = "meta_systemic"
	NameReviewDimension     = "review_dimension"
	NameCompoundFinderPhase = "compound_finder_phase"
	NamePostWorthinessGate  = "post_worthiness_gate"
	NameCompoundDedupPhase  = "compound_dedup_phase"
	NameEvidenceVerifier    = "evidence_verifier"
	NameAdversaryPhase      = "adversary_phase"
	NameDeepenFindings      = "deepen_findings"
	NameExtractObligations  = "extract_obligations"
	NameVerifyObligation    = "verify_obligation"
	NameCoverageGate        = "coverage_gate"
)

Control-plane registration names of the 16 router reasoners (design §B.1). node/register.go registers each handler under these names, and the orchestrator's CallLocal-routed seams (orch.callLocalSeams) invoke them by the same constants — a single source of truth so the DAG's phase names can never drift from the registered surface.

Variables

Labels is every label a reasoner's session carries.

Functions

func AdversaryPhase

func AdversaryPhase(ctx context.Context, deps Deps, in AdversaryInput) (map[string]any, error)

AdversaryPhase ports adversary_phase: the skeptical challenger that confirms, challenges, or escalates each finding against ground-truth evidence. Skepticism escalates to "high" when the AI-generated confidence exceeds 0.5 (handled inside the prompt builder).

Output keys (§B.2): results. Parse failure degrades to an empty list.

func AnatomyPhase

func AnatomyPhase(ctx context.Context, deps Deps, in AnatomyInput) (map[string]any, error)

AnatomyPhase ports anatomy_phase: deterministic diff decomposition (parse, stats, clusters, blast radius) plus one .harness() call for the semantic narrative fields, merged into an AnatomyResult.

Output keys (§B.2): files, clusters, blast_radius, dependency_graph, stats, pr_narrative, risk_surfaces, unrelated_changes, intent_gaps, context_notes. A harness parse failure degrades to empty semantic fields (Python falls back to a default _AnatomySemanticResult), never an error.

func CompoundDedupPhase

func CompoundDedupPhase(ctx context.Context, deps Deps, in CompoundDedupInput) (map[string]any, error)

CompoundDedupPhase ports compound_dedup_phase: one harness call that decides which compound findings are genuinely distinct insights.

Output keys (§B.2): keep_indices, reasoning. One-or-fewer findings short-circuits to keep-everything; an empty/invalid index list (including the parse-failure fallback) also degrades to keep-everything.

func CompoundFinderPhase

func CompoundFinderPhase(ctx context.Context, deps Deps, in CompoundFinderInput) (map[string]any, error)

CompoundFinderPhase ports compound_finder_phase: given a small cluster of findings that might interact, synthesize NEW compound findings when the combined risk is real.

Output keys (§B.2): findings. Fewer than two findings short-circuits to an empty list without a harness call; parse failure degrades to an empty list.

func CoverageGate

func CoverageGate(ctx context.Context, deps Deps, in CoverageGateInput) (map[string]any, error)

CoverageGate ports coverage_gate: one .ai() call that decides whether the review dimensions covered every change cluster, with a .harness() retry of the same prompt when the AI seam is unavailable or refuses the structured request (harnesses.py coverage_gate wraps its .ai() call the same way).

Output keys (§B.2): fully_covered, gap_descriptions, confident. Absent response keys land on the pydantic defaults through CoverageGate's seeded UnmarshalJSON (confident=true, gap_descriptions=[]); a harness fallback that fails to parse returns {} (Python returns a literal empty dict).

func DeepenFindings

func DeepenFindings(ctx context.Context, deps Deps, in DeepenInput) (map[string]any, error)

DeepenFindings ports deepen_findings (registered but DEAD on the live path): the literal ground-truth verification pass over the changed code.

Output keys (§B.2): findings. No non-empty patches short-circuits to an empty list without a harness call; parse failure degrades to an empty list.

func EvidenceVerifier

func EvidenceVerifier(ctx context.Context, deps Deps, in EvidenceVerifierInput) (map[string]any, error)

EvidenceVerifier ports evidence_verifier: independent verification of critical/important findings against programmatically extracted ground-truth code, before the adversarial phase.

Output keys (§B.2): verified_findings. Parse failure degrades to an empty list.

func ExtractObligations

func ExtractObligations(ctx context.Context, deps Deps, in ExtractObligationsInput) (map[string]any, error)

ExtractObligations ports extract_obligations: enumerate the cross-location consistency obligations the changed code creates (breadth pass; judged one at a time by VerifyObligation).

Output keys (§B.2): obligations (each: id, where, relies_on, property). No non-empty patches short-circuits to an empty list without a harness call; parse failure degrades to an empty list.

func IntakePhase

func IntakePhase(ctx context.Context, deps Deps, in IntakeInput) (map[string]any, error)

IntakePhase ports intake_phase: a fast .ai() metadata classification gate that, when confident, combines with the deterministic extractors into an IntakeResult; otherwise it escalates to a full .harness() classification.

Output keys (§B.2): pr_type, complexity, languages, areas_touched, risk_signals, ai_generated, review_depth, pr_summary — or {} when the harness fallback fails to parse (Python returns a literal empty dict).

func MetaMechanical

func MetaMechanical(ctx context.Context, deps Deps, in MetaInput) (map[string]any, error)

MetaMechanical ports meta_mechanical.

func MetaSemantic

func MetaSemantic(ctx context.Context, deps Deps, in MetaInput) (map[string]any, error)

MetaSemantic ports meta_semantic.

func MetaSystemic

func MetaSystemic(ctx context.Context, deps Deps, in MetaInput) (map[string]any, error)

MetaSystemic ports meta_systemic.

func PlanningPhase

func PlanningPhase(ctx context.Context, deps Deps, in PlanningInput) (map[string]any, error)

PlanningPhase ports planning_phase (registered but DEAD on the live path — the meta-selectors replaced it; kept for surface parity).

Output keys (§B.2): dimensions, cross_ref_hints, ai_adjusted, total_budget — or the literal {"dimensions": [], "cross_ref_hints": []} on parse failure.

func PostWorthinessGate

func PostWorthinessGate(ctx context.Context, deps Deps, in PostWorthinessInput) (map[string]any, error)

PostWorthinessGate ports post_worthiness_gate: an experienced-reviewer judgment over which findings are genuinely worth posting (recall-preserving: unsure -> keep).

Output keys (§B.2): keep_indices, reasoning — EXCEPT the <=1-finding short-circuit, which Python returns as {"keep_indices": [...]} with no reasoning key. Empty/invalid harness indices (including parse failure) degrade to keep-everything, never silencing all findings.

func ReviewDimension

func ReviewDimension(ctx context.Context, deps Deps, in ReviewDimensionInput) (map[string]any, error)

ReviewDimension ports review_dimension: one focused reviewer over an assigned dimension, with optional sub-review spawning below max depth.

Output keys (§B.2): findings, sub_reviews, current_depth. A schema parse failure logs loudly (indistinguishable from a clean review otherwise) and reports zero findings — Python prints and substitutes an empty _ReviewFindingsResult.

func VerifyObligation

func VerifyObligation(ctx context.Context, deps Deps, in VerifyObligationInput) (map[string]any, error)

VerifyObligation ports verify_obligation: read BOTH ends of one consistency obligation and decide whether the property holds.

Output keys (§B.2): holds, title, severity, file_path, line_start, line_end, body, evidence, suggestion, confidence. Parse failure degrades to the seeded verdict (holds=true, severity="important", confidence=0.7) — Python's `_ObligationVerdict(holds=True)`.

Types

type AICaller

type AICaller interface {
	AI(ctx context.Context, prompt string, opts ...ai.Option) (*ai.Response, error)
}

AICaller is the seam for the SDK's LLM chat entry point (Agent.AI), used by the two .ai() reasoners (intake_phase's gate and coverage_gate). Declaring the one-method interface here lets tests script structured responses without a live model; the review's appx.App satisfies it.

type AdversaryInput

type AdversaryInput struct {
	Findings              []schemas.ReviewFinding   `json:"findings"`
	AIGeneratedConfidence float64                   `json:"ai_generated_confidence"`
	PrContext             string                    `json:"pr_context"`
	RepoPath              string                    `json:"repo_path"`
	EvidencePackages      map[string]map[string]any `json:"evidence_packages"`
}

AdversaryInput mirrors adversary_phase(findings, ai_generated_confidence=0.0, pr_context="", repo_path="", evidence_packages=None).

type AnatomyInput

type AnatomyInput struct {
	PRData   schemas.GitHubPRData `json:"pr_data"`
	Intake   schemas.IntakeResult `json:"intake"`
	RepoPath string               `json:"repo_path"`
}

AnatomyInput mirrors anatomy_phase(pr_data, intake, repo_path="").

type CompoundDedupInput

type CompoundDedupInput struct {
	CompoundFindings          []schemas.ReviewFinding `json:"compound_findings"`
	IndividualFindingsSummary string                  `json:"individual_findings_summary"`
}

CompoundDedupInput mirrors compound_dedup_phase(compound_findings, individual_findings_summary="").

type CompoundFinderInput

type CompoundFinderInput struct {
	ClusterFindings []schemas.ReviewFinding   `json:"cluster_findings"`
	RepoPath        string                    `json:"repo_path"`
	EvidenceMap     map[string]map[string]any `json:"evidence_map"`
}

CompoundFinderInput mirrors compound_finder_phase(cluster_findings, repo_path="", evidence_map=None). EvidenceMap values are EvidencePackage.model_dump()-shaped dicts keyed by finding title.

type CoverageGateInput

type CoverageGateInput struct {
	Anatomy                schemas.AnatomyResult `json:"anatomy"`
	ReviewedClusters       []string              `json:"reviewed_clusters"`
	DimensionNamesReviewed []string              `json:"dimension_names_reviewed"`
}

CoverageGateInput mirrors coverage_gate(anatomy, reviewed_clusters, dimension_names_reviewed=None).

type DeepenInput

type DeepenInput struct {
	DiffPatches    OrderedPatches `json:"diff_patches"`
	ExistingTitles []string       `json:"existing_titles"`
	RepoPath       string         `json:"repo_path"`
	PrContext      string         `json:"pr_context"`
}

DeepenInput mirrors deepen_findings(diff_patches=None, existing_titles=None, repo_path="", pr_context="").

type Deps

type Deps struct {
	Harness harnessx.HarnessCaller
	AI      AICaller
}

Deps carries the two injectable capabilities a reasoner may use. Harness is required by every reasoner except CoverageGate; AI is required only by IntakePhase and CoverageGate (Python's router.app.ai calls).

type EvidenceVerifierInput

type EvidenceVerifierInput struct {
	Findings         []schemas.ReviewFinding   `json:"findings"`
	EvidencePackages map[string]map[string]any `json:"evidence_packages"`
	PrContext        string                    `json:"pr_context"`
	RepoPath         string                    `json:"repo_path"`
}

EvidenceVerifierInput mirrors evidence_verifier(findings, evidence_packages=None, pr_context="", repo_path="").

type ExtractObligationsInput

type ExtractObligationsInput struct {
	DiffPatches OrderedPatches `json:"diff_patches"`
	RepoPath    string         `json:"repo_path"`
	PrContext   string         `json:"pr_context"`
}

ExtractObligationsInput mirrors extract_obligations(diff_patches=None, repo_path="", pr_context="").

type IntakeInput

type IntakeInput struct {
	PRData schemas.GitHubPRData `json:"pr_data"`
	Depth  string               `json:"depth"`
}

IntakeInput mirrors intake_phase(pr_data, depth="standard").

func (*IntakeInput) UnmarshalJSON

func (i *IntakeInput) UnmarshalJSON(b []byte) error

type MetaInput

type MetaInput struct {
	Intake           schemas.IntakeResult  `json:"intake"`
	Anatomy          schemas.AnatomyResult `json:"anatomy"`
	Depth            string                `json:"depth"`
	RepoPath         string                `json:"repo_path"`
	DiffPatches      OrderedPatches        `json:"diff_patches"`
	ReviewerFeedback string                `json:"reviewer_feedback"`
}

MetaInput mirrors the shared signature of meta_semantic / meta_mechanical / meta_systemic(intake, anatomy, depth="standard", repo_path="", diff_patches=None, reviewer_feedback="").

func (*MetaInput) UnmarshalJSON

func (m *MetaInput) UnmarshalJSON(b []byte) error

type OrderedPatches

type OrderedPatches []prompts.StrPair

OrderedPatches is a diff_patches dict with preserved insertion order — Python's dict[str, str] whose ordering the meta/deepen/obligation prompts render. It JSON-round-trips as an object, decoding in document order.

func (OrderedPatches) MarshalJSON

func (p OrderedPatches) MarshalJSON() ([]byte, error)

MarshalJSON renders the pairs as a JSON object in slice order.

func (*OrderedPatches) UnmarshalJSON

func (p *OrderedPatches) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes a JSON object into ordered pairs, preserving the document's key order (duplicate keys: last value wins, first position kept — matching Python's dict literal semantics). null decodes to nil.

type PlanningInput

type PlanningInput struct {
	Intake  schemas.IntakeResult  `json:"intake"`
	Anatomy schemas.AnatomyResult `json:"anatomy"`
	Depth   string                `json:"depth"`
	Hints   []string              `json:"hints"`
}

PlanningInput mirrors planning_phase(intake, anatomy, depth="standard", hints=None).

func (*PlanningInput) UnmarshalJSON

func (p *PlanningInput) UnmarshalJSON(b []byte) error

type PostWorthinessInput

type PostWorthinessInput struct {
	Findings []schemas.ReviewFinding `json:"findings"`
}

PostWorthinessInput mirrors post_worthiness_gate(findings). The live path passes ReviewFinding dumps.

type ReviewDimensionInput

type ReviewDimensionInput struct {
	ReviewPrompt      string            `json:"review_prompt"`
	TargetFiles       []string          `json:"target_files"`
	ContextFiles      []string          `json:"context_files"`
	RepoPath          string            `json:"repo_path"`
	CurrentDepth      int               `json:"current_depth"`
	MaxDepth          int               `json:"max_depth"`
	PrNarrative       string            `json:"pr_narrative"`
	RiskSurfaces      []string          `json:"risk_surfaces"`
	IntakeSummary     string            `json:"intake_summary"`
	PrDescription     string            `json:"pr_description"`
	DiffPatches       map[string]string `json:"diff_patches"`
	AllDimensionNames []string          `json:"all_dimension_names"`
	ReviewerFeedback  string            `json:"reviewer_feedback"`
	PrimedCode        string            `json:"primed_code"`
}

ReviewDimensionInput mirrors review_dimension's long keyword signature. DiffPatches is a plain map — the prompt renders patches in TargetFiles order, so dict ordering is immaterial here.

func (*ReviewDimensionInput) UnmarshalJSON

func (r *ReviewDimensionInput) UnmarshalJSON(b []byte) error

type VerifyObligationInput

type VerifyObligationInput struct {
	Obligation map[string]any `json:"obligation"`
	RepoPath   string         `json:"repo_path"`
}

VerifyObligationInput mirrors verify_obligation(obligation, repo_path=""). Obligation is the raw dict (an ExtractObligations output element); the reasoner validates it into the private obligation struct exactly as Python runs _Obligation.model_validate.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL