Skip to content

refactor(cfg): replace LoopContext wrapper with continue_stack - #317

Merged
jeremy-wayland merged 1 commit into
mainfrom
refactor/cfg-continue-stack-307
Aug 9, 2026
Merged

jeremy-wayland merged 1 commit into
mainfrom
refactor/cfg-continue-stack-307

Conversation

@jeremy-wayland

Copy link
Copy Markdown
Member

Closes #307

LoopContext was left holding a single field (continue_target: usize) once switch break handling moved to break_stack. This drops the wrapper and stores the loop header directly in continue_stack: Vec<usize>, so the break/continue state reads symmetrically at the CFGBuildState declaration.

Change

topos/engine/src/graphs/cfg/builder.rs only, 6 insertions / 13 deletions:

  • delete struct LoopContext
  • loop_stack: Vec<LoopContext> -> continue_stack: Vec<usize>
  • start_loop pushes header; finish_loop pops — same single push/pop pair as before
  • ContinueStmt reads continue_stack.last().copied()

No edge-contract change

Push and pop sites are unchanged in number and position, so stack depth stays balanced on every path. No edge kind, target, or ordering is touched — this is a pure representation change to the builder's own scratch state.

Verification

  • cargo test -p topos-engine graphs::cfg — 25 passed, 0 failed (includes preserves_pre_refactor_edge_contracts_across_supported_languages and finally_paths_keep_distinct_completions_and_frames)
  • cargo test -p topos-engine — 371 passed, 0 failed, 1 ignored
  • cargo clippy -p topos-engine --all-targets — clean
  • cargo fmt --all — no other files touched

finish_agent_contract was flagged in the same review but belongs with #233; deliberately untouched here.

🤖 Generated with Claude Code

After switch `break` handling moved to `break_stack`, `LoopContext` held
only `continue_target`. Drop the one-field struct and store the loop
header directly in `continue_stack: Vec<usize>`, so break and continue
state read symmetrically. No CFG behavior or edge-contract change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jeremy-wayland added a commit that referenced this pull request Aug 9, 2026
* docs: document squash-merge + Unreleased changelog convention

Records the repo git convention: main's history is a series of
squash-merged PRs, each carrying its own CHANGELOG [Unreleased] entry.
Release scope is decided after the work lands, and the release PR --
which renames [Unreleased] to a version heading -- comes last.

Explicitly rules out long-lived release branches that accumulate feature
PRs, superseding the v0.4.x stacked-PR-into-release-branch pattern.

Opens the [Unreleased] section and backfills entries for the four v0.6.0
fixes already in review (#317, #318, #319, #320), which were authored
before this convention existed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: scope PRs to one issue cluster, add stacked-PR rules

Stacking is for work review surfaced -- a required fix to a PR under
review, or a distinct issue found while reviewing it -- and stacks onto
the PR branch, never onto a release branch.

Documents the replant step (git rebase --onto main) that stacked-squash
divergence requires, and notes the cheaper default: if the parent has
not merged and the fix belongs to its issue, push another commit to the
parent instead of stacking.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: tighten PR scope, stacking test, and replant procedure

Scope a PR by coherent outcome -- reviewed, reverted, and explained as
one unit -- rather than by issue count, and make the PR title the
permanent squash subject.

Replace the "review surfaced it" test for stacking with the stricter
"child structurally depends on an unmerged parent"; discovery during
review is not itself a reason to stack. Bound stacks to two or three,
require the ordered stack in every description, and review bottom-up.

Correct the replant procedure: fetch and rebase onto origin/main rather
than a possibly stale local main, record each parent's old tip before
rebasing it, and move shallowest to deepest so every descendant lands on
its newly rebased parent. GitHub retargets a child only after the merged
head branch is deleted, and retargeting never rewrites commits -- always
rebase, inspect, and rerun CI.

Add the repository settings that enforce the convention instead of
relying on memory, and keep an empty [Unreleased] after each release.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jeremy-wayland
jeremy-wayland merged commit b43fd8a into main Aug 9, 2026
22 checks passed
@jeremy-wayland jeremy-wayland mentioned this pull request Aug 9, 2026
12 tasks
@jeremy-wayland
jeremy-wayland deleted the refactor/cfg-continue-stack-307 branch August 11, 2026 04:10
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.

Simplify residual CFG builder context wrappers

1 participant