Repository navigation
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Root-anchored .orca rules break pipeline re-inclusion, and future-schema read-only databases can fail when pipeline side tables are absent.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Adds user-authored Heimdall pipelines spanning the shared graph model, execution engine, persistence, remote protocol, CLI, and canvas UI.
Changes:
- Introduces pipeline schemas, validation, interpretation, persistence, execution, and capability negotiation.
- Adds pipeline authoring/run UI, CLI commands, localization, and remote-host support.
- Integrates built-in Objective/PR-sitter flows and configurable repeated-fix handling.
| File | Description |
|---|---|
src/shared/rpc-contract/rpc-params-catalog.generated.ts |
Registers pipeline RPC schemas. |
src/shared/protocol-version.ts |
Advertises pipeline capabilities. |
src/shared/fork-hosted-review-sitter/types.ts |
Adds repeat-fix limits. |
src/shared/fork-hosted-review-sitter/enrollment-candidate.ts |
Validates repeat limits. |
src/shared/fork-hosted-review-sitter/agent-prompt.ts |
Includes previous fix evidence. |
src/shared/fork-hosted-review-sitter/agent-prompt.test.ts |
Tests repeated-failure prompts. |
src/shared/fork-heimdall/owner/deviation.ts |
Adds pipeline-node deviations. |
src/shared/fork-heimdall-pipeline/yaml-writer/pipeline-edit-values.ts |
Handles YAML edit values. |
src/shared/fork-heimdall-pipeline/yaml-writer/pipeline-edit-types.ts |
Defines editing contracts. |
src/shared/fork-heimdall-pipeline/yaml-writer/pipeline-authoring-document.ts |
Defines authoring documents. |
src/shared/fork-heimdall-pipeline/yaml-writer/layout-writer.ts |
Serializes canvas layouts. |
src/shared/fork-heimdall-pipeline/yaml-writer/index.ts |
Exports YAML writer APIs. |
src/shared/fork-heimdall-pipeline/task-list.test.ts |
Tests task-list validation. |
src/shared/fork-heimdall-pipeline/run-view-types.test.ts |
Tests forward-compatible run views. |
src/shared/fork-heimdall-pipeline/pipeline-source.ts |
Bounds pipeline source size. |
src/shared/fork-heimdall-pipeline/pipeline-source.test.ts |
Tests source limits. |
src/shared/fork-heimdall-pipeline/pipeline-ref.ts |
Parses pipeline references. |
src/shared/fork-heimdall-pipeline/pipeline-ref.test.ts |
Tests reference parsing. |
src/shared/fork-heimdall-pipeline/pipeline-pin.ts |
Defines immutable run pins. |
src/shared/fork-heimdall-pipeline/pipeline-canonical-hash.ts |
Hashes canonical documents. |
src/shared/fork-heimdall-pipeline/node-id.ts |
Defines node identifiers. |
src/shared/fork-heimdall-pipeline/layout-schema.ts |
Defines layout schemas. |
src/shared/fork-heimdall-pipeline/layout-schema.test.ts |
Tests layout compatibility. |
src/shared/fork-heimdall-pipeline/interpreter/verdict-output.ts |
Decodes verdict outputs. |
src/shared/fork-heimdall-pipeline/interpreter/swarm-rules.ts |
Schedules swarm children. |
src/shared/fork-heimdall-pipeline/interpreter/stop-verdict.ts |
Determines terminal verdicts. |
src/shared/fork-heimdall-pipeline/interpreter/node-history.ts |
Projects node attempt history. |
src/shared/fork-heimdall-pipeline/interpreter/merge-order.ts |
Orders merge operations. |
src/shared/fork-heimdall-pipeline/enrollment-payload.ts |
Defines run enrollment payloads. |
src/shared/fork-heimdall-pipeline/enrollment-payload.test.ts |
Tests enrollment validation. |
src/shared/fork-heimdall-pipeline/capability.ts |
Defines wire capabilities. |
src/shared/fork-heimdall-pipeline/capability.test.ts |
Tests capability mapping. |
src/shared/fork-heimdall-pipeline/capability-grants.ts |
Computes requested grants. |
src/shared/fork-heimdall-pipeline/builtin-pipelines.ts |
Defines built-in pipelines. |
src/shared/fork-heimdall-pipeline/builtin-pipelines.test.ts |
Tests built-in documents. |
src/renderer/src/store/slices/tabs-hydration.ts |
Drops transient pipeline tabs. |
src/renderer/src/store/slices/fork-heimdall/fleet.ts |
Uses remote-reader fleet types. |
src/renderer/src/store/slices/editor/types/open-file.ts |
Adds pipeline editor mode. |
src/renderer/src/i18n/fork-localization-catalogs.test.ts |
Removes brittle catalog-count test. |
src/renderer/src/fork-hosted-review-sitter/HostedReviewSitterStatusContent.tsx |
Supports reader-safe entries. |
src/renderer/src/fork-hosted-review-sitter/hosted-review-sitter-panel-state.ts |
Updates remote entry types. |
src/renderer/src/fork-hosted-review-sitter/active-sitter-registry.ts |
Narrows active sitter entries. |
src/renderer/src/fork-heimdall/watcher-status-copy.test.ts |
Tests watcher-kind labels. |
src/renderer/src/fork-heimdall/locales/zh.json |
Localizes new fleet UI. |
src/renderer/src/fork-heimdall/locales/ko.json |
Localizes new fleet UI. |
src/renderer/src/fork-heimdall/locales/ja.json |
Localizes new fleet UI. |
src/renderer/src/fork-heimdall/locales/fr.json |
Localizes new fleet UI. |
src/renderer/src/fork-heimdall/locales/es.json |
Localizes new fleet UI. |
src/renderer/src/fork-heimdall/locales/en.json |
Adds new fleet copy. |
src/renderer/src/fork-heimdall/HeimdallStatusPill.tsx |
Supports remote-reader rows. |
src/renderer/src/fork-heimdall/HeimdallConcurrencyControl.tsx |
Supports reader enrollments. |
src/renderer/src/fork-heimdall/heimdall-tone-pill.tsx |
Adds destructive status tone. |
src/renderer/src/fork-heimdall/heimdall-tone-pill.test.tsx |
Tests destructive styling. |
src/renderer/src/fork-heimdall/fleet-row-presentation.ts |
Projects reader-safe fleet data. |
src/renderer/src/fork-heimdall/fleet-action-history.ts |
Supports reader-safe details. |
src/renderer/src/fork-heimdall-pipeline/PipelineYamlPreview.tsx |
Adds read-only YAML preview. |
src/renderer/src/fork-heimdall-pipeline/PipelineYamlPreview.test.tsx |
Tests preview read-only state. |
src/renderer/src/fork-heimdall-pipeline/PipelineValidationList.tsx |
Displays validation errors. |
src/renderer/src/fork-heimdall-pipeline/PipelineTrackingNotice.tsx |
Shows Git tracking guidance. |
src/renderer/src/fork-heimdall-pipeline/PipelinePalette.tsx |
Adds draggable node palette. |
src/renderer/src/fork-heimdall-pipeline/PipelineExternalChangeBanner.tsx |
Handles external edits. |
src/renderer/src/fork-heimdall-pipeline/PipelineCanvasTab.tsx |
Lazily mounts the canvas. |
src/renderer/src/fork-heimdall-pipeline/pipeline-virtual-tab-id.ts |
Recognizes pipeline tab IDs. |
src/renderer/src/fork-heimdall-pipeline/pipeline-tab-lifecycle.ts |
Disposes canvas drafts. |
src/renderer/src/fork-heimdall-pipeline/pipeline-tab-lifecycle.test.ts |
Tests draft disposal. |
src/renderer/src/fork-heimdall-pipeline/pipeline-node-views/UnknownNodeView.tsx |
Renders future node types. |
src/renderer/src/fork-heimdall-pipeline/pipeline-node-views/index.ts |
Exports node views. |
src/renderer/src/fork-heimdall-pipeline/localization-catalog.ts |
Registers pipeline locales. |
src/renderer/src/fork-heimdall-objective/ObjectivePlanQuality.tsx |
Renames gates to checks. |
src/renderer/src/fork-heimdall-objective/ObjectivePlan.test.tsx |
Updates objective tests. |
src/renderer/src/fork-heimdall-objective/ObjectiveEnrollmentGateFields.tsx |
Updates check terminology. |
src/renderer/src/fork-heimdall-objective/ObjectiveEnrollmentFieldHelp.tsx |
Updates check help text. |
src/renderer/src/fork-heimdall-objective/ObjectiveDetailContent.tsx |
Handles reader-safe sitter rows. |
src/renderer/src/fork-heimdall-objective/objective-detail-format.ts |
Updates check labels. |
src/renderer/src/fork-heimdall-objective/locales/zh.json |
Adds objective translations. |
src/renderer/src/fork-heimdall-objective/locales/ko.json |
Adds objective translations. |
src/renderer/src/fork-heimdall-objective/locales/ja.json |
Adds objective translations. |
src/renderer/src/fork-heimdall-objective/locales/fr.json |
Adds objective translations. |
src/renderer/src/fork-heimdall-objective/locales/es.json |
Adds objective translations. |
src/renderer/src/components/editor/EditorPanelHeaderPath.tsx |
Treats pipelines as virtual tabs. |
src/renderer/src/components/editor/EditorPanel.tsx |
Avoids folder actions for pipelines. |
src/renderer/src/components/editor/EditorContent.tsx |
Renders pipeline canvases. |
src/renderer/src/components/editor/editor-save-queue.ts |
Routes pipeline saves. |
src/renderer/src/components/editor/editor-labels.ts |
Labels pipeline tabs. |
src/renderer/src/components/editor/editor-header.ts |
Hides file header for pipelines. |
src/renderer/src/components/editor/editor-autosave-controller.ts |
Saves pipelines before close. |
src/renderer/src/components/editor/closed-editor-tab-disposal.ts |
Disposes pipeline caches. |
src/relay/fs-handler.ts |
Exposes relay readlink. |
src/relay/fork-heimdall-pipeline/link-target-request.ts |
Implements relay readlink. |
src/relay/fork-heimdall-pipeline/link-target-request.test.ts |
Tests relay symlink reads. |
src/preload/preload-runtime-support.ts |
Preserves internal drag events. |
src/main/runtime/runtime-repository-issue-command.ts |
Reuses .orca ignore detection. |
src/main/runtime/rpc/methods/fork-heimdall/pipeline-kind-wire.ts |
Negotiates pipeline rows. |
src/main/runtime/rpc/methods/fork-heimdall/legacy-wire.ts |
Filters legacy pipeline lists. |
src/main/runtime/rpc/methods/fork-heimdall/dispatch-result-wire.ts |
Uses reader-safe details. |
src/main/runtime/rpc/methods/fork-artifact-passwords/artifact-password-local-caller.ts |
Makes caller kind optional. |
src/main/providers/ssh-filesystem-provider.ts |
Adds SSH link reading. |
src/main/providers/filesystem-provider-contract.ts |
Extends filesystem contract. |
src/main/issue-command-file.ts |
Reuses .orca ignore rules. |
src/main/ipc/hooks/register-worktree-hook-file-handlers.ts |
Reuses ignore detection remotely. |
src/main/ipc/desktop-renderer-runtime-capabilities.ts |
Advertises desktop pipeline support. |
src/main/fork-hosted-review-sitter/service-action-executor.ts |
Supplies failure history. |
src/main/fork-hosted-review-sitter/owner-state-brief.ts |
Applies repeat-fix defaults. |
src/main/fork-hosted-review-sitter/definition.ts |
Persists repeat limits. |
src/main/fork-hosted-review-sitter/definition.test.ts |
Tests repeat-limit definitions. |
src/main/fork-hosted-review-sitter/definition-store.ts |
Validates stored limits. |
src/main/fork-hosted-review-sitter/definition-store.test.ts |
Tests limit persistence. |
src/main/fork-hosted-review-sitter/agent-preparation.ts |
Adds prior attempts to prompts. |
src/main/fork-heimdall/runner-worker-lifecycle.ts |
Resolves accepted completions. |
src/main/fork-heimdall/runner-stop-lifecycle.ts |
Persists terminal projections. |
src/main/fork-heimdall/runner-gating.ts |
Supports kind-specific advisories. |
src/main/fork-heimdall/runner-actions.ts |
Persists dispatch evidence. |
src/main/fork-heimdall/runner-accepted-completion.ts |
Verifies worker completion effects. |
src/main/fork-heimdall/retention.ts |
Reads pipeline enrollment tables. |
src/main/fork-heimdall/registration.ts |
Registers pipeline-aware kinds. |
src/main/fork-heimdall/owner/owner-intervention.ts |
Generalizes rejection gates. |
src/main/fork-heimdall/owner/deviation-scope.ts |
Supports kind-owned escalation. |
src/main/fork-heimdall/owner/deviation-routing.test.ts |
Tests escalation routing. |
src/main/fork-heimdall/orchestration/coordinator-runtime-facade.ts |
Defaults terminals to background. |
src/main/fork-heimdall/notification.ts |
Adds pipeline approval copy. |
src/main/fork-heimdall/local-fleet-projection.ts |
Projects pipeline fleet state. |
src/main/fork-heimdall/local-fleet-projection.test.ts |
Tests pipeline projections. |
src/main/fork-heimdall/kernel-worker-release.test.ts |
Updates mailbox read expectations. |
src/main/fork-heimdall/kernel-terminal-transition.ts |
Recognizes pipeline uniqueness errors. |
src/main/fork-heimdall/kernel-service.ts |
Adds pipeline enrollment hooks. |
src/main/fork-heimdall/kernel-service-test-harness.ts |
Exposes runtime test fixtures. |
src/main/fork-heimdall/judgment/mailbox-refresh.ts |
Refreshes non-judgment kinds. |
src/main/fork-heimdall/fleet-remote-operations.ts |
Negotiates remote pipeline commands. |
src/main/fork-heimdall/fleet-remote-command.ts |
Refuses unsupported pipeline commands. |
src/main/fork-heimdall/fleet-ipc-forward.test.ts |
Uses reader-safe snapshot types. |
src/main/fork-heimdall/enrollment-insert-rollback.ts |
Rolls back failed enrollment inserts. |
src/main/fork-heimdall/database.ts |
Creates pipeline side tables. |
src/main/fork-heimdall/database.test.ts |
Tests side-table initialization. |
src/main/fork-heimdall/control-plane.test.ts |
Updates enrollment test doubles. |
src/main/fork-heimdall-pipeline/ssh-link-reader.ts |
Reads remote symlink targets. |
src/main/fork-heimdall-pipeline/precheck-extra-env.test.ts |
Tests precheck environment merging. |
src/main/fork-heimdall-pipeline/pipeline-store-test-fixtures.ts |
Adds in-memory store fixture. |
src/main/fork-heimdall-pipeline/pipeline-report-path.ts |
Defines report locations. |
src/main/fork-heimdall-pipeline/pipeline-report-path.test.ts |
Tests report paths. |
src/main/fork-heimdall-pipeline/pipeline-enrollment-table.ts |
Defines pipeline side tables. |
src/main/fork-heimdall-pipeline/pipeline-binding.ts |
Binds runtime pipeline services. |
src/main/fork-heimdall-pipeline/pipeline-action-dispatch-contracts.ts |
Defines dispatcher contracts. |
src/main/fork-heimdall-pipeline/orca-gitignore-rules.ts |
Manages pipeline re-inclusion. |
src/main/fork-heimdall-pipeline/orca-gitignore-rules.test.ts |
Tests ignore rewriting. |
src/main/fork-heimdall-pipeline/issue-command-orca-gitignore.test.ts |
Tests issue-command fallback. |
src/main/fork-heimdall-pipeline/check-node-executor.ts |
Executes check nodes. |
src/main/fork-heimdall-pipeline/builtin-one-node-kind.ts |
Wraps built-in watcher kinds. |
src/main/fork-heimdall-pipeline/approval-notification-copy.ts |
Formats approval notifications. |
src/main/fork-heimdall-pipeline/answer-attribution.ts |
Attributes pipeline answers. |
src/main/fork-heimdall-objective/definition.ts |
Shares worktree enrollment logic. |
src/main/fork-heimdall-objective/check-runner.ts |
Supports environment and command preservation. |
src/main/automations/precheck-runner.ts |
Merges local extra environment. |
src/cli/root-help-text-secondary.ts |
Documents pipeline creation. |
src/cli/root-help-text-primary.ts |
Adds pipeline help entry. |
src/cli/handler-group-manifest.ts |
Registers pipeline create handler. |
src/cli/fork-heimdall/specs-manage.ts |
Documents pipeline choices. |
src/cli/fork-heimdall/specs-create.ts |
Defines pipeline create CLI. |
src/cli/fork-heimdall/create-input.ts |
Broadens create candidate kinds. |
skills/orca-heimdall/SKILL.md |
Documents pipeline operations. |
resources/skills/snapshot-registry.json |
Records updated skill snapshot. |
resources/skills/current-manifest.json |
Advances skill revision. |
package.json |
Adds React Flow dependency. |
config/scripts/run-sandboxed-test-shards.test.mjs |
Tests wire-lane selection. |
config/oxlint-dead-classes.json |
Allows pipeline CSS classes. |
config/docker/test-sandbox/README.md |
Documents wire and shard lanes. |
config/docker/test-sandbox/entrypoint.sh |
Imports baseline refs. |
config/docker/test-sandbox/Dockerfile |
Adds newer Git and lsof. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| connection(): Database.Database { | ||
| return this.scoped.connection() | ||
| const connection = this.scoped.connection() | ||
| if (!this.pipelineSideTablesEnsured && !this.scoped.isReadOnly()) { | ||
| ensurePipelineSideTables(connection) | ||
| this.pipelineSideTablesEnsured = true | ||
| } |
There was a problem hiding this comment.
Fixed in 6d2fda6. Upstream has no Heimdall, so the realistic case is a newer fork build that bumped heimdall.db without ever creating the pipeline side tables. PipelineAwareEnrollmentStore now checks for the tables when the database is read-only and falls back to built-in-only results for get, list, findLiveByWorkspace, pendingKindPurges and pipelineRowsClaimedByBuiltin. A regression test opens such a database read-only.
|
| if (!allResolved) { | ||
| continue | ||
| } | ||
| const nextStatus: PipelineNodeRunState['status'] = anySatisfied ? 'ready' : 'skipped' |
There was a problem hiding this comment.
Unmatched branches complete the run When a Decision uses a text or number output and none of its
when values matches, this code skips every downstream branch. Skipped sink nodes count as complete, so the pipeline can report success without running the intended work, including Land. Require a matching branch or fallback instead of completing the run.
There was a problem hiding this comment.
Fixed in 64f8d06. Skipped sinks still count as complete, because a branch that legitimately isn't taken must not stall the run. A done Decision whose value matches none of its when edges now stops the run as pipeline-configuration-error (park), with the node and value in the detail, e.g. kindPayload.document.nodes.route.on: value "Bug" matches no branch. Covered by a new stop-verdict.test.ts for both the unmatched and matched cases.
| ): OutputRefParts | null { | ||
| const parts = outputRefParts(reference) | ||
| if (parts === null) { | ||
| return null | ||
| } |
There was a problem hiding this comment.
Missing inputs render empty A prompt can reference
$run.inputs.taks even if taks is not declared in document.inputs: validation ignores input references, and rendering replaces the missing value with an empty string. An Agent or Swarm can therefore run with a silently incomplete task prompt. Validate these references against the declared inputs.
There was a problem hiding this comment.
Fixed in 47f98df. $run.inputs.<name> references in prompts, Land text, script inputs and decision/loop/swarm expressions are now checked against document.inputs and fail validation when undeclared. A declared optional input with no default still renders empty by design. This also caught a skill-guide example that used task alongside other declared inputs; task is only implicit when inputs is omitted, so the example now declares it.
| await ensurePipelineDirectory(runtime, paths) | ||
| recordSelfWrite(paths.yamlPath, yamlText, runtimeEnvironmentId, SELF_WRITE_REMOTE_TTL_MS) | ||
| await writeRuntimeFile(runtime, paths.yamlPath, yamlText) | ||
| recordSelfWrite(paths.layoutPath, layoutText, runtimeEnvironmentId, SELF_WRITE_REMOTE_TTL_MS) | ||
| await writeRuntimeFile(runtime, paths.layoutPath, layoutText) |
There was a problem hiding this comment.
Concurrent edits can be overwritten A repository pipeline save checks the disk signature before reaching this unconditional YAML and layout write. If an external editor changes either file between the check and the write, its changes can be overwritten without a conflict banner. Protect the write against that race.
There was a problem hiding this comment.
Right that it isn't atomic: the disk-signature check and the YAML/layout writes are separate calls, and the shared fs:writeFile / files.write path has no expected-signature option. The window is a few round trips. The main editor save is looser still, since it has no save-time disk check and relies on the file watcher (editor-save-queue.ts, editor-autosave.ts). Closing it fully means adding compare-and-write to the shared file RPC, which is upstream-owned and part of the remote wire contract, so I'm keeping this consistent with the editor and tracking it separately rather than building a fork-only primitive here.
There was a problem hiding this comment.
That trade-off is reasonable. The race is real, but closing it correctly requires changing the shared file RPC and its remote wire contract; adding a fork-only compare-and-write path here would make pipeline saves behave differently from the editor and create a larger compatibility surface. I’m treating this as a known, separately tracked limitation rather than an actionable issue for this PR.
| @@ -0,0 +1,119 @@ | |||
| import { spawnSync } from 'node:child_process' | |||
There was a problem hiding this comment.
Direct child processes violate policy This new sandbox baseline script imports
spawnSync from node:child_process and uses it to start Git and tar. The repository requires Windows child processes to go through runProcess or spawnProcess in src/shared/child-process/, never directly through child_process. The same pattern appears elsewhere in this script and its test; satisfy this requirement before merging.
Context Used: AGENTS.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
The runProcess/spawnProcess rule covers shipped app code, and its ratchet (child-process-import-boundary.test.ts) only scans src/**/*.ts(x). This is a dev-side script under config/scripts. Its only caller, run-sandboxed-test-shards.mjs, imports spawnSync from node:child_process itself, as do about 30 other upstream scripts there. It just builds the tar sent to the Linux Docker test host with fixed-argv git/tar calls, so none of the Windows .cmd or quoting problems the wrapper exists for apply. Leaving it as is.
There was a problem hiding this comment.
That’s a fair distinction. The runProcess/spawnProcess boundary is enforced for shipped src/**/*.ts(x) code, and this helper is a developer-side config/scripts/**/*.mjs utility alongside existing scripts that use spawnSync. Given its fixed-argv local git/tar calls and the absence of any matching ratchet for config scripts, I’m withdrawing the direct-child-process finding; no change is needed here.
… rounds A gate or onFail send-back to a loop body node was dropped once the loop had run two or more rounds, because repair dedupe compared per-node epochs that loop rounds advance independently. Dedupe now compares ledger dispatch order. Also scopes loop acceptance and send-back comments to the epoch they were made in, and stops rendering an approve verdict as reviewer objections.
A re-run Merge (after a send-back or a loop round) read prior-epoch 'applied' rows and went done without merging the new children. Merge progress lookups now use only the Merge's current epoch, merge decisions read the swarm epoch from the run state, and a Merge whose retry budget is spent stays failed so the retries-exhausted choice is offered.
A Decision on a json, file or taskList output, and any reference to a Swarm's outputs, validated but hung or rendered empty at runtime. Both are now invalid-output-ref errors.
…runs pipelineRunView rejected every runtime-kind caller with a connection id, which includes the local desktop renderer, so remotely owned runs never rendered. Only paired runtime forwarders are rejected now.
…shes Every fleet snapshot refetched the run view and swapped the graph for a loading placeholder, closing an open gate dialog and discarding a typed send-back comment.
The next upstream sync would reset these files and silently drop the coverage. The tests now live in fork-owned files and the upstream files match main.
…raction i18next-cli resolved translate(copy.key, ...) in the gate dialog and run form to the local `key` array in makePipelineNodeEvidenceKey and extracted a phantom 'node' key, failing verify:localization-extraction.
…lasses Upstream's new shadcn(no-unknown-classes) rule flags the canvas's BEM classes from fork-heimdall-pipeline/pipeline-canvas.css. Allow pipeline-* through a declared registration seam in oxlint-dead-classes.json.
A .gitignore with /.orca/ kept pipelines ignored: the re-include appended !.orca/pipelines/ under a parent exclusion git never lifts. Accept the optional leading slash in all three exact-rule patterns.
… pipeline tables A heimdall.db bumped past this build's schema by a build that never created the pipeline side tables opens read-only, and boot then failed with 'no such table: heimdall_pipeline_enrollment'. Fall back to the built-in store when the database is read-only and the tables are absent.
A typo like $run.inputs.taks validated cleanly and rendered as an empty string. Validate input references in prompts, Land text, script inputs and decision/loop/swarm expressions against document.inputs. The Heimdall skill guide's example relied on an implicit task input alongside declared inputs, which the schema only provides when inputs is omitted; declare it.
A Decision on a text or number output whose value matched none of its when edges skipped every branch, and skipped sinks count as complete, so the run reported pipeline-complete without doing the work (Land included). Park it as a pipeline-configuration-error naming the node and the value instead.
Declare the workspace permission every RPC method now requires, and drop the preload drop-boundary test: upstream removed the preload file-drop listener it exercised, so pipeline node drags no longer pass through it.
Upstream replaced the SSH relay with orcad, so pipeline file, check, tracking and protected-digest reads now run local-only and refuse SSH hosts, matching the objective kind. Repoints renderer imports at the split runtime file clients, routes renderer host lookups by the workspace owner instead of the focused server, drops the pipeline readlink seams, and renames symbols the new anti-slop rule rejects.
Main's WSL mover now requires every SQLite schema file and table to carry a disposition, and its Vitest boundary requires real-SQLite tests to run in the Node runtime project. List the pipeline database, the pipeline enrollment side tables, and the two pipeline tests that open SQLite. The orchestration adapter test spied on a runtime method main removed; mock the trust module instead.
dff2317 to
32080ba
Compare


ELI5
Heimdall can now run pipelines you draw yourself. You drop nodes onto a canvas: an agent, a check, a human approval, a fan-out "swarm" of agents, or a "land" step that opens a PR. You wire them together, save, and press Run. Heimdall walks the graph, asks you before anything risky, and ends with a pull request. The existing Objective and PR-sitter watchers show up as one-node pipelines and behave exactly as before.
What Changed
Before: Heimdall had two fixed watcher kinds, Objective and PR sitter. Changing how work flowed meant changing code.
After:
.orca/pipelines/<id>.yaml(logic) plus<id>.layout.json(positions), or a personal pipeline in the profile. Node types are Agent, Check, Script, Decision, Loop, Swarm, Merge, Human gate and Land, plus Objective and PR sitter as composite nodes.pipelinewatcher kind. Pipeline rows live in side tables (pipeline.db), soheimdall.dbstays at schema 4 and older Orca builds keep reading the fleet.orca heimdall create --pipeline, andapprove --choicefor engine choices such as retry, skip or abort.heimdall.pipeline.v1never see pipeline rows.Engine fixes found by live acceptance and a final adversarial review:
onFailsend-back to a node inside a loop was silently dropped once the loop had run two or more rounds. The operator's comment was lost and only downstream nodes re-ran. Loop rounds advance only the loop body's epochs, so "already repaired" now compares ledger dispatch order instead of epoch numbers. Loop acceptance and send-back comments are scoped to the epoch they were made in, and an approve verdict is no longer shown to the next fixer as objections.doneand exposesprUrl,prNumber,branch,providerandheadShafor the PR-sitter composite.$run.inputs.<name>validated cleanly and rendered empty. It now fails validation.heimdall.dbbumped by a newer build that never created the pipeline tables now opens read-only with built-in watchers, instead of failing boot./.orca/and/.orcaare now recognized when re-including pipeline files.Why
The logic spec chose composite nodes for the built-ins, because their logic doesn't decompose into typed nodes without changing behavior. Side tables keep downgrade safe. One validator, one content hash and one choice-options function are shared by the canvas, CLI, host and control plane, so the surfaces can't disagree about what a pipeline means or what choices a stuck node offers.
Linked Issue
N/A (fork feature, maintainer)
Visual Proof
[ASK: the live-run screenshots were in a temp folder that has since been cleared; attach fresh captures of the canvas, a completed Bugfix run graph, and a completed Swarm run graph]
Testing
Live acceptance ran in an isolated, hidden dev profile (
ORCA_BACKGROUND_LAUNCH=1, driven over CDP only):b5775ad9-d785-496c-8a60-61db4c707ac9).## Send-back commentand the comment text, with no stale reviewer objections. Review and Verify re-ran, the gate was offered again, and after approval Land opened https://github.com/zpyoung/orca-pipeline-smoke-20261001-6fmmmu/pull/2. The run endedpipeline-complete.worktree: own. All 5 children ran in their own worktrees about 8 s apart, and the run completed.Automated:
onFail);typecheck:node,typecheck:webandtypecheck:clipass.typecheck:e2ehas pre-existing errors in files this branch doesn't touch.pnpm lintchain passes, including the changed-code gate and the localization verifiers..d.tsguards.palette-match-performance.test.ts(ledgerbug-288), which fails the same way on the base branch on that host.Tested on macOS only. SSH-hosted runs, Linux and Windows were not exercised.
AI Disclosure
Implemented with Claude Code (Opus) and omp/Codex workers. Reviewed with a multi-agent Claude review whose findings were each verified independently before fixing.
Review
Start with
src/shared/fork-heimdall-pipeline/interpreter/(decide, run-state, state-history), thensrc/main/fork-heimdall-pipeline/(executors and action dispatch). The shared-runner change that every watcher kind runs is insrc/main/fork-heimdall/judgment/mailbox-refresh.ts.Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
.gitand.orca. In the live run that swept a memory plugin's files into the PR (ledgerproposal-289).no-unknown-classesrule flags the canvas's BEM classes, sopipeline-*is allowlisted through a declared seam inconfig/oxlint-dead-classes.json. Moving the canvas to Tailwind is deferred (ledgerdeferred-295).pnpm-lock.yamlis now a permanent fork exception, because this branch adds@xyflow/reactandpackage.jsonis already one. Main's passthrough seam for the pnpm 12.5.1 lines was dropped, since the exception covers the whole file and the guard forbids both.palette-match-performance.test.ts(ledgerbug-288) fails the same way on the base branch there. Upstream's matcher is left untouched.bug-294).Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)