Skip to content

feat(verify): C4 import-aware dependency binding#17

Merged
ajaysurya1221 merged 1 commit into
mainfrom
feature/c4-import-binding
Jun 19, 2026
Merged

feat(verify): C4 import-aware dependency binding#17
ajaysurya1221 merged 1 commit into
mainfrom
feature/c4-import-binding

Conversation

@ajaysurya1221

@ajaysurya1221 ajaysurya1221 commented Jun 19, 2026

Copy link
Copy Markdown
Owner

Summary

Closes the silent C4 revalidation skip: a pytest:<nodeid> checker proves behavior when it runs, but its sealed watch was only the test file — so an edit to the implementation the test imports could be silently skipped at revalidation when the claim names no uniquely indexed symbol. This is a re-check trigger gap, not a truth gap, and that framing is preserved end to end.

dorian verify / dorian rebind now statically resolve (stdlib ast, read-only — no import execution, no sys.path mutation, no package introspection, no network) the repo-local .py files a C4 test imports, and add them to the claim's watch + auto-captured (hashed, scope-linted) read-set. A source edit then re-runs the existing C4 checker — the test still decides truth; a file change never marks a claim BROKEN by itself.

What's in it

  • src/dorian/test_deps.py — the static resolver. Binds only an unambiguous repo-local import (exactly one tracked file); stdlib imports are skipped via the interpreter module-name table; symlinks are not followed; ambiguous / zero matches are skipped, not guessed.
  • bindings.py — splits program-named vs checker-exercised files so a widened C4 watch is not flagged trigger-only-symbol (and --binding-gate=fail still seals a good behavior claim).
  • bind-suggest — content-free bind (test-dep) provenance.
  • dorian bench c4-import-binding — deterministic, known-truth: test-file-only watcher selection recall 0.0 → 1.0 for direct-import impl edits, ambiguous selected 0, alarm match 2/2, false BROKEN from a behavior-preserving edit 0.
  • Docs: spec/checkers.md, README.md, docs/SECURITY_BOUNDARY.md, docs/V1_SCOPE.md, CHANGELOG.md ([Unreleased]).

Invariants preserved

No .warrant schema, checker-grammar, public exit-code, fold-policy, or trust change. No new runtime dependency. revalidate stays import-blind (the widened watch is baked into the sidecar at seal/rebind). --deny-exec on a selected C4 → ERRORED/exit 5 (never PASS/BROKEN). checker-source=base unchanged — the widened watch affects selection only, never which spec source executes; it is a trust root, not a sandbox.

Verification

  • uv run pytest919 passed (exit 0)
  • uv run ruff check src tests bench → clean
  • uv run ruff format --check src tests bench → clean
  • uv run dorian bench c4-import-binding → deterministic, run_id 6fdcffa9b15aaa26

Release scope

This lands as a feature at version 1.1.1 with CHANGELOG [Unreleased]no version bump, tag, or publish (README latest: / action@ refs stay true at v1.1.1, so no dangling public claims). Cutting v1.2.0 is a separate dedicated release commit. Old warrants gain the wider watches via dorian rebind <artifact>.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • C4 behavior claims backed by pytest tests now automatically watch imported implementation files, triggering re-checks when those files change.
  • Documentation

    • Updated documentation and specification for C4 import-aware binding capabilities.
  • Tests

    • Added comprehensive test suites validating C4 import-aware dependency binding and benchmark functionality.

A pytest:<nodeid> checker proves behavior when it runs, but its sealed watch
was only the test file — so an edit to the implementation the test imports
could be silently skipped at revalidation when the claim names no uniquely
indexed symbol (a re-check TRIGGER gap, not a truth gap).

`dorian verify`/`rebind` now statically resolve (stdlib `ast`, read-only — no
import execution, sys.path mutation, package introspection, or network) the
repo-local .py files a C4 test imports and add them to the claim's watch and
auto-captured read-set. A source edit then re-runs the existing C4 checker;
the test still decides truth (a file change never marks a claim BROKEN by
itself). stdlib imports are skipped via the interpreter module-name table,
symlinks are not followed, and ambiguous/zero matches are skipped, not guessed.

- new src/dorian/test_deps.py resolver (no runtime dependency)
- bindings: split program-named vs checker-exercised files so a widened C4
  watch is not flagged trigger-only (and --binding-gate=fail still seals it)
- bind-suggest: content-free test-dep provenance
- dorian bench c4-import-binding (deterministic; selection recall 0.0 -> 1.0)
- docs: spec/checkers, README, SECURITY_BOUNDARY, V1_SCOPE, CHANGELOG [Unreleased]

No warrant-schema, checker-grammar, exit-code, fold-policy, or trust change.
Trigger widening only; not a sandbox. Rebind old warrants to gain the wider
watches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ajaysurya1221 ajaysurya1221 merged commit 6838e62 into main Jun 19, 2026
4 of 5 checks passed
@ajaysurya1221 ajaysurya1221 deleted the feature/c4-import-binding branch June 19, 2026 15:27
@coderabbitai

coderabbitai Bot commented Jun 19, 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: 80a79d2a-13f6-4bac-8f5d-263e8a0736f0

📥 Commits

Reviewing files that changed from the base of the PR and between 27037d0 and cb051b1.

