Skip to content

fix(todo.brownfield-contract-pointer): declare the contracts brownfield writes - #481

Merged
George-RD merged 1 commit into
mainfrom
loop/todo.brownfield-contract-pointer
Jul 26, 2026
Merged

fix(todo.brownfield-contract-pointer): declare the contracts brownfield writes#481
George-RD merged 1 commit into
mainfrom
loop/todo.brownfield-contract-pointer

Conversation

@George-RD

Copy link
Copy Markdown
Collaborator

Problem

cairn init --from-code followed by cairn change apply brownfield-init produced a map that immediately failed cairn scan: one CAIRN_CONTRACT_LEAF_UNCOVERED finding per discovered node, on a map cairn generated itself.

The contract artefacts were not missing. write_change emits meta/changes/<id>/contracts/<id>.md, and parse_artefact_operations promotes it to meta/contracts/<id>.md in the same apply step (src/changes/artefact_ops.rs:74, root.join("meta").join(relative)). The node block in the emitted delta simply carried no contract pointer, so the coverage gate reported the artefact absent.

Change

  • blueprint_delta emits contract "./meta/contracts/<id>.md" directly after the existing path line, matching hand-authored field order.
  • The filename is single-sourced in a new private contract_file_name; the change-directory writer (src/brownfield/mod.rs) and src/brownfield/refine.rs previously each inlined format!("{}.md", id.replace('.', "_")). Zero remaining copies.
  • Refine inherits the pointer with no second edit: blueprint_delta_with_renames delegates to super::blueprint_delta. run_refine filters out already-declared paths, so an emitted pointer can never overwrite a hand-authored one.
  • Not the @no-contract tag: the contract file genuinely exists, the pointer is the missing half.

map.json is the snapshot cairn scan regenerates. The two span shifts are write_change and blueprint_delta moving down thirteen lines. Same class of resync as #477.

Tests

Three, all verified failing before the fix and passing after:

  • test_blueprint_delta_emits_contract_pointer: the wire form.
  • test_contract_pointer_target_matches_written_contract_file: anti-drift, pins the delta pointer to the file write_change actually wrote.
  • test_init__archived_map_declares_contracts_for_every_leaf: end to end, init plus archive plus scan yields zero CAIRN_CONTRACT_LEAF_UNCOVERED.

Verification

scripts/pre-archive-rust-gates.sh exit 0. cairn scan --strict exit 0 at the pre-existing baseline (one deferred finding). cairn hook all pass.

End to end on a throwaway repo (two Python packages, no prior cairn state):

$ grep -n contract cairn.blueprint
11:    contract "./meta/contracts/pkg.md"
15:    contract "./meta/contracts/pkg_sub.md"
$ cairn scan
Blueprint reconciled cleanly. No findings.
exit=0

Before this change the same sequence printed two CAIRN_CONTRACT_LEAF_UNCOVERED warnings and exited 1.

Out of scope

The remaining CAIRN_ORDER_CYCLE finding on nested-package brownfield output is filed as todo.brownfield-parent-package-cycle, with the three verified facts that block the obvious fix recorded so the next session does not re-derive them. It needs a decision on how brownfield models parent packages plus delta-pipeline work, which does not fit this unit's sizing.

…ld writes

`cairn init --from-code` followed by `cairn change apply brownfield-init`
produced a map that immediately failed `cairn scan` with one
CAIRN_CONTRACT_LEAF_UNCOVERED finding per discovered node. The contract
artefacts were not missing: `write_change` emits
meta/changes/<id>/contracts/<id>.md and `parse_artefact_operations` promotes it
to meta/contracts/<id>.md in the same apply step. The emitted node block simply
carried no `contract` pointer, so the coverage gate reported the artefact
absent.

`blueprint_delta` now emits `contract "./meta/contracts/<id>.md"` alongside the
existing `path` line, and the filename is single-sourced in `contract_file_name`
rather than derived independently by the change-directory writer and the delta
emitter. Refine inherits the pointer through `blueprint_delta_with_renames`.

Verified end to end on a throwaway repo: two discovered packages now emit their
contract pointers and `cairn scan` exits 0 where it previously reported two
warnings and exited 1.

map.json is the snapshot `cairn scan` regenerates; the two span shifts are the
new helpers moving `write_change` and `blueprint_delta` down thirteen lines.

The remaining CAIRN_ORDER_CYCLE finding on nested-package brownfield output is
out of scope and filed as todo.brownfield-parent-package-cycle, with the three
facts that block the obvious fix recorded so the next session starts from them.
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 146130f5-f409-4606-9e1e-552fffe03d05

📥 Commits

Reviewing files that changed from the base of the PR and between 6a97fc3 and fda2fa2.

📒 Files selected for processing (6)
  • map.json
  • meta/todos/todo.brownfield-contract-pointer.md
  • meta/todos/todo.brownfield-parent-package-cycle.md
  • src/brownfield/mod.rs
  • src/brownfield/refine.rs
  • tests/phase_9_brownfield.rs

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Brownfield-generated blueprint entries now include contract references, preventing uncovered contract findings during scans.
    • Contract filenames are kept consistent across brownfield initialization and refinement workflows.
  • Tests

    • Added coverage confirming every discovered leaf has a corresponding contract reference.
    • Added validation that generated contract references match the written contract files.
  • Documentation

    • Added planning notes for addressing brownfield contract coverage and package dependency cycles.

Walkthrough

Brownfield initialization and refinement now centralize contract filenames, emit contract pointers in blueprint deltas, and verify those pointers against generated files and scanner results. Related TODOs document contract coverage and parent-package cycle issues, while symbol metadata spans are updated.

Changes

Brownfield contract coverage

Layer / File(s) Summary
Centralized contract pointer generation
src/brownfield/mod.rs, src/brownfield/refine.rs
Shared helpers generate contract filenames and blueprint pointers for initialization and refinement outputs.
Contract pointer validation
src/brownfield/mod.rs, tests/phase_9_brownfield.rs
Tests verify pointer paths match written contract files and that archived brownfield maps have no uncovered contract leaves.
Brownfield metadata and issue tracking
map.json, meta/todos/*
Symbol spans are updated, and TODOs document contract-pointer and parent-package-cycle findings with acceptance criteria.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant run_init_from_code
  participant blueprint_delta
  participant contracts_directory
  participant scanner
  run_init_from_code->>blueprint_delta: generate node declarations with contract pointers
  blueprint_delta->>contracts_directory: write matching contract stubs
  scanner->>blueprint_delta: read archived blueprint
  scanner->>contracts_directory: resolve contract pointers
Loading

Poem

A bunny found contracts tucked in a row,
With pointers to each stub below.
The blueprint now knows where files hide,
And scanners hop with leaves supplied.
No uncovered carrots—what a stride! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: emitting brownfield contract pointers for written contracts.
Description check ✅ Passed The description accurately explains the contract pointer fix, tests, verification, and out-of-scope cycle issue.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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 loop/todo.brownfield-contract-pointer

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.

@George-RD
George-RD merged commit 73acbfb into main Jul 26, 2026
15 checks passed
@George-RD
George-RD deleted the loop/todo.brownfield-contract-pointer branch July 26, 2026 19:47
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