Repository navigation
feat(projection): derived sequence fragments, message elements and view inverses - #23
Conversation
f29fc47 to
a80d26b
Compare
|
@codex security review |
1 similar comment
|
@codex security review |
a80d26b to
1a76962
Compare
|
@codex security review |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: 1a769620db
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
|
@codex security review |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: bd81eae3c7
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
6b046b7 to
ccd788e
Compare
|
@codex security review |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: ccd788e5ef
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
ed3da98 to
a60c68c
Compare
|
@codex security review |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: a60c68c739
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
|
@codex security review |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: f7c0f716d9
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
|
@codex security review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
5308dd5 to
37f6bb0
Compare
|
@codex security review |
37f6bb0 to
bdf73d2
Compare
|
@codex security review |
…asses Derived fragments walked and kept the whole reachable set of every forward branch to find where the branches meet, so a decision whose branches share one tail did work quadratic in the model. Where branches meet is now the decision's or fork's immediate post-dominator over forward transitions, found for every element in one dominator pass, and the scenario is read once: an alt or opt holds the messages from the branch taken until the path reaches that point, a par follows each branch taken from its fork, and a loop holds the messages inside its decision's component. Authored fragments are matched to messages through an index of their bodies, and placement marks the span each placed fragment covers, so no step scans the list of candidates or messages.
How many forward branches a decision or fork has, where they meet and whether a decision draws an opt are now found once per element before the path is read, rather than recomputed for every step that leaves it.
…n read Every chain copied its run of folded elements, so a long run of messages fanning out to many ends, or entered from many sources, cost the run's length once per chain. Each projection now indexes the folded elements once: their components are condensed, each component's reachable drawn elements are found in reverse topological order and shared along runs with nothing to add, and the elements entered from exactly one folded element form a forest recording the last trigger, effect and guard above each, so a single route's labels come from its two ends. A chain's transitions, through and joined guards, and an edge's label, are built only when read. The inverses match edges and transitions by their first transition and end, read from the projection's own record, and act on the steps from folded elements into an end once however many chains share them.
… by them A derived alt or opt listed every position it held, so decisions nested inside one another that all meet at the path's end kept positions quadratic in the nesting. An operand now holds either a run, by its ends, or a list, and fragments are compared and placed by the ends of their spans: a segment tree records when each placed fragment covers a node, and the innermost fragment at a position is the latest placement on its path to the root. No span is expanded into its positions, and which operand holds a position is a map lookup for listed positions and a binary search over runs.
The chain index kept a list of reachable targets for every folded component, copying its successor's list, so a comb of messages each with its own exit stored references quadratic in its length. A component now either takes over the list of a successor nothing else extends and prepends its own targets as cells, or points at its own targets and its successors' structures. The index stores one reference per cell, own target and successor, linear in the elements and transitions; duplicates are removed when a component's targets are first read, and the read is remembered.
…ry start A component whose own exits a later component already reached could not extend that list, so it fell back to a structure that every start walked again, and many starts into one run did work quadratic in its length. Each component's targets are now a list of cells holding each target once, shared with the components after it, kept free of duplicates while building by a layered set: extended in place by the sole way into its way on, otherwise laid thinly over it, and over the last way on at a merge. A component lists the own targets nothing further on reaches, then those further on. The index stays linear in the elements and transitions, and reading a start walks only its own targets.
…ed fragments Matching authored fragments appended a position for every fragment and message pair, so many fragments over a repeated step did work in the product of the two. The positions arriving at each element are now found once and shared by every operand whose body holds that element; an operand is its elements and their lists, and its extent, coverage and which operand holds a position are read from them without expanding.
A table crosses each shape found to need quadratic work (a comb of messages, a diamond of combs, decisions nested to one meet, many sources into one run, a run fanning out, repeated steps under many authored fragments, a wide fork, branches sharing one tail, a decision with many ways round) with every projection, and the edit lists with the inverses. Work is counted over the collection operations the projections are built from and measured per item of input and output, which must stay level as each shape doubles.
The layered sets behind each component's targets grew a layer at every merge, so serial diamonds of messages rescanned every earlier target through an ever deeper set. A component now gets one flat array of its targets only when it is read on its own: it is entered from an element that is not folded, or from two or more components. Every other component is read as part of the one before it, so it is visited once in all. Arrays are built on demand and remembered; a generation stamp per target removes duplicates in constant time, a component with nothing to add shares the array it reads, and the only builder of an array nothing else reads extends it in place. The work is linear in the elements and transitions plus the arrays that must be copied, and the reading order is unchanged.
…verses Deleting or editing many edges or state machine transitions whose folded chains share an end walked that end's arriving steps once per edge. Omitted and edited chains are now grouped by the end they share, so the steps into each end are removed, rewired or changed once, and edits to the same end that disagree are refused.
…d deletions Work is now counted over set and map lookups as well, so walks over linked structures that test membership as they go are measured. The scaling table gains serial diamonds of messages through every projection and deletion of every edge or transition of sources sharing one end through both inverses, and its shapes move to a test support module.
A shape whose state machine output is itself quadratic took longer than the test timeout to build at the shared size with every collection call counted. Projected shapes now start smaller, still large enough that quadratic work doubles per item, while the edit rows keep the larger size, which a rescan per edited item needs to overtake the fixed cost of re-projecting the model.
…per chain Every chain into a target destructured the list of folded steps arriving at it into its first item and a copy of the rest, so many paths converging on one end copied that list once per path. Chains now read its length and its one item by index. The other places that took a list apart the same way read it by index too, though each ran once per element or component.
…log time Placing a fragment inside an authored operand counted the operand's positions across all of its elements for each nested fragment, so one fragment over a long path with a fragment inside it per step did work quadratic in the path. A fragment with one operand holds its whole span; an operand held by elements keeps a set of them, against which an authored fragment inside it is checked by its own elements; any other span is checked by binary search or position by position, whichever is shorter.
…ested authored fragments Work is now also counted at each step of an array's iterator, so spreads, destructuring and loops over lists are measured. The scaling table gains many paths converging on one end through every projection, at the size where its quadratic part shows, and an authored fragment over the path with one inside it per step through the sequence diagram.
…gets Each merged chain walked everything its start reaches and filtered it by what leads to its own target, so reading every edge of a start with many common targets walked the same folded branches again per target. The walk from a start is now done once, numbering what it meets and indexing transitions by where they arrive; a chain's union is gathered by walking back from its target over that index and put in walk order, so it costs the size of the union.
…edge The scaling table gains a flowchart entry that reads every edge's lists and label, counting what it reads as output, a shape of two folded branches leading to many common ends, and an unchanged flowchart of those merged edges diffed against its model.
The walk behind merged chains entered everything a start reached, so many short chains sharing a run of messages that leads nowhere each walked and kept that run. The folded elements that lead to some accepted element are now found once, by walking back from the accepted elements, and every walk and the carried messages enter only those. Walks are shared per component, from its first member in model order, since every member of a component reaches the same elements.
The scaling table gains diamonds sharing a run that leads nowhere, and one half of which leads somewhere, through every projection and an unchanged flowchart diff. Edit rows are measured per item of their input, the model and the edited view as read, as the projection rows are.
Folding an element draws one chain per way in and drawn element it leads to, so many sources through one message, or a run of messages, to many ends drew every source to every end: quadratic output from linear input. An element is now folded only when the distinct entering transitions reaching it times the distinct drawn elements it reaches, through folded elements, is no more than their sum. The counts are capped sets carried once each way over the condensed folded graph. An element left unfolded is reported, with the transitions touching it, as an unrepresented element by the flowchart, swimlane and state machine; hand-offs and the inverses follow the same index.
The scaling table gains many sources through one message, and through two, to many ends, and a test that the flowchart, hand-offs and state machine draw no more edges than the model has transitions for those shapes as they double.
614b048 to
ff54234
Compare
|
@codex security review |
1 similar comment
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
🎉 This PR is included in version 1.1.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Phase 2b of the process-graph plan: the remaining gaps in
@exadev/process-graph-projection, plus inverses that turn an edited view back into a diff against the model.I checked each gap from the plan against main with a test on the order process first.
toStateMachinealready scopes byaffects,toSwimlanealready draws empty lanes for declared participants, andtoSequencealready wraps authored fragments, so those three needed nothing. Two were real:toSequencenever derivedalt/opt/loop/parfrom decisions, loops and forks, and no projection readmessageelements (they were only ever reported as a loss).Derived fragments come from the model's structure and are restricted to the scenario path. A decision transition whose target can reach the decision again is a loop transition (the same rule
graph-domain'sloopTransitionsuses); the decision's forward branches give analt, or anoptwhen one of two branches goes straight to where they meet; a fork gives apar. Each derived fragment names the decision or fork it came from, and one holding exactly an authored fragment's messages is dropped in favour of the authored one. A step leaving an actorless element such as a fork or join is now sent by whoever reached it, which is what lets aparshow its branches' messages.Message elements are drawn on the sequence path with their own ends, label and mode, and folded into the flowchart edge, hand-off and state machine transition that pass through them (the state machine taking the message's event as the trigger). Flowchart edges and state machine transitions now list the model transitions they stand for, which the inverses rely on.
The inverses are
diffFlowchart,diffSwimlane,diffStateMachineanddiffSequence. Each takes the edited view and returns aModelDiffmatched by element and transition id (added, removed, renamed, relaned and readdressed elements; added, removed, rewired and changed transitions; renamed events). Anything the view doesn't pin down isinferred: true: a new terminator's or bar's role, edits to a state machine transition that folds a decision (its later steps are shared with other chains), and nearly everything a sequence edit implies about steps and ownership.confirmChangesconfirms them, andapplyModelDiffrefuses withUnconfirmedChangeErroruntil nothing inferred is left. Edits the model can't express, such as a changed node shape or a lane for an entity, throw instead of being dropped. They're all exported flat through theprocess-graphentry point with no name collisions.Every new test runs on the order process fixture plus three variants of it (message elements, a payment retry loop, parallel fulfilment with an optional gift wrap). I broke the code once per behaviour to check that each test fails.