Skip to content

New nodes: 'L-System' and 'Turtle Path' - #4920

Open
Keavon wants to merge 2 commits into
masterfrom
l-system-nodes
Open

Keavon wants to merge 2 commits into
masterfrom
l-system-nodes

Conversation

@Keavon

@Keavon Keavon commented Nov 5, 2026 •

Copy link
Copy Markdown
Member
image image

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 9 files

Confidence score: 3/5

  • rewrite in l_system.rs can keep iterating through a large generation count when rules cannot change the state, freezing graph evaluation. Stop when a generation makes no changes or otherwise bound the work.
  • In turtle.rs, closing a run on its first point leaves turtle.run set, so later draws append to the closed run and revisit its start point. Reset the run when it closes.
  • rule_separator in l_system.rs can treat = inside a parenthesized where binding as the rule delimiter, misparsing the rule. Make delimiter detection account for the condition’s parentheses.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="node-graph/nodes/vector/src/turtle.rs">

<violation number="1" location="node-graph/nodes/vector/src/turtle.rs:134">
P2: After a draw closes a run on its first point, `turtle.run` stays `Some(run)`, so later draws keep appending to that run. The path then revisits its start point mid-sequence instead of beginning a new run there. End the run on closure.</violation>
</file>

<file name="node-graph/nodes/text/src/l_system.rs">

<violation number="1" location="node-graph/nodes/text/src/l_system.rs:175">
P1: `rewrite` iterates through every requested generation even when the state cannot change. With the unbounded `generations` input, `F = F` or no matching rules can make a large value run indefinitely and freeze graph evaluation; enforce a finite execution budget and report truncation.</violation>

<violation number="2" location="node-graph/nodes/text/src/l_system.rs:454">
P2: `rule_separator` treats the first single `=` anywhere in the line as the rule delimiter. A `math-parser` `where` binding inside a parenthesized condition, such as `F(x) : (x where x = 1) > 0 = F`, is split at `x = 1` and rejected; track parenthesis depth and accept only a top-level separator.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

let mut rng = StdRng::seed_from_u64(seed);
let mut modules = axiom;

for generation in 0..generations {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: rewrite iterates through every requested generation even when the state cannot change. With the unbounded generations input, F = F or no matching rules can make a large value run indefinitely and freeze graph evaluation; enforce a finite execution budget and report truncation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At node-graph/nodes/text/src/l_system.rs, line 175:

<comment>`rewrite` iterates through every requested generation even when the state cannot change. With the unbounded `generations` input, `F = F` or no matching rules can make a large value run indefinitely and freeze graph evaluation; enforce a finite execution budget and report truncation.</comment>

<file context>
@@ -0,0 +1,655 @@
+	let mut rng = StdRng::seed_from_u64(seed);
+	let mut modules = axiom;
+
+	for generation in 0..generations {
+		let partners = if rule_set.uses_context { bracket_partners(&modules) } else { Vec::new() };
+		let neighbors = Neighbors {
</file context>


self.runs[run].push(end);
turtle.anchor_slot = self.new_anchor_slot(AnchorSlot::Drawn(end));
turtle.run = Some(run);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: After a draw closes a run on its first point, turtle.run stays Some(run), so later draws keep appending to that run. The path then revisits its start point mid-sequence instead of beginning a new run there. End the run on closure.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At node-graph/nodes/vector/src/turtle.rs, line 134:

<comment>After a draw closes a run on its first point, `turtle.run` stays `Some(run)`, so later draws keep appending to that run. The path then revisits its start point mid-sequence instead of beginning a new run there. End the run on closure.</comment>

<file context>
@@ -0,0 +1,246 @@
+
+		self.runs[run].push(end);
+		turtle.anchor_slot = self.new_anchor_slot(AnchorSlot::Drawn(end));
+		turtle.run = Some(run);
+	}
+
</file context>

let bytes = line.as_bytes();
(0..bytes.len()).find(|&index| {
let previous = index.checked_sub(1).map(|previous| bytes[previous]);
bytes[index] == b'=' && !matches!(previous, Some(b'=' | b'<' | b'>' | b'!')) && bytes.get(index + 1) != Some(&b'=')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: rule_separator treats the first single = anywhere in the line as the rule delimiter. A math-parser where binding inside a parenthesized condition, such as F(x) : (x where x = 1) > 0 = F, is split at x = 1 and rejected; track parenthesis depth and accept only a top-level separator.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At node-graph/nodes/text/src/l_system.rs, line 454:

<comment>`rule_separator` treats the first single `=` anywhere in the line as the rule delimiter. A `math-parser` `where` binding inside a parenthesized condition, such as `F(x) : (x where x = 1) > 0 = F`, is split at `x = 1` and rejected; track parenthesis depth and accept only a top-level separator.</comment>

<file context>
@@ -0,0 +1,655 @@
+	let bytes = line.as_bytes();
+	(0..bytes.len()).find(|&index| {
+		let previous = index.checked_sub(1).map(|previous| bytes[previous]);
+		bytes[index] == b'=' && !matches!(previous, Some(b'=' | b'<' | b'>' | b'!')) && bytes.get(index + 1) != Some(&b'=')
+	})
+}
</file context>

This branch was successfully deployed

1 active deployment
graphite-dev (Preview) — 9a3c38b9 Deployed Nov 5, 2026 by github-actions[bot]
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.

1 participant