Skip to content

feat(impact): add deterministic blast-radius library - #26

Merged
TheHalfMoon merged 9 commits into
mainfrom
impl/cf12-impact-library
Aug 26, 2026
Merged

feat(impact): add deterministic blast-radius library#26
TheHalfMoon merged 9 commits into
mainfrom
impl/cf12-impact-library

Conversation

@TheHalfMoon

@TheHalfMoon TheHalfMoon commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Stack

CF-12 implementation Stack A for tasks T010-T018.

Base: canonical CF-12 planning merge cefa5e4a56041bf88e833844a318b170e7e7ae83.

Summary

Add the library-owned deterministic impact-analysis contract and traversal engine without shipping the CLI yet.

Changes

  • add CF-12 impact report schema v1;
  • adapt existing structural-diff evidence into canonical added/removed/modified change seeds;
  • treat canonical URL changes as removed-old + added-new identity rather than silently carrying identity across URLs;
  • reverse-traverse only exact CF-11G resolved canonical-reference edges;
  • preserve external and ambiguous edges as explicit unresolved boundaries without traversing them;
  • compute deterministic transitive artifact exposure with cycle termination;
  • select canonical shortest evidence paths with lexicographic equal-length tie-breaking;
  • compute exact version-aware reverse package exposure from schema-v2 dependency edges;
  • preserve before/after side evidence and normalize to both only for exact identical relations;
  • carry Context Graph extraction coverage and exact package source/digest evidence into the report;
  • add focused contract tests for direct/transitive/cyclic reachability, equal-length ties, add/remove canonical seeds, canonical URL identity changes, multi-version package exposure, unresolved boundaries, and byte determinism.

Authority boundary

This PR does not:

  • add commandf impact CLI yet;
  • change CF-03/04/05 compatibility semantics;
  • infer BREAKING/RISKY/ADDITIVE from reachability;
  • traverse external/ambiguous graph targets as resolved;
  • add network lookup, graph database, vector/model/agent authority;
  • change lock schema;
  • change CF-06 / HL7 production identity;
  • modify the frozen CF-10 corpus;
  • add a Rust dependency.

Required qualification

Keep Draft until the exact head passes mandatory workspace gates and all applicable repository workflows, and every substantive returned review finding is dispositioned.

Stack B will ship the user-visible CLI and cf12-impact-proof only after this library contract is qualified.

Summary by CodeRabbit

  • New Features

    • Added impact analysis reports showing how changed resources affect related artifacts and packages.
    • Reports include before/after comparisons, dependency paths, graph evidence, coverage details, and unresolved references.
    • Added JSON export for impact reports.
    • Added clear error reporting for invalid schemas, missing or ambiguous entities, conflicting filenames, and inconsistent references.
  • Tests

    • Added coverage for dependency cycles, deterministic results, resource additions/removals, identity changes, and ambiguous references.

@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0856a433-0144-47f3-838f-36b78ea17280

📥 Commits

Reviewing files that changed from the base of the PR and between cefa5e4 and 9fa948c.

📒 Files selected for processing (5)
  • crates/commandf-pkg/src/impact.rs
  • crates/commandf-pkg/src/impact_error.rs
  • crates/commandf-pkg/src/impact_model.rs
  • crates/commandf-pkg/src/lib.rs
  • crates/commandf-pkg/tests/impact.rs

📝 Walkthrough

Walkthrough

This change adds impact report construction from structural diffs and before/after context graphs. It defines report models and errors, validates inputs, traces artifact and package impacts, records unresolved boundaries, normalizes results, and adds comprehensive tests.

Changes

Impact report

Layer / File(s) Summary
Impact models and errors
crates/commandf-pkg/src/impact_model.rs, crates/commandf-pkg/src/impact_error.rs
Defines serializable report structures, impact sides and seed kinds, schema versioning, JSON output, and structured validation errors.
Input validation and seed construction
crates/commandf-pkg/src/impact.rs
Validates schemas and lockfiles, resolves subject packages and artifacts, groups resource changes, and creates deterministic added, removed, and modified seeds.
Graph traversal and normalization
crates/commandf-pkg/src/impact.rs
Traverses reverse artifact references and package dependencies, selects deterministic paths, records unresolved boundaries, and merges before and after relations.
Public wiring and behavioral validation
crates/commandf-pkg/src/lib.rs, crates/commandf-pkg/tests/impact.rs
Exports the impact API and tests traversal, cycles, resource changes, identity changes, ambiguity handling, and deterministic JSON output.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant StructuralDiffReport
  participant ContextGraphReport
  participant build_impact_report
  participant ArtifactImpactTraversal
  participant PackageImpactTraversal
  participant ImpactReport
  StructuralDiffReport->>build_impact_report: provide structural changes
  ContextGraphReport->>build_impact_report: provide before and after graphs
  build_impact_report->>ArtifactImpactTraversal: trace artifact references
  ArtifactImpactTraversal->>PackageImpactTraversal: trace package dependencies
  PackageImpactTraversal->>build_impact_report: return package impacts
  ArtifactImpactTraversal->>build_impact_report: return artifact impacts and boundaries
  build_impact_report->>ImpactReport: assemble normalized report
