# ACDL pipeline workflow (Phase 04 implementation). # # 3-dispatch approval-gate topology (D-027 / D-028; ARCHITECTURE.md # "Phase 04 pipeline topology"): # # Dispatch 1 (initial): approve_qa=false, approve_prod=false # -> runs the `dev` job (policy check, confidence # gate, mock_executor, evidence + finalize). # Dispatch 2 (QA approve): approve_qa=true, approve_prod=false # -> runs the `qa-gate` job (records QA approval # in the audit chain via evidence_writer + # finalize_evidence). # Dispatch 3 (Prod approve): approve_prod=true # -> runs the `prod-gate` job, then the `finalize` # job (needs: prod-gate) which writes the final # evidence event and commits audit.json to # acdl-evidence. # # Gitea Actions limitations driving this design: # - No `repository_dispatch` trigger (D-014). # - No environments API / `environment:` blocks are ignored (D-013). # - Re-dispatch starts a NEW run; artifacts do NOT survive between runs, # so state is persisted to acdl-evidence via the file-contents API # (D-028 / finalize_evidence.py) instead of via artifacts. # # Branch-pin rule (ARCHITECTURE.md "Branch pinning rule"): # This workflow lives on `acdl`'s default branch `milestone/v1.0-initial`. # Cross-repo `uses:` references (e.g. the issue-trigger's checkout of # l3b_agent_stub.py) MUST pin to `@milestone/v1.0-initial`, NOT `@main` # (the `acdl` repo has no `main` branch). This workflow is invoked via # the workflow_dispatch API (D-014), NOT via `workflow_call`, so the # `uses:` rule applies to the issue-trigger's checkout of the acdl repo, # not to this file itself. name: acdl-pipeline "on": workflow_dispatch: inputs: contract-ref: description: "Ref on acdl-contracts that carries the contract" required: false type: string default: main approve_qa: description: "Human approval to advance past QA" required: false type: boolean default: false approve_prod: description: "Human approval to advance past Prod" required: false type: boolean default: false jobs: dev: name: "Dev (autonomous)" if: inputs.approve_qa != true && inputs.approve_prod != true runs-on: ubuntu-latest steps: - name: "Checkout acdl (this repo, pinned to milestone/v1.0-initial)" uses: actions/checkout@v4 with: ref: milestone/v1.0-initial - name: "Checkout acdl-contracts at contract-ref" uses: actions/checkout@v4 with: repository: continuous-intelligence/acdl-contracts ref: ${{ inputs.contract-ref }} token: ${{ secrets.GITEA_TOKEN }} path: acdl-contracts - name: "Policy check" run: | python3 scripts/policy_checker.py acdl-contracts/contract.yaml - name: "Confidence signal" id: confidence run: | set +e SCORE_JSON=$(python3 scripts/confidence_signal.py acdl-contracts/contract.yaml) echo "$SCORE_JSON" echo "score_json=$SCORE_JSON" >> "$GITHUB_OUTPUT" - name: "Apply or reject based on confidence (gate < 0.50)" run: | set +e SCORE=$(python3 -c "import json,sys; print(json.load(sys.stdin)['score'])" <<< '${{ steps.confidence.outputs.score_json }}') python3 -c "import sys; sys.exit(0 if float('${SCORE}') >= 0.50 else 1)" THRESHOLD_RC=$? if [ "$THRESHOLD_RC" -ne 0 ]; then python3 scripts/evidence_writer.py --stage dev --event "dev rejected: confidence < 0.50" --audit audit.json python3 scripts/finalize_evidence.py --audit audit.json exit 1 fi STACK=$(python3 -c 'import yaml; print(yaml.safe_load(open("acdl-contracts/contract.yaml"))["stack"])') bash scripts/mock_executor.sh acdl-contracts/contract.yaml python3 scripts/evidence_writer.py --stage dev --event "dev applied: ${STACK}" --audit audit.json python3 scripts/finalize_evidence.py --audit audit.json - name: "Upload dev state artifacts (best-effort)" uses: actions/upload-artifact@v3 with: name: dev-state path: | audit.json state.json qa-gate: name: "QA (manual approval)" if: inputs.approve_qa == true && inputs.approve_prod != true runs-on: ubuntu-latest steps: - name: "Checkout acdl (this repo, pinned to milestone/v1.0-initial)" uses: actions/checkout@v4 with: ref: milestone/v1.0-initial - name: "Record QA approval in evidence" run: | python3 scripts/evidence_writer.py --stage qa --event "qa approved" --audit audit.json python3 scripts/finalize_evidence.py --audit audit.json prod-gate: name: "Prod (manual approval)" if: inputs.approve_prod == true runs-on: ubuntu-latest steps: - name: "Checkout acdl (this repo, pinned to milestone/v1.0-initial)" uses: actions/checkout@v4 with: ref: milestone/v1.0-initial - name: "Record Prod approval in evidence" run: | python3 scripts/evidence_writer.py --stage prod --event "prod approved" --audit audit.json python3 scripts/finalize_evidence.py --audit audit.json finalize: name: "Finalize (publish evidence)" needs: [prod-gate] runs-on: ubuntu-latest steps: - name: "Checkout acdl (this repo, pinned to milestone/v1.0-initial)" uses: actions/checkout@v4 with: ref: milestone/v1.0-initial - name: "Write finalize event + commit audit.json to acdl-evidence" run: | python3 scripts/evidence_writer.py --stage finalize --event "pipeline complete: audit.json committed to acdl-evidence" --audit audit.json python3 scripts/finalize_evidence.py --audit audit.json