Skip to content

feat(refs): propagate hub staleness across refs (#4)#149

Merged
Connorrmcd6 merged 2 commits into
mainfrom
feat/4-refs-composition-pr2
Jun 29, 2026
Merged

feat(refs): propagate hub staleness across refs (#4)#149
Connorrmcd6 merged 2 commits into
mainfrom
feat/4-refs-composition-pr2

Conversation

@Connorrmcd6

Copy link
Copy Markdown
Owner

Summary

Second and final stage of refs hub composition (PR1 #148 shipped the validated graph; this turns on propagation, completing #4). surf check now propagates staleness one hop: a hub that directly references a stale hub — or a stale claim within one, via > symbol — inherits a ReferencedStale divergence and fails the gate. The signal that flags a dependency now flags everything composed on top of it.

What changed and why

  • surf-core/report.rs — new DivergenceKind::ReferencedStale variant (serializes as referenced_stale); detail doc broadened. Additive to the v1 JSON contract.
  • surf-cli/check.rscheck_workspace builds a stale set during the per-claim walk (hub → diverged-claim anchor paths), then propagate_refs walks every hub's refs and emits a ReferencedStale divergence when a ref resolves to a stale target. Whole-hub refs fire on any divergence in the target; claim-level refs (> symbol) match the specific diverged claim by anchor-segment suffix, so a ref to a still-clean sibling stays green. print_human gained a REF-STALE line.

One-hop by construction

The stale set is built only from base per-claim divergences, never from other propagated ones, so a chain A → B → C does not cascade — exactly the bounded behavior the §9.3 unlock discipline calls for.

Dogfood surfaced itself

This change to check_workspace diverged its own claim in cli-check.md, which propagated REF-STALE to the two hubs that ref it (cli-workspace.md, hub-format.md). Re-sealed after updating the claim prose to document the new behavior — the feature catching its own drift.

Verification

All run on this branch:

  • cargo fmt --all --check — clean
  • cargo clippy --all-targets --all-features -- -D warnings — clean
  • cargo test --all233 passed, 0 failed (2 pre-existing #[ignore]), incl. 4 new propagation tests (ref_to_stale_hub_propagates, ref_to_clean_hub_does_not_propagate, claim_level_ref_targets_the_named_claim, propagation_is_one_hop)
  • Dogfood: surf lint → 0 errors, surf check → all anchored spans match

Try it

From the repo root after cargo build:

SURF="$(pwd)/target/debug/surf"; D="$(mktemp -d)/d"; mkdir -p "$D/src" "$D/hubs"; cd "$D"
printf 'hubs = ["hubs/*.md"]\n' > surf.toml
printf 'pub fn rotate(token: &str) -> String { format!("rotated:{token}") }\n' > src/auth.rs
printf -- '---\nsummary: token rotation\nanchors:\n  - claim: rotate returns a rotated token\n    at: src/auth.rs > rotate\n---\n# Auth\n' > hubs/auth.md
printf -- '---\nsummary: onboarding, builds on auth\nrefs:\n  - ./auth.md\n---\n# Onboarding\n' > hubs/onboarding.md
"$SURF" verify && "$SURF" check          # green
printf 'pub fn rotate(token: &str) -> String { format!("V2:{token}:{}", token.len()) }\n' > src/auth.rs
"$SURF" check                            # auth.md DIVERGED + onboarding.md REF-STALE

Closes #4

🤖 Generated with Claude Code

Connorrmcd6 and others added 2 commits June 29, 2026 11:33
Second and final stage of refs hub composition (PR1, #148, shipped the
validated graph). `surf check` now propagates staleness one hop: a hub
that directly references a stale hub — or a stale claim within one, via
`> symbol` — inherits a `ReferencedStale` divergence and fails the gate.
The signal that flags a dependency now flags everything composed on it.

Propagation is one-hop by construction: the stale set is built only from
base per-claim divergences, never from other propagated ones, so a chain
A → B → C does not cascade. Claim-level refs match the specific diverged
claim by anchor-segment suffix, so a ref to a still-clean sibling claim
stays green.

Dogfood surfaced itself: this change to `check_workspace` diverged its
own claim in cli-check.md, which propagated REF-STALE to the two hubs
that ref it — re-sealed after documenting the new behavior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Connorrmcd6 Connorrmcd6 merged commit e8a5176 into main Jun 29, 2026
4 checks passed
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.

refs: hub composition

1 participant