Repository navigation
Change maxRuns without rerunning a started node - #129
Merged
Merged
Conversation
Epsirom
added a commit
that referenced
this pull request
Oct 25, 2026
… new cycle (#127) Closes #114. Part of RSI Mode (#118). Builds on #128, where `maxRuns` replaced edge limits. ## What changes - **Validation accepts any cycle.** Unconditional, nested, and overlapping cycles, cycles with several entries or exits from any node, and decisions without an exit choice are no longer rejected. - **Closing edges only decide where each round starts.** Braid picks them per strongly connected part: it keeps the other edges as ordinary dependencies, and an edge that would complete a cycle closes it instead. Preference for closing: edges into an entry (a node an outside edge enters), then a decision's choice edges, then edges back to nodes listed earlier. Graphs accepted before keep their closing edge, except a rare cycle without an entry where a decision inside it has a choice edge back to an earlier-listed node; its round start can move. That is acceptable because the cycle rules are unreleased since 0.5; `docs/compatibility.md` notes it. `closingEdges(graph)` returns them all. - **Exits per round.** Edges that leave a cycle wait while any of its nodes reruns. For a cycle closed by a decision's choice edge they still wait for the final round. For an unconditional closing edge they fire in every round: downstream nodes outside the cycle run with each finished round (inactive ones wait for a later round). Round clones are created at the end of the scheduling pass, so exits are admitted before the next round takes the slots; #128's `maxRuns` check still applies when a clone is admitted. - **Overlapping cycles** that reach a shared node together merge: the first closing edge clones it, the second attaches to the clone as another input. - **Bounds.** Cycles are bounded by `maxRuns` on their nodes (#128): total runs, never reset per round of an enclosing cycle (tested and documented). - **Cycle notices.** Each submission or update that creates cycles emits `cycles_created` with each new cycle (`GraphCycle`: `nodeIds` starting where its rounds start, `edges` ending with its closing edge, `stops` = the decision choice edges on it, `limitedNodeIds` = its nodes with a finite `maxRuns`; at most 20, with `truncated`). `newCycles(graph, previous?)` computes the same list. Pi and DSH `braid` / `braid_update` results show it, and flag a cycle with nothing that stops or bounds it, so an accidental `test → fix` next to `fix → test` is noticed. - Pi and DSH tool descriptions, guidance, and READMEs describe the new rules. Pi's `display.ts` gets only the event-text case the exhaustive switch requires. ## Docs `docs/execution-control.md` (Cycles, Cycle notices), README graph schema and out-of-scope list, ROADMAP (#114 checked, scope row), and a 0.6 migration subsection in `docs/compatibility.md`. ## Compatibility Not labelled breaking: existing callers need no changes. TypeScript code with an exhaustive `switch` over `ExecutionEvent` needs a case for `cycles_created`. ## Decided: `maxRuns` never resets `maxRuns` is the most runs a lineage can reach, including in a nested cycle across rounds of the enclosing one; it does not reset per round. The owner raises or lowers it by updating the node; since #129, an upsert that only changes `maxRuns` keeps a started head instead of replacing it. ## Tests New `test/cycles.test.ts` covers: - an unconditional cycle with an exit that runs each round, ended at `maxRuns` - a nested cycle, and `maxRuns` counting across outer rounds - overlapping cycles merging at a shared node - cycle reports for submissions and updates, and the report cap Validation and closing-edge tests are updated, and Pi and DSH tests cover the notices. `npm run verify` passes on `main` with #128 and #129 (core 309, Pi 195, DSH 69, package smoke).
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.
Follow-up to #128. Part of RSI Mode (#118).
maxRunsis the most runs a node's lineage can reach, and it never resets, including per round of an enclosing cycle (decided in #127). The owner adjusts it by updating the node. Before this change, that worked only while a rerun was waiting at the limit. On a running or settled head, any upsert replaced it: raisingmaxRunsahead of time cancelled a running execution and reran it, and reran a settled one.What changes
maxRunskeeps a started head. A running head keeps running, and a settled one keeps its result and any hold. Later reruns (clones) use the new limit, so the limit can be raised or lowered at any time.nodekeeps the definition it ran with;snapshot().graphshows the newmaxRuns.docs/execution-control.md(live updates, limits),GraphUpdate.upsertNodesdoc,docs/compatibility.md, and the Pi/DSH READMEs and tool descriptions (maxRuns,braid_update).Tests
test/limits.test.tscovers:maxRunswhile the head runs: no cancellation, and later reruns stop at the new limitmaxRunson a settled, held head: no replacement, and the hold is keptnpm run verifypasses (core 305, Pi 194, DSH 68, package smoke).Overlap with #127
#127 edits the cycle paragraphs of the same READMEs and docs. This PR puts its sentences elsewhere to avoid conflicts, but whichever merges second may need a trivial rebase.