Loading
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch impl/cf12-impact-library

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

ⓘ Your Qodo trial ends soon. Ask your workspace admin to set up billing to keep reviews running after the trial. Manage billing

@TheHalfMoon
TheHalfMoon marked this pull request as ready for review August 26, 2026 06:58

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@TheHalfMoon
TheHalfMoon merged commit d46591f into main Aug 26, 2026
6 of 7 checks passed
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add deterministic blast-radius impact analysis library

✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Defines schema-v1 impact reports from structural diffs and exact context evidence.
• Computes deterministic artifact and package exposure while preserving unresolved reference
 boundaries.
• Proves cycle safety, canonical identity handling, path tie-breaking, and byte stability.
Diagram

graph TD
  D["Structural diff"] --> V{"Inputs supported?"} --> S["Canonical seeds"] --> A["Artifact traversal"] --> N["Normalize sides"] --> R["Impact report"]
  G["Context graphs"] --> V
  S --> P["Package traversal"] --> N
  G --> A
  G --> P
Loading
High-Level Assessment

The custom ordered traversal is appropriate because the contract requires exact identity semantics, fail-closed reference handling, stable shortest-path tie-breaking, and byte-deterministic output. A generic graph dependency would add surface area without removing the domain-specific seed, boundary, and side-normalization logic.

Files changed (5) +1350 / -0

Enhancement (4) +859 / -0
impact.rsImplement deterministic impact traversal and report assembly +642/-0

Implement deterministic impact traversal and report assembly

• Builds canonical change seeds from structural diffs, validates exact before/after graph evidence, and reverse-traverses resolved artifact and package edges. It terminates cycles, selects canonical shortest paths, preserves unresolved boundaries, and normalizes only identical cross-side relations.

crates/commandf-pkg/src/impact.rs

impact_error.rsAdd fail-closed impact analysis errors +83/-0

Add fail-closed impact analysis errors

• Defines typed errors for unsupported schemas, missing or ambiguous subjects and artifacts, conflicting filenames, and inconsistent resolved references. Human-readable messages identify the affected evidence side.

crates/commandf-pkg/src/impact_error.rs

impact_model.rsDefine the impact report schema-v1 contract +124/-0

Define the impact report schema-v1 contract

• Adds serializable models for subjects, seeds, artifact and package paths, unresolved boundaries, evidence, coverage, and side attribution. Provides stable pretty-JSON byte serialization with a trailing newline.

crates/commandf-pkg/src/impact_model.rs

lib.rsExport the public impact analysis API +10/-0

Export the public impact analysis API

• Registers the impact implementation, model, and error modules and re-exports the report builder and schema types from the crate root.

crates/commandf-pkg/src/lib.rs

Tests (1) +491 / -0
impact.rsProve deterministic blast-radius invariants +491/-0

Prove deterministic blast-radius invariants

• Covers transitive and cyclic reachability, lexicographic shortest-path ties, add/remove and canonical URL identity changes, multi-version package exposure, unresolved boundaries, and byte-identical serialization.

crates/commandf-pkg/tests/impact.rs

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Identityless seeds are emitted 🐞 Bug ≡ Correctness
Description
When a canonical diff entry omits both optional filenames, build_seeds emits an ImpactSeed with
neither a before nor after artifact identity, so the reported change cannot be traversed or tied to
exact digest evidence. CF-12 requires missing required seed identity to fail closed (or be
explicitly marked unsupported), but this schema has no unsupported state and silently returns a
successful report.
Code

crates/commandf-pkg/src/impact.rs[R220-224]

