Add future_with_report() for explicit negation-resolution audit - #294
Merged
Conversation
A leftover literal `no ...` line was the only way a caller could detect that a change contained a negation that did not apply cleanly in future() output, forcing change-validation pipelines to grep the render. HConfig.future_with_report() returns the same prediction together with a frozen FutureReport of unresolved negations and persisting idempotency-tracked negation replacements, so pipelines can assert `not report.unresolved_negations` instead. FutureReport is a frozen slotted dataclass rather than a Pydantic model because it holds HConfigChild nodes (plain slotted classes) and the project convention forbids arbitrary_types_allowed. Closes #285
Both methods carried the same construct-compute-prune pipeline, so a change to one had to be mirrored in the other. Delegating leaves one code path; the discarded report costs one small builder allocation per call.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements #285 (follow-on to #269). Targets
nextfor v4.0.0.future()resolves negations in explicit tiers (exact match → idempotency replace → shorthand prefix → keep-as-signal), but a leftover literalno ...line was the only way a caller could detect a negation that did not apply cleanly — change-validation pipelines had to grep the render fornolines.HConfig.future_with_report(config, *, prune_empty_branches=False)returnstuple[HConfig, FutureReport];future()is byte-identical (no overloads or union returns under strict typing).FutureReport(exported fromhier_config) is a frozen slotted dataclass:unresolved_negations— negations that matched nothing in the running config (the keep-as-signal tier)idempotency_replacements— negation-form lines that displaced an idempotency-tracked line but persist in the render (e.g. IOSno logging console); positive-form idempotent value updates are normal changes and are excludedHConfigChildnodes living in the returned future tree, sopath()/lineage()give context. A dataclass rather than a Pydantic model becauseHConfigChildis a plain slotted class and the repo convention forbidsarbitrary_types_allowed._FutureReportBuilderthrough thecompute_futurerecursion via a keyword-only parameter;compute_future_with_report()keeps the builder private totree_algorithms.prune_empty_branches=True: pruning only deletes childless nodes whose running-config counterpart had children, which cannot match a kept negation or a persisting replacement (covered by test).Testing
TDD: 8 new integration tests written first (failed on missing import), covering unresolved detection with lineage, clean-change empty report, idempotency-replacement identity with the rendered node, positive-form exclusion, accumulation across recursed sections, pruning interaction, render identity with
future(), and report immutability.poetry run ./scripts/build.py lint-and-testexits 0 (757 passed, coverage 97.08%)poetry run mkdocs build --strictpassesDocs & changelog
docs/user/future-config.md— new "Auditing negation resolution" section, cross-linked from the unmatched-negations bulletdocs/dev/api-reference.md—FutureReportin the Reporting groupdocs/user/migrating-from-v3.md— "New in v4" bulletCHANGELOG.md— Unreleased → Added (Unresolved-negation report for future() #285)Closes #285