---ci---
phase: 3
milestone: v1.0
status: verify
requirements:
covered: [REQ-04, REQ-05, REQ-06, REQ-07, REQ-08, REQ-11]
partial: [REQ-12]
lessons:
- 'set -e' + command substitution kills the parent script when the
child exits non-zero, even when 'rc=$?' follows. verify_phase03.sh
uses 'set -uo pipefail' (no set -e) so policy_checker's intended
exit 1 can be captured. Same pattern recommended for future
verify_phaseNN.sh scripts that test negative cases.
- 'mock_executor.sh' resolves modules/l2/ relative to cwd, not to the
script location. The pipeline (Phase 04) must 'cd' to the repo
root before invoking it. Documented in the I/O contract.
- Python json.dumps collapses 0.90 -> 0.9; confidence_signal emits
the JSON literal as a string to preserve the spec-mandated 0.90/0.40.
This is a demo-aesthetic choice; the parsed float is identical.
- l3b_agent_stub keyword priority matters: 'gas price' (commodity)
wins over 'compliance' (regulatory) because commodity is checked
first per D-008. The Act 3 example was crafted to hit this case.
review:
p0: 0
p1: 0
---/ci---
Layer 1 STRUCTURAL: PASS (10/10 files; bash -n + py_compile + yaml load clean; no TODO/FIXME).
Layer 2 BEHAVIORAL: PASS (verify_phase03.sh 18/18; all 9 PLAN.md must-haves met).
Layer 3 SECURITY: PASS (no secrets; subprocess calls use argv lists; hash chain is tamper-evident).
Layer 4 QUALITY: PASS (correctness, testing, security, performance, maintainability, adversarial all green).
Requirements covered this phase: REQ-04, REQ-05, REQ-06, REQ-07, REQ-08, REQ-11.
Partial: REQ-12 (l3b_agent_stub created; full issue-trigger wiring in Phase 04).
---ci---
phase: 3
milestone: v1.0
status: research
research:
l2_schema: l1s list of {name, inputs: map}; 4 L2s each referencing 5 L1s
contract_schema: stack + inputs + optional public-ingress: bool
state_json_shape: l2, l1s array (name+applied+exit_code), contract
audit_json: JSON array; canonical-JSON SHA-256 hash chain; GENESIS prev_hash
core_script_io: 5 scripts with explicit input/output/exit contracts
personas: no change; backend-engineer owns core scripts + L2 manifests; infra-stub-engineer owns L1 manifests only
---/ci---
ARCHITECTURE.md gains the L2 manifest schema, the L2 list with per-L2
L1 references (5 each, within max-depth-5), the contract.yaml schema,
the state.json shape, the audit.json event + canonical-JSON hash chain,
and a core-script I/O contract table. PERSONAS.md is unchanged for
Phase 03 (backend-engineer and infra-stub-engineer were both already
active in the project-level roster).
---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.