{"record":{"id":"2ab1ea4c595b4a05","repo":"coleam00/Archon","slug":"node-loop-interactive-deprecated","errorCode":"node_loop_interactive_deprecated","errorMessage":"Node '${id}': node-level loop 'interactive:' is deprecated. A future release re-expresses the interactive loop as a gate + loop_group composition (#2707 step 3). Continue using it for now.","messagePattern":"Node '(.+?)': node-level loop 'interactive:' is deprecated\\. A future release re-expresses the interactive loop as a gate \\+ loop_group composition \\(#2707 step 3\\)\\. Continue using it for now\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/workflows/src/loader.ts","lineNumber":472,"sourceCode":"          `Node '${id}': 'approval.on_reject' is deprecated. Declare 'approval.decisions' ` +\n          `and wire a rework node with \"when: \\\\\"$${id}.output.decision == 'reject'\\\\\"\" ` +\n          'instead (loop it with loop_group if it should iterate). This gate keeps running ' +\n          'via the legacy mechanism until migrated.';\n        warnings.push(message);\n        getLog().warn({ id, warning: message }, 'node_on_reject_deprecated');\n      }\n    }\n  }\n  const interactiveLoop =\n    (isLoopNode(node) && node.loop.interactive === true) ||\n    (isLoopGroupNode(node) && node.loop_group.interactive === true);\n  if (interactiveLoop) {\n    const message =\n      `Node '${id}': node-level loop 'interactive:' is deprecated. A future release ` +\n      're-expresses the interactive loop as a gate + loop_group composition (#2707 step 3). ' +\n      'Continue using it for now.';\n    warnings.push(message);\n    getLog().warn({ id, warning: message }, 'node_loop_interactive_deprecated');\n  }\n\n  // The prose `until:` completion channel is deprecated for EVERY loop/loop_group,\n  // not only interactive ones (#2707 step 3, \"What gets deleted\"): its one stated\n  // reason to exist — \"the iteration output is a message a human reads at an\n  // interactive gate\" (#2563) — evaporates once that human interaction is a gate\n  // node with structured decision output rather than a prose sentinel. `until_bash`\n  // and (loop: only) `until_field` are the declared, structured replacements. This\n  // keeps running exactly as before; only the guidance is new.\n  if (isLoopNode(node) && node.loop.until !== undefined) {\n    const message =\n      `Node '${id}': the prose 'loop.until' completion signal is deprecated. Declare ` +\n      \"'loop.until_bash' (deterministic check) or 'loop.until_field' (a declared boolean \" +\n      'in output_format) instead (#2707 step 3). While supported, emit legacy signals as ' +\n      \"'<promise>SIGNAL</promise>' or a final standalone signal line.\";\n    warnings.push(message);\n    getLog().warn({ id, warning: message }, 'node_loop_until_deprecated');\n  } else if (isLoopGroupNode(node) && node.loop_group.until !== undefined) {","sourceCodeStart":454,"sourceCodeEnd":490,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/loader.ts#L454-L490","documentation":"Node-level `interactive: true` on a loop or loop_group (the interactive loop where iteration output is reviewed by a human) is deprecated. The planned target model re-expresses the interactive loop as a gate + loop_group composition (#2707 step 3). The loader warns but the field keeps working for now — the message explicitly says to continue using it.","triggerScenarios":"collectGateAndLoopDeprecationWarnings (via parseDagNode) on a workflow where a loop node has `loop.interactive: true` or a loop_group node has `loop_group.interactive: true` (loader.ts:472); fires on every parse.","commonSituations":"Interactive loops authored before the gate/loop_group composition model; workflows migrated from prose human-in-the-loop patterns; templates copied from older examples.","solutions":["Short-term: continue using it (the warning says so), but track the affected workflows.","Plan the migration: re-express the interactive loop as an approval/decision gate plus loop_group — gate the iteration output to a human and loop the body until approval.","Use deterministic completion checks (`until_bash`/`until_field`) during the rewrite.","Migrate before #2707 step 3 ships and the composition change alters or removes the field."],"exampleFix":"# before\nloop:\n  interactive: true\n  prompt: \"iterate\"\n# after: gate + loop_group composition\nloop_group:\n  body: [iterate]\n  gate: human_review   # approval node reading $iterate.output\n  until_bash: \"test \\\"$human_review.output.decision\\\" = 'approve'\"","handlingStrategy":"validation","validationCode":"// Detect deprecated interactive loops so they can be scheduled for migration:\nconst interactive = workflow.nodes.filter(\n  (n) => (n.type === 'loop' && n.loop?.interactive === true) ||\n         (n.type === 'loop_group' && n.loop_group?.interactive === true)\n);\nif (interactive.length) console.warn('Migrate interactive loops to gate + loop_group:', interactive.map((n) => n.id));","typeGuard":"function isInteractiveLoopNode(node: { type: string; loop?: { interactive?: boolean }; loop_group?: { interactive?: boolean } }): boolean {\n  return node.loop?.interactive === true || node.loop_group?.interactive === true;\n}","tryCatchPattern":null,"preventionTips":["Track every interactive loop (the warning fires on each parse) in a migration backlog.","Prefer the gate + loop_group composition for new human-in-the-loop loops.","Use deterministic until_bash/until_field completion checks in new loops.","Follow #2707 step 3 so migration lands before the composition change ships."],"tags":["workflow","deprecation","loop","interactive"],"backgroundTag":"deprecated-workflow-field","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}