name: bug-ancestor-auto-advance version: 1 description: >- M43 demo โ€” script-only auto-advance for a bug whose parent milestone carries the opt-in tag. Functionally what R1 (bug-ai-resolve-seed) does today, minus the per-bug tagging step: the trigger rule matches on the PARENT's tag (match.ancestor, spec/workflow-triggers.md ยง3c), this workflow re-checks the link in-band, tags the bug `ai-resolve` (so the existing R2 verify rule picks it up), then transitions it to verify-pending. Zero LLM nodes. runtime: script input: # A freshly-created bug has no flow_state yet, so eligibility sees its # lifecycle state (ItemView.workflow_state = flow_state or state). Accept # both lifecycle spellings seen across backends. state: pending tags_required: [] tags_forbidden: [blocked, paused, ai-resolve] required_artifacts: [] escalation_input_states: [pending, open] output: state: verify-pending scope_budget: # Schema minimum is 1; no node here touches a repo, so these are nominal. files_modified_max: 1 lines_diff_max: 1 wall_clock_seconds_max: 300 nodes: # Gate: re-verify in-band that the parent milestone still carries the # opt-in tag (the trigger's ancestor read may be up to 60s stale on the # consumer path, WT-ANC-5). Fails closed โ€” refuse_dispatch on a miss. - id: parent-link-check kind: script cmd: scripts/workflow/parent-link-check on_fail: refuse_dispatch runtime_env: CP_URL: "https://agents.oreillyit.nz/api" WORKFLOW_ITEM_UUID: "${item.uuid}" PARENT_LINK_TAG: auto-resolve-bugs PARENT_LINK_RELATION: parent # Opt the bug into the existing verify pipeline (R2 bug-ai-resolve-verify # requires tags_required: [ai-resolve]). - id: tag-ai-resolve kind: script cmd: scripts/workflow/tag-set depends_on: [parent-link-check] on_fail: escalate runtime_env: CP_URL: "https://agents.oreillyit.nz/api" WORKFLOW_ITEM_UUID: "${item.uuid}" TAG_SET_ADD: ai-resolve # Advance the bug; R2 then dispatches bug-verify-sonnet@1 at verify-pending. - id: state-tx kind: script cmd: scripts/workflow/state-tx depends_on: [tag-ai-resolve] on_fail: escalate runtime_env: CP_URL: "https://agents.oreillyit.nz/api" STATE_TX_NEW_STATE: verify-pending STATE_TX_FROM_STATES: "pending,open" # NOTE (script-node credentials): kind: script nodes are harness-exempt # (WF-COMP-6), but the flag-on script path composes the workflow-script/v1 # composite (shared-variables/v1 + cp-service-token/v1; WF-COMP-31). The # cp-service-token/v1 layer restages the AU-51 internal-service bearer token # and exports CP_SERVICE_TOKEN_FILE=/run/agent/cp-service-token/token, which # all three nodes above read via # `open(os.environ["CP_SERVICE_TOKEN_FILE"]).read().strip()`. The legacy # WF-COMP-26 mount (`secrets_required: [CP_SERVICE_TOKEN]` and # `runtime_env.CP_SERVICE_TOKEN_FILE=/run/secrets/CP_SERVICE_TOKEN`, backed by # the dispatcher's legacy-key branch) is removed (WF-COMP-33 step 10). Each # script still resolves its own actor identity (OIDC_IDENTITY_EMAIL or # CP_Caller-Identity header โ€” see scripts/workflow/tag-set and # parent-link-check) for the write envelope. # # STATE_TX_FROM_STATES on the state-tx node is the compare-and-set guard: the # live flow_state must be one of the listed states (or already the target), # else state-tx exits 2 (unexpected_current_state). pending,open mirror # `input.state` + `escalation_input_states`.