fix(review): apply code-review fixes — runId/foreachNodeId wiring, worktree-leak cleanup, rework re-execution, instance pruning, SIGKILL fallback, type dedup, board memo split, agent-native field-schema context + fn_workflow_get

17 findings from 12-reviewer code review applied:
- P1 runId trio (pin-probe/resume/markIntegrated used placeholder runId; 4-reviewer corroboration) + production-wiring tests
- P1 worktree/branch release on instance failure/exhaustion/abort
- P2 runGraphTaskStep no longer masks step-session failures; rejected memo cleared so rework re-executes
- P2 clearStaleInstanceStates wired at run start/end (mirrors branch pruning)
- P2 code-node timeout killSignal SIGKILL; dead template-recursion removed
- P1/P2 field-type re-declarations replaced with @fusion/core imports (stale comments removed)
- P2 Board memo split + TaskCard comparator stringify guard + modal prop-driven field defs
- HIGH agent-native: executor prompt injects custom-field schema/values; self-correcting rejection text; fn_workflow_get; fn_task_update bare-call guard; integration-conflict task log

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-06-04 14:01:55 -07:00
parent 94da14cd81
commit 3ebaa321f8
24 changed files with 1142 additions and 160 deletions

View File

@@ -334,6 +334,11 @@ function defaultSpawnRunner(params: {
{
cwd: params.cwd,
timeout: params.timeoutMs,
// Ensure the timeout actually KILLS a child that traps/ignores SIGTERM:
// execFile defaults to SIGTERM, which a long-running or signal-trapping
// script can swallow, letting it outlive the timeout. SIGKILL cannot be
// trapped, so the timeout is enforceable.
killSignal: "SIGKILL",
// Minimal env: PATH + a few harmless basics; no inherited secrets beyond
// what the worktree-scoped script tier already has access to (KTD-15:
// same trust as existing script steps).
@@ -390,13 +395,10 @@ export async function validateCodeNodeSources(
error: err instanceof CodeNodeError ? err.message : String(err),
});
}
// Recurse into foreach templates (code nodes are legal inside them, KTD-15).
const template = (node.config as { template?: { nodes?: WorkflowIrNode[] } } | undefined)?.template;
if (template?.nodes) {
failures.push(...(await validateCodeNodeSources({ nodes: template.nodes })));
}
// (A `code` node has no `template` — the only template recursion is the
// foreach pass below; the prior code-node-loop recursion here was dead.)
}
// Also recurse into any foreach templates at the top level.
// Recurse into any foreach templates (code nodes are legal inside them, KTD-15).
for (const node of ir.nodes) {
if (node.kind !== "foreach") continue;
const template = (node.config as { template?: { nodes?: WorkflowIrNode[] } } | undefined)?.template;