+        match (before_canonical, after_canonical) {
+            (None, None) => {
+                if resource.kind == ResourceKeyKind::Canonical {
+                    push_seed_from_key(&mut seeds, &resource, &state, before, after);
+                }
Relevance

●● Moderate

Fail-closed on missing identity is plausible per team norms, but no exact precedent for this
seed-emission scenario.

PR-#21
PR-#2

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The diff model permits omitted filenames, artifact lookup returns None for them, and the changed
branch passes both absent identities into a normal seed. Traversal subsequently skips both sides,
contradicting the specification's exact-identity and fail-closed requirements.

crates/commandf-pkg/src/artifact_diff_model.rs[53-70]
crates/commandf-pkg/src/impact.rs[314-322]
crates/commandf-pkg/src/impact.rs[40-59]
specs/013-cf-12-impact/plan.md[70-76]
specs/013-cf-12-impact/spec.md[49-61]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Reject malformed structural-diff seed evidence instead of emitting a canonical seed with no exact artifact identity.

## Issue Context
StructuralDiffReport filenames are optional, and `artifact_for_filename` maps an absent filename to `None`. CF-12 requires missing required identity evidence to fail closed unless an explicit unsupported state is represented; the current model has no such state.

## Fix Focus Areas
- crates/commandf-pkg/src/impact.rs[174-265]
- crates/commandf-pkg/src/impact_error.rs[4-41]
- crates/commandf-pkg/tests/impact.rs[133-246]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Dangling edges create phantom impacts 🐞 Bug ≡ Correctness
Description
validate_inputs checks only schema numbers, then artifact and package traversal trusts edge
endpoint identities without verifying that they exist in the graph's node collections. A
schema-compatible graph with a dangling resolved source or dependency from endpoint therefore
produces an impact relation for a nonexistent artifact or package instead of failing closed.
Code

crates/commandf-pkg/src/impact.rs[R107-110]

+    for (side, graph) in [("before", before_graph), ("after", after_graph)] {
+        if graph.schema != ContextGraphReport::SCHEMA_V1 {
+            return Err(ImpactError::UnsupportedContextSchema {
+                side,
Relevance

●● Moderate

Plausible fail-closed gap on dangling edges, but no close accepted precedent confirms this exact
validation pattern.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The complete validator only checks schema fields. Both traversals then index and emit relations
directly from edge identities, while the canonical graph builder demonstrates that valid edges are
expected to resolve through known package/artifact nodes; malformed evidence is required to fail
closed.

crates/commandf-pkg/src/impact.rs[99-121]
crates/commandf-pkg/src/impact.rs[390-405]
crates/commandf-pkg/src/impact.rs[420-437]
crates/commandf-pkg/src/impact.rs[463-496]
crates/commandf-pkg/src/context.rs[50-77]
crates/commandf-pkg/src/context.rs[147-158]
specs/013-cf-12-impact/spec.md[46-49]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Validate Context Graph node and edge invariants before computing impact so dangling identities cannot become reported impacts.

## Issue Context
The context builder normally creates edges from known nodes, but `build_impact_report` is a public API accepting public, deserializable report structs. The CF-12 contract requires malformed required evidence to fail closed.

## Fix Focus Areas
- crates/commandf-pkg/src/impact.rs[99-121]
- crates/commandf-pkg/src/impact.rs[382-501]
- crates/commandf-pkg/src/impact_error.rs[4-41]
- crates/commandf-pkg/tests/impact.rs[9-330]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. build_impact_report errors untested 📘 Rule violation ▣ Testability
Description
The new public impact handler implements multiple explicit failure branches, but every added test
invokes it with valid inputs and unwraps success. Unsupported schemas, missing or ambiguous
subjects/artifacts, conflicting filenames, and inconsistent resolved references therefore have no
automated assertions for their error type or message.
Code

crates/commandf-pkg/src/impact.rs[R104-105]

+    if diff.schema != StructuralDiffReport::SCHEMA_V1 {
+        return Err(ImpactError::UnsupportedDiffSchema { found: diff.schema });
Relevance

●●● Strong

Accepted precedent favors testing explicit error/edge-case branches in business logic handlers.

PR-#10
PR-#21

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2717396 requires a test for each explicit business-logic failure branch. The new
implementation returns nine distinct ImpactError paths, while all repository calls from the added
impact test suite use .unwrap() on successful inputs and no impact test references an
ImpactError variant or calls unwrap_err()/is_err().

Rule 2717396: Test error and conflict branches in business logic handlers
crates/commandf-pkg/src/impact.rs[104-119]
crates/commandf-pkg/src/impact.rs[152-161]
crates/commandf-pkg/src/impact.rs[330-339]
crates/commandf-pkg/tests/impact.rs[69-92]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Add deterministic automated coverage for every explicit `ImpactError` branch returned by `build_impact_report`.

## Issue Context
The current impact tests exercise only successful report construction. Tests should force unsupported diff/context/lock schemas, missing and duplicated subject packages, missing and duplicated artifacts, conflicting resource filenames, and resolved references with a candidate count other than one, then assert the exact error variant and stable message.

## Fix Focus Areas
- crates/commandf-pkg/src/impact.rs[99-162]
- crates/commandf-pkg/src/impact.rs[292-340]
- crates/commandf-pkg/src/impact.rs[382-400]
- crates/commandf-pkg/tests/impact.rs[9-330]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 13 rules
Review mode: ⚖️ Balanced

Grey Divider

Tip of the day
💡 Did you know, you can start a comment with 'qodo' or '@qodo' to chat about any finding

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment on lines +104 to +105
if diff.schema != StructuralDiffReport::SCHEMA_V1 {
return Err(ImpactError::UnsupportedDiffSchema { found: diff.schema });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. build_impact_report errors untested 📘 Rule violation ▣ Testability

The new public impact handler implements multiple explicit failure branches, but every added test
invokes it with valid inputs and unwraps success. Unsupported schemas, missing or ambiguous
subjects/artifacts, conflicting filenames, and inconsistent resolved references therefore have no
automated assertions for their error type or message.
Agent Prompt
## Issue description
Add deterministic automated coverage for every explicit `ImpactError` branch returned by `build_impact_report`.

## Issue Context
The current impact tests exercise only successful report construction. Tests should force unsupported diff/context/lock schemas, missing and duplicated subject packages, missing and duplicated artifacts, conflicting resource filenames, and resolved references with a candidate count other than one, then assert the exact error variant and stable message.

## Fix Focus Areas
- crates/commandf-pkg/src/impact.rs[99-162]
- crates/commandf-pkg/src/impact.rs[292-340]
- crates/commandf-pkg/src/impact.rs[382-400]
- crates/commandf-pkg/tests/impact.rs[9-330]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +220 to +224
match (before_canonical, after_canonical) {
(None, None) => {
if resource.kind == ResourceKeyKind::Canonical {
push_seed_from_key(&mut seeds, &resource, &state, before, after);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Identityless seeds are emitted 🐞 Bug ≡ Correctness

When a canonical diff entry omits both optional filenames, build_seeds emits an ImpactSeed with
neither a before nor after artifact identity, so the reported change cannot be traversed or tied to
exact digest evidence. CF-12 requires missing required seed identity to fail closed (or be
explicitly marked unsupported), but this schema has no unsupported state and silently returns a
successful report.
Agent Prompt
## Issue description
Reject malformed structural-diff seed evidence instead of emitting a canonical seed with no exact artifact identity.

## Issue Context
StructuralDiffReport filenames are optional, and `artifact_for_filename` maps an absent filename to `None`. CF-12 requires missing required identity evidence to fail closed unless an explicit unsupported state is represented; the current model has no such state.

## Fix Focus Areas
- crates/commandf-pkg/src/impact.rs[174-265]
- crates/commandf-pkg/src/impact_error.rs[4-41]
- crates/commandf-pkg/tests/impact.rs[133-246]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +107 to +110
for (side, graph) in [("before", before_graph), ("after", after_graph)] {
if graph.schema != ContextGraphReport::SCHEMA_V1 {
return Err(ImpactError::UnsupportedContextSchema {
side,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Dangling edges create phantom impacts 🐞 Bug ≡ Correctness

validate_inputs checks only schema numbers, then artifact and package traversal trusts edge
endpoint identities without verifying that they exist in the graph's node collections. A
schema-compatible graph with a dangling resolved source or dependency from endpoint therefore
produces an impact relation for a nonexistent artifact or package instead of failing closed.
Agent Prompt
## Issue description
Validate Context Graph node and edge invariants before computing impact so dangling identities cannot become reported impacts.

## Issue Context
The context builder normally creates edges from known nodes, but `build_impact_report` is a public API accepting public, deserializable report structs. The CF-12 contract requires malformed required evidence to fail closed.

## Fix Focus Areas
- crates/commandf-pkg/src/impact.rs[99-121]
- crates/commandf-pkg/src/impact.rs[382-501]
- crates/commandf-pkg/src/impact_error.rs[4-41]
- crates/commandf-pkg/tests/impact.rs[9-330]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant