Skip to content

fix(cue): harden cue.yaml chain validation + topo-sort chain subs in pipeline editor - #981

Merged
pedramamini merged 2 commits into
RunMaestro:rcfrom
chr1syy:fix/cue-renderer
May 13, 2026
Merged

fix(cue): harden cue.yaml chain validation + topo-sort chain subs in pipeline editor#981
pedramamini merged 2 commits into
RunMaestro:rcfrom
chr1syy:fix/cue-renderer

Conversation

@chr1syy

@chr1syy chr1syy commented May 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Hardens cue.yaml validation around command chains (source_sub required when an agent.completed sub has action: command; fan-in source_sub/source_session array shapes must match positionally).
  • Adds visible error nodes in the Pipeline Editor when source_sub points at an unknown subscription, instead of silently falling back to session-name resolution.
  • Topologically sorts chain subs by source_sub dependencies in yamlToPipeline.ts. The previous chain-index sort placed a fan-in chain before the chains it depended on; under target_node_key-keyed pipelines this produced a duplicate phantom agent node and left the real fan-in target disconnected on canvas. Chain index is retained as a tie-breaker for deterministic layout and as the cycle-fallback order.
  • Documents the agent-authored Trigger → Cmd → Agent YAML checklist in docs/maestro-cue-configuration.md.

Reproduces the user-reported Obsidian Daily Pipe failure mode (Schedule → `Digest/Git/Health Script` (cmd) → per-agent chain → fan-in to Copilot) where the editor showed unresolved upstream links instead of the configured graph.

Test plan

  • vitest run src/__tests__/renderer/components/CuePipelineEditor/utils/yamlToPipeline.test.ts — 47/47 pass, including new regression test keeps fan-in wiring intact when chains carry target_node_key and chain-index ordering misranks dependencies (failed before fix with 4 agent nodes; passes after with the expected 3).
  • vitest run src/__tests__/renderer/components/CuePipelineEditor/utils/ src/__tests__/main/cue/cue-yaml-loader.test.ts — 489/489 pass.
  • Type-check + prettier clean on changed files.
  • Manually open a pipeline with a Trigger → Cmd → Agent → fan-in shape (each chain carrying a target_node_key) and confirm no phantom unresolved agent nodes.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved error detection for fan-in chain configurations with missing source references, now explicitly flagging invalid source relationships.
    • Enhanced validation for array-based configuration fields to ensure consistent length alignment.
  • Documentation

    • Updated configuration guide with validation rules for fan-in chains requiring positionally-aligned source mappings.
  • Tests

    • Added comprehensive test coverage for chain subscription resolution and error scenarios.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 11, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 650c6656-7789-418a-952b-2870459dcbe4

📥 Commits

Reviewing files that changed from the base of the PR and between 6d15e87 and d2fcfc3.

📒 Files selected for processing (5)
  • docs/maestro-cue-configuration.md
  • src/__tests__/main/cue/cue-yaml-loader.test.ts
  • src/__tests__/renderer/components/CuePipelineEditor/utils/yamlToPipeline.errorNodes.test.ts
  • src/__tests__/renderer/components/CuePipelineEditor/utils/yamlToPipeline.test.ts
  • src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/maestro-cue-configuration.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/tests/renderer/components/CuePipelineEditor/utils/yamlToPipeline.errorNodes.test.ts
  • src/tests/renderer/components/CuePipelineEditor/utils/yamlToPipeline.test.ts
  • src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts

📝 Walkthrough

Walkthrough

This pull request enhances Cue pipeline chain validation and resolution for command-triggered agent subscriptions. It adds documentation guidance, a validator test for array shape alignment, implements dependency-aware topological ordering of chain subscriptions, detects missing upstream references with error nodes, and includes regression tests to prevent subscription misrouting in fan-in scenarios.

Changes

Command-Chain Source Subscription Validation & Resolution

Layer / File(s) Summary
Configuration Checklist
docs/maestro-cue-configuration.md
Documentation checklist updated to require aligned array shapes (source_sub / source_session / source_session_ids must match length and positional alignment) for fan-in chains.
Validator Tests
src/__tests__/main/cue/cue-yaml-loader.test.ts
Test added asserting that when source_session is an array in agent.completed command-mode subscriptions, source_sub must also be an array (fails with a shape-mismatch error if source_sub is a string).
Dependency-Aware Chain Ordering
src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts
subscriptionsToPipelines replaces name-based sorting with two-phase ordering: initial-trigger subscriptions followed by chain subscriptions ordered via Kahn topological sort over source_sub dependencies, with chain index as tie-break and cycle fallback; builds knownSubNames set for validation.
Missing Upstream Detection
src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts
During chain-to-command and chain-to-agent edge construction, detects when a source_sub name is not in knownSubNames, creates explicit missing-source error nodes, and uses them as edge sources instead of fallback resolution.
Missing-Source Error Node Tests
src/__tests__/renderer/components/CuePipelineEditor/utils/yamlToPipeline.errorNodes.test.ts
Added two regression cases asserting exactly one error node with reason: 'missing-source' is emitted when source_sub references an unknown subscription name; verifies error payload includes the chain subscription name and stale source_sub value, and that downstream agents receive edges only from the error node.
Topological Resolution Regression
src/__tests__/renderer/components/CuePipelineEditor/utils/yamlToPipeline.test.ts
Regression test verifying that misranked dependency order using target_node_key does not break fan-in chains; asserts no error nodes, correct node counts (one trigger, two command nodes, three agent nodes), and end-to-end connectivity from both commands through their source agents to the main agent.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • RunMaestro/Maestro#872: Both PRs modify yamlToPipeline.ts chain/subscription handling around source_sub upstream resolution and fan-in/chain edge construction, adding logic and tests for correct chain wiring.
  • RunMaestro/Maestro#976: Both PRs harden Cue command-chain handling for agent.completed subscriptions by enforcing correct source_sub/source_session shapes in validation and emitting missing-source error nodes for unresolved references.
  • RunMaestro/Maestro#987: Both PRs address Cue config validation for event: agent.completed and the source_sub/source_session type/shape alignment in command-triggered chains.

Poem

🐰 Chain subscriptions now align with grace,
Dependencies topologically in place,
Missing sources glow as error nodes bright,
Fan-in flows correctly, everything's right!
A rabbit's delight in validation's new might! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main changes: hardening cue.yaml chain validation and implementing topological sorting for chain subscriptions in the pipeline editor.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
docs/maestro-cue-configuration.md (1)

205-209: ⚡ Quick win

Add explicit fan-in positional mapping rule in the checklist.

Line 205-Line 209 should also state that for fan-in chains, source_sub and source_session arrays must be the same length and aligned by index (and source_session_ids too, when present). This is now validator-enforced and is easy to miss without a direct checklist callout.

Suggested doc patch
 1. Initial trigger subscription uses `action: command` with a valid `command` object.
 2. The downstream `agent.completed` subscription includes `source_sub` pointing to that command subscription name.
+3. For fan-in, if you use arrays, keep `source_sub` / `source_session` (and `source_session_ids` when present) equal-length and positionally aligned.
-3. Keep `pipeline_name` consistent across all subs in the pipeline.
-4. Keep per-node identity fields (`target_node_key`, `fan_out_node_keys`) stable once created.
+4. Keep `pipeline_name` consistent across all subs in the pipeline.
+5. Keep per-node identity fields (`target_node_key`, `fan_out_node_keys`) stable once created.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/maestro-cue-configuration.md` around lines 205 - 209, Add a checklist
item stating that in fan-in chains the arrays source_sub and source_session (and
source_session_ids when present) must be the same length and positionally
aligned; update the checklist lines referencing initial trigger subscription,
downstream agent.completed subscription, pipeline_name, and node identity rules
to include this rule so authors know the validator enforces index-wise alignment
for fan-in mappings.
src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts (1)

946-964: 💤 Low value

Consider extracting the missing-source error-node creation.

The branch at lines 946-964 (command-target) and lines 1041-1060 (agent-target) construct the same missing-source error node — same id pattern (error-source-sub-${sub.name}-${i}), same data shape, same position math. Same is also true of the older missing-source branches at lines 973-990 and 1070-1088 that the PR didn't touch.

Extracting a small createMissingSourceErrorNode(sub, i, subRef, targetCol, existingRows) helper would consolidate four near-identical blocks and prevent future drift between the command-target and agent-target paths (e.g. if a new field is added to ErrorNodeData).

Not a blocker — purely a maintainability improvement and the duplication predates this PR.

Also applies to: 1041-1060

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts` around
lines 946 - 964, The code duplicates identical "missing-source" error-node
construction in multiple branches of yamlToPipeline.ts; add a helper function
(e.g., createMissingSourceErrorNode(sub, i, targetCol, existingRows, LAYOUT))
that builds the error node id (`error-source-sub-${sub.name}-${i}`), composes
the ErrorNodeData (reason:'missing-source', subscriptionName: sub.name, message
using subRef), computes the position using LAYOUT and (targetCol, existingRows),
calls createErrorNode and returns the node (and id if useful); then replace the
four duplicated blocks (the spots that currently call createErrorNode and set
nodeMap/sourceNode for missing-source — references: variables sub, i, subRef,
targetCol, existingRows, nodeMap, sourceNode) to call the new helper and insert
the returned node into nodeMap and assign to sourceNode.
src/__tests__/main/cue/cue-yaml-loader.test.ts (1)

760-818: ⚡ Quick win

Consider adding the symmetric shape-mismatch test.

The validator at lines 381-385 emits two distinct errors:

  • "source_sub" must be an array when "source_session" is an array (string sub, array session)
  • "source_sub" must be a string when "source_session" is a string (array sub, string session)

Only the second path is asserted here (lines 798-818). A test for the first path would lock in the symmetric error message and guard against accidental message drift.

♻️ Proposed additional test
+		it('rejects source_sub string when source_session is an array', () => {
+			const result = validateCueConfig({
+				subscriptions: [
+					{
+						name: 'fan-in-invalid-shape-2',
+						event: 'agent.completed',
+						source_session: ['A', 'B'],
+						source_sub: 'chain-a',
+						prompt: '{{CUE_SOURCE_OUTPUT}}',
+					},
+				],
+			});
+			expect(result.valid).toBe(false);
+			expect(result.errors).toEqual(
+				expect.arrayContaining([
+					expect.stringContaining(
+						'"source_sub" must be an array when "source_session" is an array'
+					),
+				])
+			);
+		});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/__tests__/main/cue/cue-yaml-loader.test.ts` around lines 760 - 818, The
tests for validateCueConfig are missing the symmetric shape-mismatch case: add a
test (in src/__tests__/main/cue/cue-yaml-loader.test.ts) that passes a
subscription with source_session as an array (e.g., ['A','B']) and source_sub as
a plain string, invoke validateCueConfig, assert result.valid is false, and
assert result.errors contains the expected message substring like '"source_sub"
must be an array when "source_session" is an array' to mirror the existing test
that covers the opposite mismatch; use the same test naming pattern as the other
cases so it clearly ties to validateCueConfig and the agent.completed
subscription validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@docs/maestro-cue-configuration.md`:
- Around line 205-209: Add a checklist item stating that in fan-in chains the
arrays source_sub and source_session (and source_session_ids when present) must
be the same length and positionally aligned; update the checklist lines
referencing initial trigger subscription, downstream agent.completed
subscription, pipeline_name, and node identity rules to include this rule so
authors know the validator enforces index-wise alignment for fan-in mappings.

In `@src/__tests__/main/cue/cue-yaml-loader.test.ts`:
- Around line 760-818: The tests for validateCueConfig are missing the symmetric
shape-mismatch case: add a test (in
src/__tests__/main/cue/cue-yaml-loader.test.ts) that passes a subscription with
source_session as an array (e.g., ['A','B']) and source_sub as a plain string,
invoke validateCueConfig, assert result.valid is false, and assert result.errors
contains the expected message substring like '"source_sub" must be an array when
"source_session" is an array' to mirror the existing test that covers the
opposite mismatch; use the same test naming pattern as the other cases so it
clearly ties to validateCueConfig and the agent.completed subscription
validation.

In `@src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts`:
- Around line 946-964: The code duplicates identical "missing-source" error-node
construction in multiple branches of yamlToPipeline.ts; add a helper function
(e.g., createMissingSourceErrorNode(sub, i, targetCol, existingRows, LAYOUT))
that builds the error node id (`error-source-sub-${sub.name}-${i}`), composes
the ErrorNodeData (reason:'missing-source', subscriptionName: sub.name, message
using subRef), computes the position using LAYOUT and (targetCol, existingRows),
calls createErrorNode and returns the node (and id if useful); then replace the
four duplicated blocks (the spots that currently call createErrorNode and set
nodeMap/sourceNode for missing-source — references: variables sub, i, subRef,
targetCol, existingRows, nodeMap, sourceNode) to call the new helper and insert
the returned node into nodeMap and assign to sourceNode.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 05460e78-97a6-4659-b847-916bbe97baa1

📥 Commits

Reviewing files that changed from the base of the PR and between 56ece61 and 08fa4b1.

📒 Files selected for processing (5)
  • docs/maestro-cue-configuration.md
  • src/__tests__/main/cue/cue-yaml-loader.test.ts
  • src/__tests__/renderer/components/CuePipelineEditor/utils/yamlToPipeline.test.ts
  • src/main/cue/config/cue-config-validator.ts
  • src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts

@greptile-apps

greptile-apps Bot commented May 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a phantom-agent bug in the Pipeline Editor where fan-in chain subs (carrying target_node_key) were processed before their upstream chains due to chain-index ordering — causing a duplicate disconnected agent node on the canvas. It also hardens cue.yaml validation with new shape checks for source_sub/source_session positional alignment.

  • Topo sort in yamlToPipeline.ts: Kahn's algorithm replaces the simple chain-index sort for chain subs; chain index is demoted to a tie-breaker. A new knownSubNames guard surfaces an error node when source_sub names a subscription that doesn't exist in the pipeline instead of silently falling back to session-name resolution.
  • Validator hardening in cue-config-validator.ts: source_sub is now required for agent.completed subs with action: command, and source_sub/source_session array lengths are checked for positional alignment.
  • Test coverage: A regression test for the Obsidian Daily Pipe shape (47 tests pass) and three new validator unit tests (489 total) are included; the error-node path for unknown source_sub has no direct test yet.

Confidence Score: 4/5

Safe to merge; the topo-sort fix is well-reasoned and the regression test validates the exact failure mode from the user bug report.

The core algorithm change is correct and covered by a purpose-built regression test. Two non-blocking gaps exist: an error-node code path that has no direct test (meaning a future regression there would go unnoticed), and a validator error message that reads 'must be a string when source_session is a string' even when source_session is absent rather than a string. Neither affects current runtime behaviour.

The new !knownSubNames.has(subRef) branch in yamlToPipeline.ts (both the command and agent-target paths) lacks a dedicated test; cue-config-validator.ts line 384 has a slightly inaccurate error message for the undefined source_session case.

Important Files Changed

Filename Overview
src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts Replaces the old chain-index sort with Kahn's topological sort over source_sub dependencies, and adds error-node creation when source_sub references an unknown subscription. Core algorithm is correct; happy path is well-tested by the new regression test, but the error-node branch has no direct test coverage.
src/main/cue/config/cue-config-validator.ts Adds validation requiring source_sub on command-action agent.completed subs, and checks positional alignment of source_sub/source_session arrays. Logic is sound; one error message is misleading when source_session is undefined rather than a string.
src/tests/renderer/components/CuePipelineEditor/utils/yamlToPipeline.test.ts Adds a well-constructed regression test (Obsidian Daily Pipe shape) that specifically targets the chain-index mis-ranking bug; assertions cover node counts, absence of phantom/error nodes, and all four expected edges.
src/tests/main/cue/cue-yaml-loader.test.ts Three new unit tests cover the new validator rules (missing source_sub for command action, array-length mismatch, shape mismatch); an existing test is also updated to satisfy the new source_sub requirement.
docs/maestro-cue-configuration.md Documents the Trigger → Command → Agent YAML checklist for AI-authored configs with a concrete annotated example; no issues found.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Split subs into initialTriggers / chainSubs] --> B[Sort initialTriggers by tieBreak]
    B --> C[Build indegree + dependents maps\nfrom source_sub refs within chainSubNames]
    C --> D{ready queue\nnon-empty?}
    D -- yes --> E[Pick candidate with lowest tieBreak]
    E --> F[Emit to orderedChainSubs\nDecrement dependents' indegree]
    F --> G{any dependent\nreached 0?}
    G -- yes --> H[Push to ready queue]
    H --> D
    G -- no --> D
    D -- no --> I{consumed all\nchain subs?}
    I -- yes --> J[sorted = initialTriggers + orderedChainSubs]
    I -- no --> K[Cycle fallback: append\nremainders in tieBreak order]
    K --> J
    J --> L[Loop over sorted subs]
    L --> M{source_sub\nresolved in subNameToNode?}
    M -- yes --> N[Use existing node]
    M -- no --> O{subRef NOT in\nknownSubNames?}
    O -- yes --> P[Emit visible error node]
    O -- no --> Q[Fall back to session-name\nresolution]
Loading

Reviews (1): Last reviewed commit: "fix(cue-renderer): topologically sort ch..." | Re-trigger Greptile

Comment thread src/main/cue/config/cue-config-validator.ts Outdated
Comment thread src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts
@pedramamini

Copy link
Copy Markdown
Collaborator

Thanks for the contribution, @chr1syy! This is a really nice fix — the topological sort + validation hardening directly addresses the Obsidian Daily Pipe failure mode, and the new regression test is exactly what we want here.

Unfortunately the PR currently has merge conflicts against rc. Could you kindly rebase onto the latest rc and resolve the conflicts so we can get a clean merge? Once that's done we should be good to land it.

chr1syy added a commit to chr1syy/Maestro that referenced this pull request May 11, 2026
- Validator: narrow the source_sub shape-mismatch error to the *string*
  case explicitly so a missing source_session emits only the
  required-field error instead of the misleading "must be a string when
  source_session is a string" message (Greptile P2).
- Docs: add the fan-in positional-alignment checklist item — when
  source_sub / source_session / source_session_ids are arrays they must
  be the same length and aligned by index (CodeRabbit nit).
- Tests: add the symmetric shape-mismatch case (array session + string
  sub) and a regression locking in the "no misleading error when
  source_session is missing" behaviour (Greptile + CodeRabbit nit).
- Tests: add two regression tests for the visible-error-node path —
  agent-target and command-target — so a future refactor can't silently
  revert `!knownSubNames.has(subRef)` back to the session-name fallback
  (Greptile P2).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@chr1syy
chr1syy force-pushed the fix/cue-renderer branch from 08fa4b1 to 6d15e87 Compare May 11, 2026 07:36

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/__tests__/renderer/components/CuePipelineEditor/utils/yamlToPipeline.errorNodes.test.ts (1)

307-341: ⚡ Quick win

Consider adding edge verification for consistency.

This test successfully locks in error emission for the command-action branch. However, unlike the agent-target test (lines 298-305), it doesn't verify that downstream nodes wire to the error node. Adding similar edge assertions would strengthen the regression guard and ensure both code paths have equivalent coverage.

♻️ Optional: Add edge verification like the agent-target test
 		const [pipeline] = subscriptionsToPipelines(subs, sessions);
 		const errs = errorNodes(pipeline.nodes);
 		expect(errs).toHaveLength(1);
 		const data = errs[0].data as ErrorNodeData;
 		expect(data.reason).toBe('missing-source');
 		expect(data.message).toContain('Stale Ghost Sub');
+		// Verify the command node wires to the error node, not a fallback
+		const cmdNode = pipeline.nodes.find(
+			(n) => n.type === 'command' && n.data?.subscriptionName === 'pipe-cmd-chain'
+		);
+		expect(cmdNode).toBeDefined();
+		const incomingToCmd = pipeline.edges.filter((e) => e.target === cmdNode!.id);
+		expect(incomingToCmd).toHaveLength(1);
+		expect(incomingToCmd[0].source).toBe(errs[0].id);
 	});

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2298189f-0334-4fde-9a0c-1cf85dc05d35

📥 Commits

Reviewing files that changed from the base of the PR and between 08fa4b1 and 6d15e87.

📒 Files selected for processing (6)
  • docs/maestro-cue-configuration.md
  • src/__tests__/main/cue/cue-yaml-loader.test.ts
  • src/__tests__/renderer/components/CuePipelineEditor/utils/yamlToPipeline.errorNodes.test.ts
  • src/__tests__/renderer/components/CuePipelineEditor/utils/yamlToPipeline.test.ts
  • src/main/cue/config/cue-config-validator.ts
  • src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/maestro-cue-configuration.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/renderer/components/CuePipelineEditor/utils/yamlToPipeline.ts
  • src/tests/renderer/components/CuePipelineEditor/utils/yamlToPipeline.test.ts