📒 Files selected for processing (12)
  • .gitignore
  • CHANGELOG.md
  • README.md
  • bench/c4_import_binding.py
  • docs/SECURITY_BOUNDARY.md
  • docs/V1_SCOPE.md
  • spec/checkers.md
  • src/dorian/bindings.py
  • src/dorian/commands.py
  • src/dorian/test_deps.py
  • tests/test_c4_import_binding.py
  • tests/test_c4_import_binding_bench.py

📝 Walkthrough

Walkthrough

Adds C4 import-aware dependency binding to dorian: a new test_deps.py module statically resolves Python imports from pytest: test files using stdlib ast (no execution) and widens the claim re-check watch set to include imported implementation files. This is wired into verify, bind-suggest, and rebind commands, the trigger-only-symbol diagnostic in bindings.py, a new deterministic benchmark, comprehensive tests, and documentation updates.

Changes

C4 Import-Aware Dependency Binding

Layer / File(s) Summary
Static import resolver
src/dorian/test_deps.py
New module: BFS AST-based resolution of tracked repo-local Python imports (python_import_dependencies, c4_dependency_watch_paths, merge_watch_maps), with ambiguity skipping, stdlib exclusion, symlink safety, and size guards.
Command wiring: verify, bind-suggest, rebind
src/dorian/commands.py
cmd_verify and cmd_rebind merge C4 import-derived watch maps with symbol-definer watches; cmd_bind_suggest adds bind_test_deps provenance; benchmark dispatch gains c4-import-binding entry.
Bindings trigger-only-symbol diagnostic
src/dorian/bindings.py
analyze_candidate switches from _checker_named_files to new _checker_exercised_files (which adds C4 import deps) so widened watches are not misclassified as spurious triggers.
Benchmark suite
bench/c4_import_binding.py
New deterministic benchmark with selection-layer recall scenarios and verdict-layer BROKEN/VERIFIED/ERRORED outcomes; forbidden-word guard; JSON/markdown/JSONL outputs; run_benchmark() and main() entrypoints.
Unit and integration tests
tests/test_c4_import_binding.py
Unit tests for all test_deps edge cases plus slow integration tests for watch widening, revalidation triggers, deny-exec, scope lint, bindings diagnostic, --binding-gate=fail, bind-suggest, rebind, and trusted-base mode.
Benchmark integration tests
tests/test_c4_import_binding_bench.py
Slow tests asserting schema, recall values, alarm correctness, deterministic reruns, forbidden-word absence, and content-free resolved_deps records.
Spec, docs, changelog, gitignore
spec/checkers.md, docs/SECURITY_BOUNDARY.md, docs/V1_SCOPE.md, README.md, CHANGELOG.md, .gitignore
C4 grammar updated for import-aware derived watch; security boundary and V1 scope documented; README command surface and roadmap revised; CHANGELOG Added/Changed entries added; generated report gitignored.

Sequence Diagram(s)

sequenceDiagram
    rect rgba(70, 130, 180, 0.5)
        Note over cmd_verify,seal_artifact: verify / rebind path
    end
    participant cmd_verify
    participant claim_watch_paths
    participant c4_dependency_watch_paths
    participant merge_watch_maps
    participant seal_artifact

    cmd_verify->>claim_watch_paths: claims, repo
    claim_watch_paths-->>cmd_verify: symbol_watch_map
    cmd_verify->>c4_dependency_watch_paths: repo, claims
    c4_dependency_watch_paths-->>cmd_verify: c4_watch_map
    cmd_verify->>merge_watch_maps: symbol_watch_map, c4_watch_map
    merge_watch_maps-->>cmd_verify: merged symbol_watch
    cmd_verify->>seal_artifact: extra_watch=merged symbol_watch

    rect rgba(180, 100, 50, 0.5)
        Note over analyze_candidate,_checker_exercised_files: bindings diagnostic path
    end
    participant analyze_candidate
    participant _checker_exercised_files
    participant python_import_dependencies

    analyze_candidate->>_checker_exercised_files: repo, claim, entry_uris
    _checker_exercised_files->>python_import_dependencies: repo, test_file
    python_import_dependencies-->>_checker_exercised_files: import deps
    _checker_exercised_files-->>analyze_candidate: exercised file set
    Note over analyze_candidate: trigger-only-symbol check uses exercised set
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ajaysurya1221/dorian#4: This PR directly extends the binding lifecycle changes from that PR by updating bindings.py's trigger-only-symbol diagnostic to compare against C4 import-exercised files and plumbing merged watch coverage through commands.py.
  • ajaysurya1221/dorian#3: Both PRs modify cmd_verify's watch/read-set wiring in src/dorian/commands.py; this PR extends that path to merge in C4 test-import-derived watch paths via seal_artifact(extra_watch).
  • ajaysurya1221/dorian#1: Both PRs modify the _BENCH_DISPATCH variable in src/dorian/commands.py to add dorian bench subcommands at the same code site.

Poem

🐇 Hoppity-hop through the AST tree,
Parsing imports without running free—
No sys.path tricks, no network call,
Just static reads to catch them all!
When implementation shifts and slides,
The widened watch re-runs with pride. 🌿

✨ 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 feature/c4-import-binding

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

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.

2 participants