---ci---
phase: 4
milestone: v1.0
status: execute
persona: backend-engineer
task: T-4.3
requirements:
covered: [REQ-12]
---/ci---
Wave 1, task T-4.3. Replaces the Phase 01 issue-to-contract.yml skeleton
with the real L3B trigger (D-030). On issue opened, the workflow checks out
the acdl repo at milestone/v1.0-initial (branch-pin rule) to obtain
l3b_agent_stub.py, parses the Issue body into contract.yaml, commits it to
a new branch contract/<issue-number> on acdl-contracts via the Gitea
file-contents API using the new_branch field (single POST creates the
branch + file), comments on and closes the Issue, then dispatches the
pipeline workflow on acdl via POST .../actions/workflows/pipeline.yml/
dispatches with inputs contract-ref=contract/<issue-number>
(cross-repo trigger per D-014). The `on:` key is quoted as "on": so
PyYAML parses it as a string key.
---ci---
phase: 4
milestone: v1.0
status: execute
persona: backend-engineer
task: T-4.2
requirements:
covered: [REQ-10]
---/ci---
Wave 1, task T-4.2. Replaces the Phase 01 pipeline.yml skeleton with the
real 3-dispatch approval-gate topology (D-027/D-028). workflow_dispatch
inputs contract-ref/approve_qa/approve_prod drive four jobs: dev (policy +
confidence gate + mock_executor + evidence, persist via finalize_evidence),
qa-gate (records approval), prod-gate (records approval), finalize
(needs: prod-gate, commits final audit.json to acdl-evidence). Each stage
persists its audit.json to acdl-evidence via the file-contents API since
Gitea Actions artifacts do not survive re-dispatch. The `on:` key is quoted
as "on": so PyYAML parses it as a string key (it would otherwise be coerced
to the boolean True).
---ci---
phase: 4
milestone: v1.0
status: execute
persona: backend-engineer
task: T-4.1
requirements:
covered: [REQ-10]
---/ci---
Wave 1, task T-4.1. Adds scripts/finalize_evidence.py, a stdlib-only helper
that uploads a local audit.json to the acdl-evidence Gitea repo via the
file-contents API. It GETs the existing file to discover its sha (update
mode) and falls back to create mode on 404, then PUTs/POSTs the base64-encoded
content with the Authorization: token <token> header. This is the per-stage
state-persistence mechanism (D-028) used by the pipeline jobs between
re-dispatches, and the finalize-step writer (D-029).
---ci---
phase: 4
milestone: v1.0
status: research
research:
gitea_actions_capabilities:
upload_artifact_v3: supported (v4 NOT supported by act_runner)
artifacts_cross_dispatch: NOT preserved (re-dispatch starts a new run)
workflow_dispatch_api: POST /actions/workflows/{filename}.yml/dispatches
workflow_call: supported; uses: <owner>/<repo>/.gitea/workflows/<file>@<ref>
checkout_cross_repo: actions/checkout@v4 with repository + ref + token
secrets: ${{ secrets.GITEA_TOKEN }} must be a manually-created PAT (auto-token is current-repo only)
approval_gate: workflow_dispatch input (approve_qa, approve_prod); no native pause-and-wait
pipeline_design:
topology: single pipeline.yml with workflow_dispatch inputs (contract-ref, approve_qa, approve_prod)
stages: 3 separate dispatches (initial dev, qa-approve, prod-approve+finalize)
state_persistence: each stage writes evidence to acdl-evidence via file-contents API (PUT audit.json)
job_if_conditions: dev runs when !approve_qa && !approve_prod; qa-gate when approve_qa && !approve_prod; prod-gate+finalize when approve_prod
personas: no change; backend-engineer owns the workflow YAML + finalize + issue trigger; lead-developer owns verify_phase04.sh
---/ci---
ARCHITECTURE.md gains a 'Phase 04 pipeline topology (research)' section:
the artifact-vs-re-dispatch limitation forces 3-dispatch topology with
evidence persisted to acdl-evidence (PUT audit.json) between dispatches.
PERSONAS.md is unchanged for Phase 04 (backend-engineer + lead-developer
active; infra-stub-engineer idle; frontend-engineer still off).
---ci---
phase: 4
milestone: v1.0
status: clarify
decisions:
- id: D-027
decision: Two workflows: pipeline.yml (workflow_call + workflow_dispatch) and issue-to-contract.yml (issues.opened); gates via workflow_dispatch approve_qa/approve_prod inputs
rationale: Gitea has no environment reviewers, no repository_dispatch, no native approval UI; D-013 fallback
confidence: 0.85
alternatives: [single long-running workflow that polls, external approval bot]
- id: D-028
decision: All 4 stages in one workflow run; state passed via upload/download-artifact; gates re-dispatched with approve inputs
rationale: Gitea supports upload/download-artifact; alternative is committing state between jobs (heavier)
confidence: 0.80
alternatives: [commit state.json + audit.json to a state branch between jobs]
- id: D-029
decision: Finalize commits audit.json to acdl-evidence main via the Gitea file-contents API (same mechanism as Phase 01 index.html push)
rationale: D-012 raw-URL requires the file to be on main; the API is the only way to put it there from a step
confidence: 0.90
alternatives: [clone acdl-evidence in the step, copy file, commit, push]
- id: D-030
decision: Issue-to-contract workflow checks out l3b_agent_stub from acdl, parses Issue, commits contract.yaml to contract/<issue-number> branch on acdl-contracts, then dispatches pipeline via workflow_dispatch API
rationale: Gitea Actions cannot trigger cross-repo without an explicit API call; the branch carries the contract ref
confidence: 0.85
alternatives: [push contract to a sentinel branch on the acdl repo itself]
---/ci---
Phase 04 has real pipeline-topology ambiguities (Gitea's gaps vs the spec's
approval-gate intent). Four decisions logged: D-027 two-workflow topology
+ dispatch-input gates, D-028 artifact-based state passing, D-029 finalize
commits via file-contents API, D-030 issue workflow checks out
l3b_agent_stub from acdl and dispatches the pipeline.
---ci---
phase: 1
milestone: v1.0
status: research
research:
gitea_capabilities:
pages: not_supported
environments_api: not_supported
repository_dispatch: not_supported
workflow_call: supported
workflow_dispatch: supported
issues_opened: supported
workarounds:
- D-012 raw file URLs in place of Pages
- D-013 workflow_dispatch approval inputs in place of environments
- D-014 workflow_dispatch API in place of repository_dispatch
verification_toolchain:
typecheck: bash -n + python -m py_compile (no package.json)
test: per-phase scripts/verify_phaseNN.sh
build: no-op
---/ci---
ARCHITECTURE.md gains a Gitea API surface table and a branch-pinning rule.
PERSONAS.md is the canonical project-level persona roster: lead-developer
and backend-engineer always active; infra-stub-engineer custom persona owns
L1 stubs; data-engineer deactivated (no DB); frontend-engineer deactivated
until Phase 05.
---ci---
phase: 1
milestone: v1.0
status: clarify
decisions:
- id: D-011
decision: Single-project mode explicitly enforced via config.json mode=single
rationale: run.md Step 0 reads projects[] length as multi-project trigger; explicit flag disambiguates from D-010
confidence: 0.95
alternatives: [move acdl into .ciagent/acdl/ subdirectory and adopt multi-project paths]
- id: D-012
decision: Gitea has no native Pages; serve acdl-evidence via raw file URLs + CORS note
rationale: Research confirms Gitea has no [pages] section; raw URLs work without server config
confidence: 0.85
alternatives: [sidecar static server, external Pages host]
- id: D-013
decision: QA/Prod gates modeled as workflow_dispatch approval inputs (D-004 fallback) instead of Gitea environments
rationale: Research confirms Gitea ignores environment: blocks and exposes no environments API
confidence: 0.90
alternatives: [external approval bot, drop approval gates entirely]
- id: D-014
decision: Cross-repo triggering uses workflow_dispatch API from inside a step (no repository_dispatch)
rationale: Gitea Actions does not support repository_dispatch
confidence: 0.85
alternatives: [push-based trigger with a sentinel file, polling]
- id: D-015
decision: New repos acdl-contracts and acdl-evidence use default_branch=main with auto_init=true
rationale: Matches Gitea DEFAULT_BRANCH=main; required for the default branch to exist before any push
confidence: 0.95
alternatives: [use milestone/v1.0-initial as default_branch]
- id: D-016
decision: Pages placeholder for Phase 01 is a minimal HTML stub; full timeline UI deferred to Phase 05
rationale: Phase 01 success criterion is the URL returns 200 with placeholder; full UI is Phase 05
confidence: 0.90
alternatives: [build a minimal timeline now]
---/ci---
Clarifications accepted at full autonomy per clarify.md Step 4. Three requirements
re-stated: REQ-09 (new repos default_branch=main), REQ-10 Pages (raw-URL 200
substitute), REQ-10 environments (workflow_dispatch inputs + qa/prod branches).
See .ciagent/REQUIREMENTS.md Clarifications table.
---ci---
phase: 0
milestone: v1.0
status: specify
security:
- id: SEC-001
type: info_disclosure
disposition: mitigated
summary: Literal API token was committed in config.json gitea.api_token_env field
fix: Replaced literal with env var name 'ACDL_GITEA_TOKEN'; token supplied via shell env at runtime
severity: high
stride: Information Disclosure
---/ci---
The 40-char value previously stored in .ciagent/config.json was a live Gitea
API token. Per the spec constraint 'no secrets in repo', the field now holds
an env var name. The token itself is exported in the shell session at runtime
and is never written to disk. Treat the prior value as already-leaked and
rotate it via the Gitea UI before any external disclosure.