@chr1syy chr1syy added the ready to merge This PR is ready to merge label May 11, 2026
chr1syy and others added 2 commits May 13, 2026 10:20
When a fan-in chain sub's `source_sub` referenced another chain with a
higher `-chain-N` index, the chain-index sort processed the dependent
first. Its source lookup in `subNameToNode` missed, fell back to
session-name resolution, and invented a premature agent node — and
when the real upstream later created its keyed target via
`target_node_key`, the legacy sessionName dedup in
`getOrCreateAgentNode` was bypassed, leaving a disconnected phantom
agent next to the real one. This was the visible "unresolved upstream"
symptom on canvases authored as Trigger → Cmd → Agent → fan-in.

Replace the chain-index sort with Kahn's algorithm over `source_sub`
dependencies. Chain index becomes a tie-breaker among ready subs and
the cycle-fallback order, preserving deterministic layout. Added a
regression test that mirrors the user-reported Obsidian Daily Pipe
shape (chain-1/chain-2/chain-4 fan-in with `target_node_key` on every
sub) — produces 4 agent nodes before the fix, 3 after.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Validator: narrow the source_sub shape-mismatch error to the *string*
  case explicitly so a missing source_session emits only the
  required-field error instead of the misleading "must be a string when
  source_session is a string" message (Greptile P2).
- Docs: add the fan-in positional-alignment checklist item — when
  source_sub / source_session / source_session_ids are arrays they must
  be the same length and aligned by index (CodeRabbit nit).
- Tests: add the symmetric shape-mismatch case (array session + string
  sub) and a regression locking in the "no misleading error when
  source_session is missing" behaviour (Greptile + CodeRabbit nit).
- Tests: add two regression tests for the visible-error-node path —
  agent-target and command-target — so a future refactor can't silently
  revert `!knownSubNames.has(subRef)` back to the session-name fallback
  (Greptile P2).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@pedramamini
pedramamini merged commit 7dc892e into RunMaestro:rc May 13, 2026
3 checks passed
pedramamini added a commit that referenced this pull request May 14, 2026
…t keys

CLI server discovery (main):
- Start CLI server + publish discovery file early in whenReady so a later
  startup failure can't silently leave maestro-cli unable to connect (the
  symptom that previously required toggling Live Mode to recover).
- Retry ensureCliServer on failure and verify the file is actually present
  on disk after each write.
- Periodic watchdog re-publishes the discovery file if it goes missing or
  drifts out of sync with the running server.
- Surface fatal whenReady errors to Sentry instead of swallowing them.

FilePreview:
- HTML files get a Globe toggle in the header that swaps source view for a
  sandboxed iframe (allow-scripts allow-popups allow-forms, no
  same-origin, no-referrer). State persists per-tab via tabStore.
- Move PreviewTierChip into the header button cluster (new iconOnly mode)
  so the dedicated tier-chip bar is gone — same popover behavior.
- HighlightedCodeEditor: whitespace pre + textarea wrap=off so markdown
  tables and other long lines scroll horizontally instead of fragmenting
  around `|` delimiters.

Cue pipeline layout:
- Match saved positions by stable identifiers first (trigger
  subscriptionName, agent/command nodeKey) and fall back to legacy
  index-based keys only for older saves. Fixes positions drifting onto
  the wrong nodes after the chain-sub topo-sort reorder (#981).

Misc UX:
- SshRemoteSelector: hide the share-to-project-dir toggle when SSH
  execution is active (it has no audience on the remote).
- GroupChatMessages / TerminalOutput: tooltip hints include
  Shift+ArrowUp for previous-message navigation.

Tests:
- ensureCliServer retry + watchdog coverage.
- semanticNodeKeys priority + YAML-reorder regression cases.
- PreviewTierChip iconOnly mode.
- FilePreview HTML render mode (toggle visibility, iframe sandbox).
- tabStore setFileTabHtmlRenderMode.

Claude ID: c9bb9f6b-2568-4b5d-a0db-8b1bb09a510e
Maestro ID: 865ec2d1-8898-4a68-9d06-e13562d127e0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready to merge This PR is ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants