Documentation
¶
Overview ¶
Package codesignal turns pkg/semantics analysis results into prioritized, change-aware coaching signals.
Signal derivation is deterministic and rule-based. A shared registry (registry.go) dispatches each semantics.Finding.Kind to its rule constructor: "state.hidden_input_mutation" ("mutates_input"), "coupling.tight_constructor_init" ("tight_coupling"), "structure.constructor_density" ("constructor_func"), "structure.pointer_return_density" ("pointer_return"), and "security.toctou_check_then_act" ("toctou_check_then_act"). The two structure rules are density-gated: a file only surfaces them once its own per-side count of that finding kind reaches a threshold. Unrecognized finding kinds are ignored. A third dispatch path, signalsFromImports, derives "coupling.deep_relative_import" directly from a TypeScript/TSX file's semantics.ImportFeature list rather than from Findings or Metrics. A fourth path, signalsFromCognitiveComplexity, derives "complexity.cognitive_complexity" from per-function semantics.FunctionCognitiveComplexity records (threshold-gated in codesignal, not in semantics). A fifth path, signalsFromReactOrchestration, derives "structure.react_component_orchestration_density" from per-component semantics.ReactComponentFacts records via a state-domain classification and Emission Rule that live entirely in this package.
A Signal's Lifecycle classifies it relative to an optional Base result. Signal.Changed is independent of Lifecycle: a pre-existing signal may sit on a changed line, and a new signal may sit outside any changed range.
Fingerprints are stable across line moves within a file, but adding or removing an earlier duplicate with the same key can shift occurrence ordinals and change later fingerprints.
pkg/codesignal itself does no I/O or LLM calls: Build is a pure function of its Input.
Index ¶
- Constants
- Variables
- func EvaluateGoLayerBypass(result domain.LayerBypassResult, ...) ([]ProjectChange, []Diagnostic)
- func EvaluateGoLayerViolations(model domain.Model, policy LayerPolicy, ...) ([]ProjectChange, []Diagnostic)
- func EvaluateTypeScriptLayerBypass(result domain.LayerBypassResult, ...) ([]ProjectChange, []Diagnostic)
- func EvaluateTypeScriptLayerViolations(model domain.Model, policy LayerPolicy, ...) ([]ProjectChange, []Diagnostic)
- func RequiredCoverageIncomplete(report *Report) bool
- func SortDiagnostics(diagnostics []Diagnostic)
- type ArchitectureLayer
- type Builder
- type Category
- type ChangeStatus
- type Confidence
- type Coverage
- type CoverageGroup
- type Diagnostic
- type FileChange
- type ForbiddenLayerImport
- type Input
- type LayerPolicy
- type Lifecycle
- type LineRange
- type NarrowOptions
- type Options
- type PathContinuity
- type ProjectChange
- type ProjectFact
- type ProjectLocation
- type ProjectNextAction
- type ProjectPathStep
- type ProjectProvenance
- type ProjectScopeReport
- type ProjectScopeRevisionReport
- type ProjectSummary
- type Provenance
- type ProvenanceAnalyzer
- type ProvenanceCoverage
- type ProvenancePackageManager
- type ProvenanceRevision
- type ProvenanceRuntime
- type Report
- type Scope
- type Severity
- type Signal
- type SignalsWithheld
- type Summary
Constants ¶
const ( DiagKindProjectCoverageIncomplete = "project_coverage_incomplete" DiagKindProjectLifecycleIndeterminate = "project_lifecycle_indeterminate" DiagKindWorktreeChangesNotAnalyzed = "worktree_changes_not_analyzed" )
Diagnostic.Kind values projectLifecycleState (project_lifecycle_state.go) emits when project analysis did not complete, on either side of a diff.
const ( DiagKindWorktreeNotClean = "worktree_not_clean" DiagKindWorktreeStatusCheckFailed = "worktree_status_check_failed" DiagKindWorktreeReportReflectsCommittedHEAD = "worktree_report_reflects_committed_head" )
Dirty-tree notices other than "changes were not analyzed". These kind strings must not contain "not_analyzed".
const DiagKindProjectChangeLifecycleIndeterminate = "project_change_lifecycle_indeterminate"
DiagKindProjectChangeLifecycleIndeterminate identifies a diagnostic naming one degraded ProjectChange's own anchor path together with the comparison Side/Revision that made it indeterminate. It is additive to the single project_lifecycle_indeterminate diagnostic emitted once per report.
Variables ¶
var ( // ErrNilReport reports a Narrow of a nil Report. ErrNilReport = errors.New("codesignal: nil report") // ErrUnknownSeverityFloor reports a NarrowOptions.MinSeverity outside the // severities a Report can emit. ErrUnknownSeverityFloor = errors.New("codesignal: unknown severity floor") // ErrNegativeTop reports a NarrowOptions.Top below zero. ErrNegativeTop = errors.New("codesignal: negative top") // ErrAlreadyNarrowed reports a Narrow of a Report that already carries a // withheld record: a second narrowing could not say which view it produced. ErrAlreadyNarrowed = errors.New("codesignal: report is already narrowed") )
var ErrInvalidSignalsWithheld = errors.New("codesignal: invalid signals_withheld record")
ErrInvalidSignalsWithheld reports a SignalsWithheld that Narrow cannot produce, which would encode as a view that drops or misstates what it withheld.
Functions ¶
func EvaluateGoLayerBypass ¶ added in v0.4.0
func EvaluateGoLayerBypass(result domain.LayerBypassResult, ruleVersion, backendVersion, configDigest string) ([]ProjectChange, []Diagnostic)
EvaluateGoLayerBypass maps result's high-confidence LayerBypassWitnesses (see pkg/projectmodel.BuildGoLayerBypass) onto one architecture.layer_bypass ProjectChange per witness. A witness whose Confidence is not LayerBypassConfidenceHigh is silently skipped rather than downgraded: this re-checks a contract BuildGoLayerBypass already guarantees, defensively, across the package boundary.
SemanticKey is keyed on (RequiredLayer, Source, Sink) -- the same triple LayerBypassWitness.ID uses -- so identity stays stable when only the witness's intermediate Path changes between two revisions. Callers that need Changed to reflect a route change must rely on CausalEvidenceDigest, which this function derives from the ordered Path node-ID sequence.
PrimaryAnchor and each ProjectPathStep.SourceLocations are populated from the witness's own Path[i].Path/Line (a real repository-relative source position -- see pkg/projectmodel/go_layer_bypass.go) rather than a call-graph node identity string: PrimaryAnchor uses the first Path step with a resolvable position (ordinarily the witness's Source function itself; a later step only when Source's own position is unresolvable, e.g. a synthetic wrapper). When no step on the path resolves a position at all, PrimaryAnchor is left empty rather than fabricated -- callers must route this return value through Build's filterAnchorlessProjectChanges (or equivalent), which drops the anchorless change and emits a project_observation_missing_primary_path diagnostic instead of surfacing a fake location. The witness's SSA node identity is never lost: it stays on MachineEvidence["source"]/["path"] and every ProjectPathStep.NodeID.
result.Coverage reports how much of BuildGoLayerBypass's own source/sink search actually completed; it is independent of Build's project-level Input.ProjectCoverage/BaseProjectCoverage gate. When result.Coverage is not complete, EvaluateGoLayerBypass still emits any witnesses found (they are real, statically resolved paths regardless of what else was truncated) but also returns a project_layer_bypass_coverage_incomplete Diagnostic, because the absence of a witness for some other source/sink pair in this same incomplete run is not a sound "no bypass" claim. Callers must fold result.Coverage into Input.ProjectCoverage/BaseProjectCoverage (the two Coverage values this rule's caller is responsible for combining, alongside every other project evaluator's) so projectLifecycleState (project_lifecycle_state.go) degrades affected ProjectChanges to Lifecycle "unknown" rather than emitting "resolved" for a witness that only disappeared because the search was truncated, not because the bypass was actually fixed.
func EvaluateGoLayerViolations ¶ added in v0.4.0
func EvaluateGoLayerViolations(model domain.Model, policy LayerPolicy, ruleVersion, backendVersion, configDigest string) ([]ProjectChange, []Diagnostic)
EvaluateGoLayerViolations evaluates model's internal Go import edges against policy and returns one architecture.layer_violation ProjectChange per violating (importer package directory, importee package directory) pair -- multiple edges/sites between the same pair collapse into a single ProjectChange rather than one per edge.
Only ImportEdges with Kind == "internal" are ever eligible; every other Kind (stdlib, external, replaced, unresolved, excluded) is silently skipped. An edge whose importer or importee package directory does not map to any configured layer is likewise silently skipped -- that is an expected, non-error outcome (partial layer coverage), not a diagnostic. Consequently the returned diagnostics are always nil in the current design.
If policy has no Layers or no ForbiddenImports, EvaluateGoLayerViolations returns (nil, nil) immediately: there is no policy to evaluate.
func EvaluateTypeScriptLayerBypass ¶ added in v0.4.0
func EvaluateTypeScriptLayerBypass(result domain.LayerBypassResult, ruleVersion, backendVersion, configDigest string) ([]ProjectChange, []Diagnostic)
EvaluateTypeScriptLayerBypass is the TypeScript analog of EvaluateGoLayerBypass: it maps result's high-confidence LayerBypassWitnesses (see pkg/projectmodel.BuildTypeScriptLayerBypass) onto one architecture.layer_bypass ProjectChange per witness, under the same ruleLayerBypassID vocabulary, plus a MachineEvidence["language"] = "typescript" entry -- mirroring EvaluateTypeScriptLayerViolations' relationship to EvaluateGoLayerViolations (rule_layer_violation.go). See EvaluateGoLayerBypass's doc comment for the shared confidence-filtering, anchoring, and coverage-incompleteness contract this function reuses unchanged via layerBypassChange.
func EvaluateTypeScriptLayerViolations ¶ added in v0.4.0
func EvaluateTypeScriptLayerViolations(model domain.Model, policy LayerPolicy, ruleVersion, backendVersion, configDigest string) ([]ProjectChange, []Diagnostic)
EvaluateTypeScriptLayerViolations is the TypeScript/TSX analog of EvaluateGoLayerViolations: it evaluates model's value-level (import, reexport), file-addressed TS/TSX import edges against policy, producing architecture.layer_violation ProjectChanges with the same field shape as the Go evaluator plus a MachineEvidence["language"] = "typescript" entry.
An edge is eligible only when Kind is "import" or "reexport" and both From and To carry the "file:" prefix (see forbiddenTSPair). The project sidecar only ever emits a "file:"-addressed To together with Resolution "snapshot" (js/semantics/src/project-sidecar/edges-resolve.ts), so the prefix check alone is sufficient to select snapshot-resolved edges; "type_only" edges are never runtime dependencies, and "commonjs_require"/"dynamic_import" edges or edges resolving to "external:"/"unresolved:" targets are silently skipped, same as Go's evaluator skips non-internal edges. Consequently the returned diagnostics are always nil in the current design.
If policy has no Layers or no ForbiddenImports, EvaluateTypeScriptLayerViolations returns (nil, nil) immediately: there is no policy to evaluate.
func RequiredCoverageIncomplete ¶ added in v0.8.0
RequiredCoverageIncomplete reports whether required project coverage is incomplete for any analyzed side of the report. Model or bypass incompleteness on any side counts; reachability incompleteness alone does not. When ProjectProvenance is absent, a project_backend_unavailable diagnostic is treated as incomplete so schema-1 reports (which carry no provenance) still satisfy the predicate.
func SortDiagnostics ¶ added in v0.4.0
func SortDiagnostics(diagnostics []Diagnostic)
SortDiagnostics orders diagnostics by path, kind, location, then message. Callers that append diagnostics after Build must use this so report order stays identical to Build's own sortDiagnostics pass.
Types ¶
type ArchitectureLayer ¶ added in v0.4.0
ArchitectureLayer names a policy layer and its repository-relative directory prefixes. Prefixes are assumed already validated as non-empty, unique, and mutually non-overlapping by the caller.
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder produces Reports from Input. It holds no mutable state after construction (options is copied in New and never written to again), so a *Builder is safe for concurrent Build calls without additional synchronization.
type ChangeStatus ¶
type ChangeStatus string
type Confidence ¶
type Confidence string
type Coverage ¶ added in v0.1.2
type Coverage struct {
TrackedFilesDiscovered int `json:"tracked_files_discovered"`
FilesAnalyzed int `json:"files_analyzed"`
FilesUnanalyzable int `json:"files_unanalyzable"`
Unsupported []CoverageGroup `json:"unsupported"`
Excluded []CoverageGroup `json:"excluded"`
}
Coverage reports file-discovery accounting for a Repository Baseline run. A base-diff Report also sets Coverage, but only to carry Excluded (the diff flow's filtered-file tally, for the same "why did my file disappear" disclosure a baseline report gives); TrackedFilesDiscovered, FilesAnalyzed, and FilesUnanalyzable are full-repository accounting that only baseline mode computes, and read as zero on a diff-flow report regardless of how many files it actually analyzed -- see Report.Summary for diff-flow file counts instead. Coverage is nil on a diff-flow report when nothing was filtered.
type CoverageGroup ¶ added in v0.1.2
type CoverageGroup struct {
Reason string `json:"reason"`
Language string `json:"language,omitempty"`
Count int `json:"count"`
}
CoverageGroup summarizes a set of files sharing an exclusion/unsupported reason and language or file-type, rather than one entry per file.
type Diagnostic ¶
type Diagnostic struct {
Path string `json:"path"`
Kind string `json:"kind"`
Message string `json:"message"`
Location *semantics.Location `json:"location,omitempty"`
// Side identifies which comparison side this diagnostic concerns: "head"
// or "base".
Side string `json:"side,omitempty"`
// Revision is Side's git revision (e.g. commit SHA), so the diagnostic's
// text-named side/revision has a machine-readable counterpart.
Revision string `json:"revision,omitempty"`
}
Diagnostic reports a problem observed while building a Report.
type FileChange ¶
type FileChange struct {
Path string `json:"path"`
Status ChangeStatus `json:"status,omitempty"`
SourceScope string `json:"source_scope,omitempty"`
Base *semantics.Result `json:"base,omitempty"`
Head *semantics.Result `json:"head,omitempty"`
ChangedRanges []LineRange `json:"changed_ranges,omitempty"`
}
FileChange describes one file's before/after analysis results.
type ForbiddenLayerImport ¶ added in v0.4.0
ForbiddenLayerImport is one directed "layer From must not import layer To" rule.
type Input ¶
type Input struct {
Scope Scope `json:"scope"`
Files []FileChange `json:"files,omitempty"`
Diagnostics []Diagnostic `json:"diagnostics,omitempty"`
Coverage *Coverage `json:"coverage,omitempty"`
// ProjectChanges are head-side raw project observations, not yet
// lifecycle-classified. BaseProjectChanges is the base-side equivalent
// for a diff-flow comparison (empty/nil for a Repository Baseline
// run). SemanticKey must be set by the caller on every entry -- it is
// ProjectChange's lifecycle identity, unlike Signal which derives its
// key from rule/path/subject/evidence.
ProjectChanges []ProjectChange `json:"project_changes,omitempty"`
BaseProjectChanges []ProjectChange `json:"base_project_changes,omitempty"`
ProjectFacts []ProjectFact `json:"project_facts,omitempty"`
ProjectCoverage *domain.Coverage `json:"project_coverage,omitempty"`
BaseProjectCoverage *domain.Coverage `json:"base_project_coverage,omitempty"`
// ProjectBaseAnalyzed reports whether a base-side project model was
// built at all; distinct from len(BaseProjectChanges) > 0, which cannot
// distinguish a clean base (analyzed, zero changes) from no base having
// been analyzed. Build uses this flag (not slice length) to decide
// whether head-only project changes are "introduced" or "unknown" --
// mirroring how Signal lifecycle classification keys off FileChange.Base's
// presence rather than whether it produced findings. A non-nil empty
// BaseProjectChanges with ProjectBaseAnalyzed false is treated as "no
// base side" (valid for baseline); non-empty changes without the flag
// are inconsistent and force lifecycle-indeterminate.
ProjectBaseAnalyzed bool `json:"project_base_analyzed,omitempty"`
// UndeterminedContinuity lists rename/copy pairs whose old-path
// continuity was not determined. A project change that would otherwise
// be introduced at Path, or resolved at PreviousPath, is classified
// "unknown" instead: a path-keyed identity cannot tell a move from a
// fix plus a new defect.
UndeterminedContinuity []PathContinuity `json:"undetermined_continuity,omitempty"`
RuntimeKind string `json:"runtime_kind,omitempty"`
RuntimeVersion string `json:"runtime_version,omitempty"`
RuntimeOrigin string `json:"runtime_origin,omitempty"`
CompilerVersion string `json:"compiler_version,omitempty"`
CompilerOrigin string `json:"compiler_origin,omitempty"`
// Language is the project language ("typescript" or "go"). Only
// "typescript" triggers project_provenance population on the report.
Language string `json:"language,omitempty"`
// ConfigDigest is the stable hex digest of the validated project config bytes.
ConfigDigest string `json:"config_digest,omitempty"`
// SelectedRoots lists the config roots declared in the project config.
SelectedRoots []string `json:"selected_roots,omitempty"`
// AnalyzerProtocolVersion identifies the protocol version the analyzer used
// to produce project observations. For TypeScript reports, buildProjectProvenance
// defaults this to 1 when the caller leaves it zero.
AnalyzerProtocolVersion int `json:"analyzer_protocol_version,omitempty"`
AnalyzerVersion string `json:"analyzer_version,omitempty"`
AnalyzerDigest string `json:"analyzer_digest,omitempty"`
// PackageManager* describe the package manager detected from the analyzed
// snapshot's committed metadata. Version is omitted when unverifiable from PATH.
PackageManagerKind string `json:"package_manager_kind,omitempty"`
PackageManagerVersion string `json:"package_manager_version,omitempty"`
PackageManagerOrigin string `json:"package_manager_origin,omitempty"`
// HeadProjectScope and BaseProjectScope carry the per-revision scope
// classification result from the project backend. A nil HeadProjectScope
// means the backend never produced root_scopes data for that revision
// (distinct from an analyzed but empty scope). See ProjectBackendResult for
// the backend contract.
HeadProjectScope *domain.ProjectScope `json:"head_project_scope,omitempty"`
BaseProjectScope *domain.ProjectScope `json:"base_project_scope,omitempty"`
// Phase-specific coverage observations for each analyzed revision. A nil
// pointer means the phase was not observed (treat as not_run in D7 mapping).
HeadModelCoverage *domain.Coverage `json:"head_model_coverage,omitempty"`
BaseModelCoverage *domain.Coverage `json:"base_model_coverage,omitempty"`
HeadBypassCoverage *domain.Coverage `json:"head_bypass_coverage,omitempty"`
BaseBypassCoverage *domain.Coverage `json:"base_bypass_coverage,omitempty"`
HeadReachabilityCoverage *domain.Coverage `json:"head_reachability_coverage,omitempty"`
BaseReachabilityCoverage *domain.Coverage `json:"base_reachability_coverage,omitempty"`
}
Input is the unit of work for a Builder.
type LayerPolicy ¶ added in v0.4.0
type LayerPolicy struct {
Layers []ArchitectureLayer
ForbiddenImports []ForbiddenLayerImport
}
LayerPolicy is a decoded, already-schema-validated layer configuration.
type NarrowOptions ¶ added in v0.10.0
NarrowOptions selects a presentation view of a Report. The zero value narrows nothing: an empty MinSeverity is no floor and a zero Top is no cap.
type Options ¶
type Options struct {
IncludeResolved bool `json:"include_resolved"`
Baseline bool `json:"baseline"`
// ProjectEnabled switches Build onto the schema-2 project-analysis
// report path: SchemaVersion becomes "2" and the Report's project_*
// fields become eligible to serialize. See Report's field block for
// the byte-identity guarantee this default-false zero value preserves.
ProjectEnabled bool `json:"project_enabled"`
}
type PathContinuity ¶ added in v0.10.0
PathContinuity is one git rename or copy: PreviousPath at the base revision, Path at head.
type ProjectChange ¶ added in v0.4.0
type ProjectChange struct {
SemanticKey string `json:"semantic_key"`
ID string `json:"id"`
Fingerprint string `json:"fingerprint"`
RuleID string `json:"rule_id"`
RuleVersion string `json:"rule_version"`
BackendVersion string `json:"backend_version,omitempty"`
AlgorithmVersion string `json:"algorithm_version,omitempty"`
ConfigDigest string `json:"config_digest,omitempty"`
Kind string `json:"kind"`
Category Category `json:"category"`
Severity Severity `json:"severity"`
Confidence Confidence `json:"confidence"`
Lifecycle Lifecycle `json:"lifecycle"`
// Changed is derived by the lifecycle classifier from causal evidence and
// the primary anchor. A producer may set it while constructing an
// observation, but Build recomputes it whenever a comparable base exists.
Changed bool `json:"changed"`
CausalEvidenceDigest string `json:"causal_evidence_digest,omitempty"`
PrimaryAnchor ProjectLocation `json:"primary_anchor"`
RelatedLocations []ProjectLocation `json:"related_locations,omitempty"`
PathSteps []ProjectPathStep `json:"path_steps,omitempty"`
CoverageRefs []string `json:"coverage_refs,omitempty"`
// Evidence is producer-supplied prose. Build appends a fixed note when it
// degrades Lifecycle to "unknown" for incomplete coverage, so a reader
// scanning one finding at a time can see why without separately
// cross-referencing the report's project_lifecycle_indeterminate
// diagnostic. Excluded from Fingerprint/ID (see appendProjectIdentity).
Evidence string `json:"evidence,omitempty"`
// MachineEvidence holds structured rule evidence (e.g. importer/importee
// for architecture.layer_violation). Keys are frozen per rule; encoding/json
// sorts map keys so equivalent maps marshal byte-identically. Not part of
// lifecycle identity — producers fold causal machine fields into
// CausalEvidenceDigest when Changed must track them.
MachineEvidence map[string]string `json:"machine_evidence,omitempty"`
WhyItMatters string `json:"why_it_matters,omitempty"`
Recommendation string `json:"recommendation,omitempty"`
SuggestedSkill string `json:"suggested_skill,omitempty"`
Provenance Provenance `json:"provenance"`
}
ProjectChange is one project-level observation derived from pkg/projectmodel facts -- the cross-file/cross-module analog of Signal. Unlike Signal (scoped to one FileChange, deduplicated by a composite rule/path/subject/evidence key with per-occurrence ordinals), a ProjectChange's SemanticKey is itself the stable lifecycle identity: at most one ProjectChange per SemanticKey exists on each side (head/base) of a comparison. ProjectChange never wraps a synthetic FileChange -- it carries its own PrimaryAnchor/RelatedLocations/PathSteps instead.
type ProjectFact ¶ added in v0.4.0
type ProjectFact struct {
Kind string `json:"kind"`
SemanticKey string `json:"semantic_key,omitempty"`
PathSteps []ProjectPathStep `json:"path_steps,omitempty"`
CoverageRefs []string `json:"coverage_refs,omitempty"`
Evidence string `json:"evidence,omitempty"`
Provenance Provenance `json:"provenance"`
}
ProjectFact is a facts-only project observation (e.g. possible call reachability). Unlike ProjectChange it is never lifecycle-classified, never appears in ProjectSummary active counters, and must not be encoded as a synthetic ProjectChange with a placeholder anchor.
func ReachabilityProjectFacts ¶ added in v0.4.0
func ReachabilityProjectFacts(result domain.ReachabilityResult, language string) []ProjectFact
ReachabilityProjectFacts maps result's possible-call-reachability facts (see pkg/projectmodel.BuildGoReachability / BuildTypeScriptReachability) onto ProjectFact. Provenance.Producer is always "projectmodel", Provenance.FindingKind is the fact's own Kind, and Provenance.Language is set from the language parameter ("go" or "typescript"), matching this package's other project-origin emitters (rule_layer_violation.go, rule_layer_bypass.go). The output is facts-only by construction -- it builds no ProjectChange or Signal, since ordinary possible-call reachability is never an active finding (issue #216 AC-4/AC-11).
type ProjectLocation ¶ added in v0.4.0
type ProjectLocation struct {
Path string `json:"path"`
Location semantics.Location `json:"location"`
}
ProjectLocation anchors a ProjectChange (or one step/related point) to a specific file and position -- Signal's Location is file-implicit (the enclosing Signal.Path); ProjectChange has no single enclosing file, so every location must carry its own Path.
type ProjectNextAction ¶ added in v0.8.0
type ProjectNextAction struct {
Kind string `json:"kind"`
}
ProjectNextAction is one recommended next step surfaced in project_next_actions. Kind values: record_baseline, review_policy_coverage, inspect_diagnostics.
type ProjectPathStep ¶ added in v0.4.0
type ProjectPathStep struct {
NodeID string `json:"node_id"`
DisplayName string `json:"display_name,omitempty"`
Resolution string `json:"resolution,omitempty"`
Confidence Confidence `json:"confidence,omitempty"`
SourceLocations []ProjectLocation `json:"source_locations,omitempty"`
}
ProjectPathStep is one node in a project observation's causal or reachability path. SourceLocations retain the repository evidence for that node without flattening the path into an ambiguous list of files.
type ProjectProvenance ¶ added in v0.8.0
type ProjectProvenance struct {
Language string `json:"language"`
ConfigDigest string `json:"config_digest"`
SelectedRoots []string `json:"selected_roots"`
Analyzer ProvenanceAnalyzer `json:"analyzer"`
Runtime ProvenanceRuntime `json:"runtime"`
PackageManager *ProvenancePackageManager `json:"package_manager,omitempty"`
Head ProvenanceRevision `json:"head"`
Base *ProvenanceRevision `json:"base,omitempty"`
}
ProjectProvenance records how a TypeScript project report was produced: which analyzer ran, which runtime was used, which package manager was detected, and what coverage each revision received. It is optional on Report and populated only for schema-2 TypeScript reports (Go reports omit it via omitempty).
type ProjectScopeReport ¶ added in v0.8.0
type ProjectScopeReport struct {
InclusionRule string `json:"inclusion_rule"`
PatternSet string `json:"pattern_set"`
Head ProjectScopeRevisionReport `json:"head"`
Base *ProjectScopeRevisionReport `json:"base,omitempty"`
}
ProjectScopeReport is the report-level wrapper for project_scope. It adds head/base revision identity around the per-revision scope data that domain.ProjectScope provides. inclusion_rule and pattern_set are top-level (same for both revisions); head and base each carry their own revision SHA plus the per-revision roots/layer classification.
Populated only for schema-2 TypeScript reports; omitted for Go reports via omitempty on Report.ProjectScope.
type ProjectScopeRevisionReport ¶ added in v0.8.0
type ProjectScopeRevisionReport struct {
Revision string `json:"revision"`
Roots []domain.ProjectScopeRoot `json:"roots"`
MatchedLayers []string `json:"matched_layers"`
UnmatchedLayers []string `json:"unmatched_layers"`
}
ProjectScopeRevisionReport is the per-revision part of project_scope, combining the revision SHA with the scope classification results. Roots reuses domain.ProjectScopeRoot so the JSON tags stay consistent with the projectmodel package (root, candidate_files, analyzed_files).
type ProjectSummary ¶ added in v0.4.0
type ProjectSummary struct {
ActiveChanges int `json:"active_changes"`
IntroducedChanges int `json:"introduced_changes"`
ExistingChanges int `json:"existing_changes"`
ResolvedChanges int `json:"resolved_changes"`
BaselineChanges int `json:"baseline_changes"`
}
ProjectSummary counts ProjectChanges across a Report the same way Summary counts Signals. It is a separate, always-optional struct (never merged into Summary) so a disabled/default Report's existing Summary fields never change shape or gain silently-always-zero project fields.
Report.ProjectSummary is non-nil whenever Options.ProjectEnabled is true, even when there are zero ProjectChanges on either side of the comparison -- enabling the mode, not having something to report, is what makes the field appear, so a caller can distinguish "project analysis ran and found nothing" (present, all-zero) from "project analysis did not run" (absent, omitempty). Fact-only observations never increment these counters.
type Provenance ¶
type Provenance struct {
Producer string `json:"producer"`
FindingKind string `json:"finding_kind,omitempty"`
// Language is the source language a project-origin fact was derived
// from ("go" or "typescript"), when the producer records one. It is
// the only queryable cross-language provenance signal on ProjectFact,
// which unlike ProjectChange has no MachineEvidence map to carry an
// equivalent key (see ReachabilityProjectFacts).
Language string `json:"language,omitempty"`
}
type ProvenanceAnalyzer ¶ added in v0.8.0
type ProvenanceAnalyzer struct {
Version string `json:"version"`
Digest string `json:"digest"`
ProtocolVersion int `json:"protocol_version"`
}
ProvenanceAnalyzer identifies the analyzer binary that produced the report.
type ProvenanceCoverage ¶ added in v0.8.0
type ProvenanceCoverage struct {
Model string `json:"model"`
Bypass string `json:"bypass"`
Reachability string `json:"reachability"`
}
ProvenanceCoverage holds the coverage phase outcome for each analysis dimension. Values: complete, incomplete, not_run, not_requested.
type ProvenancePackageManager ¶ added in v0.8.0
type ProvenancePackageManager struct {
Kind string `json:"kind"`
Version string `json:"version,omitempty"`
Origin string `json:"origin"`
}
ProvenancePackageManager describes the package manager detected from snapshot metadata. Kind and origin come from the analyzed revision; Version is the host-probed executable version and is omitted when unverifiable (SA-280-033).
type ProvenanceRevision ¶ added in v0.8.0
type ProvenanceRevision struct {
Revision string `json:"revision"`
Coverage ProvenanceCoverage `json:"coverage"`
}
ProvenanceRevision records coverage for one revision (head or base) of a TypeScript project report.
type ProvenanceRuntime ¶ added in v0.8.0
type ProvenanceRuntime struct {
Kind string `json:"kind"`
Version string `json:"version"`
Origin string `json:"origin"`
CompilerVersion string `json:"compiler_version"`
CompilerOrigin string `json:"compiler_origin"`
DeclaredVersion string `json:"declared_version,omitempty"`
}
ProvenanceRuntime describes the Node/Bun runtime resolved for the project. DeclaredVersion is populated only when the project pins a version (T13/#354).
type Report ¶
type Report struct {
SchemaVersion string `json:"schema_version"`
Scope Scope `json:"scope"`
Summary Summary `json:"summary"`
Signals []Signal `json:"signals"`
Diagnostics []Diagnostic `json:"diagnostics"`
Coverage *Coverage `json:"coverage"`
SignalsWithheld *SignalsWithheld `json:"signals_withheld,omitempty"`
ProjectChanges []ProjectChange `json:"project_changes"`
ProjectFacts []ProjectFact `json:"project_facts"`
ProjectSummary *ProjectSummary `json:"project_summary"`
ProjectCoverage *domain.Coverage `json:"project_coverage"`
ProjectProvenance *ProjectProvenance `json:"project_provenance,omitempty"`
ProjectScope *ProjectScopeReport `json:"project_scope,omitempty"`
ProjectNextActions []ProjectNextAction `json:"project_next_actions,omitempty"`
}
func (Report) MarshalJSON ¶ added in v0.4.0
func (*Report) Narrow ¶ added in v0.10.0
func (r *Report) Narrow(opts NarrowOptions) (*Report, error)
Narrow returns a copy of r whose Signals and ProjectChanges hold only what opts keeps, and whose SignalsWithheld records what it left out.
When opts narrow anything, Narrow ranks its copy of the signals, so a report in any order yields the same view. The severity floor applies first and the cap takes the leading signals of what remains. Signals sort by lifecycle group before severity, so the two narrowings do not commute; Narrow is the only entry point and fixes the order, so the record always describes the view that was produced.
Summary, Coverage, Diagnostics and every project summary and coverage block are shared with r untouched. ProjectChanges follow their mirrored signal by ID, so each finding is counted once.
A nil r, an already narrowed r, an unrecognised floor or a negative Top returns an error and no view, never a different view than the one asked for; that holds for zero opts too. Valid zero opts then return r itself with no record.
type Scope ¶
type Scope struct {
Repository string `json:"repository,omitempty"`
Revision string `json:"revision,omitempty"`
Base string `json:"base,omitempty"`
AppliedScope string `json:"applied_scope,omitempty"`
Baseline bool `json:"baseline,omitempty"`
}
Scope identifies the repository and revision range an Input covers.
type Severity ¶
type Severity string
func ParseSeverityFloor ¶ added in v0.10.0
ParseSeverityFloor accepts exactly the severities the report can emit.
func SeverityFloors ¶ added in v0.10.0
func SeverityFloors() []Severity
SeverityFloors lists the severities a floor may name, highest first. The slice is a copy the caller may modify.
type Signal ¶
type Signal struct {
ID string `json:"id"`
Fingerprint string `json:"fingerprint"`
RuleID string `json:"rule_id"`
RuleVersion string `json:"rule_version"`
Kind string `json:"kind"`
Category Category `json:"category"`
Severity Severity `json:"severity"`
Confidence Confidence `json:"confidence"`
Lifecycle Lifecycle `json:"lifecycle"`
Changed bool `json:"changed"`
Path string `json:"path"`
SourceScope string `json:"source_scope,omitempty"`
Subject string `json:"subject,omitempty"`
Location semantics.Location `json:"location"`
Evidence string `json:"evidence,omitempty"`
WhyItMatters string `json:"why_it_matters"`
Recommendation string `json:"recommendation"`
SuggestedSkill string `json:"suggested_skill"`
Provenance Provenance `json:"provenance"`
MachineEvidence map[string]string `json:"machine_evidence"`
RelatedLocations []ProjectLocation `json:"related_locations"`
PathSteps []ProjectPathStep `json:"path_steps"`
CoverageRefs []string `json:"coverage_refs"`
}
func (Signal) MarshalJSON ¶ added in v0.4.0
type SignalsWithheld ¶ added in v0.10.0
type SignalsWithheld struct {
MinSeverity Severity `json:"min_severity,omitempty"`
BelowMinSeverity int `json:"below_min_severity"`
Top int `json:"top,omitempty"`
BeyondTop int `json:"beyond_top"`
}
SignalsWithheld records what a narrowed view of a Report left out, so a shortened signals list is never mistaken for a smaller analysis. It is nil on an unnarrowed Report. A narrowing is in effect when its identifying field is set: MinSeverity for the severity floor, Top for the cap; a zero count next to a set identifier is still reported.
It describes presentation narrowing only: Summary and Coverage keep describing the full analysis. An analysis-level filter (suppression, vendor exclusion) changes what was analyzed, so it must change Summary and Coverage and shall not reuse this record.
func (SignalsWithheld) MarshalJSON ¶ added in v0.10.0
func (w SignalsWithheld) MarshalJSON() ([]byte, error)
MarshalJSON emits each narrowing's pair of fields only while that narrowing is in effect, so a cap-only view carries no floor fields and vice versa. A record that names no narrowing, counts withheld signals for one it does not name, names a floor outside the severity vocabulary, or holds a negative cap or count, is an error: Narrow cannot produce it, and encoded it would drop or misstate what the view withheld.
type Summary ¶
type Summary struct {
FilesAnalyzed int `json:"files_analyzed"`
FilesWithDiagnostics int `json:"files_with_diagnostics"`
// FilesUnanalyzed counts distinct diagnostic paths that never became
// an analyzed FileChange. Zero is omitted so unchanged ranges stay
// byte-identical.
FilesUnanalyzed int `json:"files_unanalyzed,omitempty"`
ActiveSignals int `json:"active_signals"`
IntroducedSignals int `json:"introduced_signals"`
ExistingSignals int `json:"existing_signals"`
ResolvedSignals int `json:"resolved_signals"`
BaselineSignals int `json:"baseline_signals"`
UnknownSignals int `json:"unknown_signals"`
}
Source Files
¶
- changed_ranges.go
- codesignal.go
- coverage_types.go
- diagnostics.go
- doc.go
- file_change.go
- file_signals.go
- fingerprint.go
- input.go
- lifecycle.go
- location_compare.go
- metric_rules.go
- options.go
- project_complete_no_match.go
- project_continuity.go
- project_coverage_clone.go
- project_coverage_complete.go
- project_coverage_mapping.go
- project_fact_order.go
- project_facts_reachability.go
- project_fingerprint.go
- project_lifecycle.go
- project_lifecycle_state.go
- project_model_coverage_diagnostics.go
- project_order.go
- project_path_step_order.go
- project_provenance.go
- project_report.go
- project_report_surface.go
- project_scope_report.go
- registry.go
- report.go
- report_assembly.go
- rule_branch_density.go
- rule_cognitive_complexity.go
- rule_constructor_density.go
- rule_deep_relative_import.go
- rule_hidden_input_mutation.go
- rule_layer_bypass.go
- rule_layer_bypass_path.go
- rule_layer_violation.go
- rule_layer_violation_go_edges.go
- rule_layer_violation_match.go
- rule_layer_violation_ts_edges.go
- rule_max_nesting_depth.go
- rule_pointer_return_density.go
- rule_react_orchestration.go
- rule_tight_constructor_init.go
- rule_toctou_check_then_act.go
- severity.go
- signal_key.go
- signal_rank.go
- signal_summary.go
- signal_view.go
- signals_withheld.go
- sort.go
- string_slice_order.go