diff --git a/.ciagent/PROJECT.md b/.ciagent/PROJECT.md index 320dbbd..c6aaddd 100644 --- a/.ciagent/PROJECT.md +++ b/.ciagent/PROJECT.md @@ -89,4 +89,7 @@ Build a runnable demo (Linux + GitHub/Gitea Actions) that walks executives throu | D-027 | Phase 04 models the pipeline as TWO Gitea Actions workflows: (1) `acdl/.gitea/workflows/pipeline.yml` — `on: workflow_call` + `on: workflow_dispatch` (so it can be both called by the contracts-repo trigger AND manually re-dispatched for approvals); (2) `acdl-contracts/.gitea/workflows/issue-to-contract.yml` — `on: issues [opened]`. Approval gates are implemented as separate workflow_dispatch inputs (`approve_qa: bool`, `approve_prod: bool`) on the pipeline workflow, since Gitea ignores `environment:` blocks (D-013) | Gitea Actions has no environment reviewers, no `repository_dispatch`, no native approval UI | Pipeline can be re-dispatched by a human at each gate; the workflow_dispatch API call from a step (D-014) drives cross-repo triggering | | D-028 | The pipeline workflow runs all 4 stages (dev, qa-gate, prod-gate, finalize) in a single workflow run, with each gate job checking a workflow_dispatch input (`approve_qa`/`approve_prod`). When the input is false (the default), the gate job fails with a clear "awaiting approval" message; the human re-dispatches with `approve_qa=true` to advance. State (state.json, audit.json, contract ref) is passed via workflow artifacts (upload/download between jobs) because Gitea Actions artifacts work the same as GitHub Actions | Gitea Actions supports `actions/upload-artifact` and `actions/download-artifact`; the alternative is committing state between jobs, which is heavier | Deterministic, observable pipeline; artifacts keep the audit trail within one run | | D-029 | The finalize step commits `audit.json` to `acdl-evidence` main via the Gitea file-contents API (POST `/repos/{owner}/{repo}/contents/{path}` with the base64 content + a commit message referencing the pipeline run id), exactly like Phase 01's `gitea_setup.sh` does for `index.html`. It uses `${GITEA_TOKEN}` (a repo secret) for auth | D-012 raw-URL approach requires the file to be on main; the API is the only way to put it there from a workflow step | The evidence timeline (Phase 05 UI) fetches the raw URL after finalize completes | -| D-030 | The issue-to-contract workflow in `acdl-contracts` checks out `l3b_agent_stub.py` from the `acdl` repo (pinned to `@milestone/v1.0-initial` per the branch-pin rule), parses the Issue body, commits `contract.yaml` to a new branch `contract/` on `acdl-contracts`, then dispatches the pipeline workflow on the `acdl` repo via `curl POST /actions/workflows//dispatches` with `inputs: {contract-ref: contract/}` (D-014). The pipeline workflow checks out `acdl-contracts` at that ref to read the contract | Gitea Actions cannot trigger across repos without an explicit API call; the branch carries the contract ref | Reproducible Act 3: Issue → contract.yaml → pipeline run with the same contract as Act 2 | \ No newline at end of file +| D-030 | The issue-to-contract workflow in `acdl-contracts` checks out `l3b_agent_stub.py` from the `acdl` repo (pinned to `@milestone/v1.0-initial` per the branch-pin rule), parses the Issue body, commits `contract.yaml` to a new branch `contract/` on `acdl-contracts`, then dispatches the pipeline workflow on the `acdl` repo via `curl POST /actions/workflows//dispatches` with `inputs: {contract-ref: contract/}` (D-014). The pipeline workflow checks out `acdl-contracts` at that ref to read the contract | Gitea Actions cannot trigger across repos without an explicit API call; the branch carries the contract ref | Reproducible Act 3: Issue → contract.yaml → pipeline run with the same contract as Act 2 | +| D-031 | Phase 05 "dry run" = a local bash script (`scripts/run_demo.sh`) that simulates the full pipeline by calling the core scripts in sequence + writing evidence events via `evidence_writer.py` + uploading `audit.json` to `acdl-evidence` via `finalize_evidence.py`. It does NOT use act_runner (no runner is registered in this environment). It exercises all 4 acts: (1) Friction — a static "manual 2-week" log entry; (2) Developer Self-Service — a valid `contract.yaml` for `l2-commodity-price-feed`, full pipeline (dev→qa→prod→finalize), all evidence events; (3) Citizen Developer — an Issue body, `l3b_agent_stub.py` produces the contract, identical pipeline; (4) Safety Net — a malicious `public-ingress: true` contract for `l2-regulatory-reporting`, dev rejects with confidence < 0.50, rejection visible in the timeline | The spec says "4 scripted acts reproduce deterministically in a dry run"; without a runner, the bash simulation IS the deterministic reproduction | The same `audit.json` shape is produced as a real pipeline run would produce, so the `index.html` UI renders the timeline identically | +| D-032 | `index.html` (vanilla JS) is committed to the `acdl` repo at `evidence-ui/index.html` as the source of truth, and pushed to `acdl-evidence` main by `scripts/run_demo.sh` (via the file-contents API) alongside `audit.json`. The UI fetches `audit.json` from the same raw-URL origin (D-012). It renders events as a vertical timeline with `seq`, `ts`, `stage` (color-coded), `event` text, and a truncated `hash` per event. No frameworks; one HTML file with inline CSS + JS | D-012 raw-URL approach; the UI must be a single file (no separate JS/CSS) for simplicity; vanilla JS per REQ-14 | The UI loads in any browser by visiting the raw URL; it fetches the sibling `audit.json` and renders | +| D-033 | The `audit.json` raw URL on `acdl-evidence` main is the single source of truth for the timeline. `run_demo.sh` writes the final `audit.json` (after all 4 acts) and the final `index.html` in two API calls. Re-running `run_demo.sh` overwrites both (idempotent). The UI's fetch URL is relative (`./audit.json`) so the same `index.html` works against any raw-URL origin | D-012 + D-029; relative URL avoids hardcoding the host | Deterministic re-run; UI always reflects the latest audit | \ No newline at end of file