diff --git a/docs/attended-window/2026-10-11-daily-red-batch.md b/docs/attended-window/2026-10-11-daily-red-batch.md index b2c69124..1a6f488d 100644 --- a/docs/attended-window/2026-10-11-daily-red-batch.md +++ b/docs/attended-window/2026-10-11-daily-red-batch.md @@ -59,3 +59,32 @@ to zero does not revoke RBAC: recovery also removes only these newly issued bindings. Existing reviewers and consumer grants remain available during recovery. Live execution still requires T03/T04 and the ordered predecessor proof, fresh image/inventory reconciliation, server dry-run, headroom and the reviewed receipt. + +The same exact batch includes the proposed runtime naming table in +`access-engine/decisions/decisions.md` (FLEX-DEC-2026-021): namespace/chart +`access-engine`, the nine `access-engine-` names, exact DNS origins and +caller audience `access-engine`. This records the intended side-by-side rename; +the accepted binary ruling remains FLEX-DEC-2026-020. No broader-table founder +acceptance is inferred from the binary ruling. Protected consumer bindings and +grants retain their original meanings. + +## FLEX-WP-0036-T04 — new public image package + +Publish the exact reviewed Access Engine source under +`forgejo.coulomb.social/coulomb/access-engine`, retaining the existing +`coulomb/flex-auth` package through the migration. `tools/publish-runtime-images.sh` +builds once, tags both names, then independently pulls each published immutable +tag and checks equal registry manifest digests, including OCI indexes and +attestations. A local image/config digest alone cannot satisfy the gate. + +Normal push CI continues to publish only the already admitted legacy package. +Paired publication is an explicit `workflow_dispatch` with +`publish_runtime_rename: true`, after the batch disposition and binding to the +exact committed source revision. No paired dispatch or new-package publication +has run. Local image build, renamed entrypoint, both policy paths and the +exit-2 legacy stub are verified. The lifecycle Containerfile's stale stub +entrypoint is repaired. Abort owner: access-engine. Stop on a failed push, +pull or digest mismatch; retain the partial publication record and do not +switch any workload. Recovery retains existing workload pins and prior +published digests; no registry deletion is proposed. New reviewer grants and +runtime deployment remain separate verified steps after their exact approval. diff --git a/scripts/security_flow_report.py b/scripts/security_flow_report.py index 288a0db9..afd9f4fd 100644 --- a/scripts/security_flow_report.py +++ b/scripts/security_flow_report.py @@ -25,6 +25,12 @@ def field(block, key): return m.group(1).strip().strip('"') if m else "" +def dependencies(block): + # Accept the convention's inline lists and YAML's indented multiline lists. + m = re.search(r"^depends_on:[ \t]*(.*(?:\n[ \t]+[^\n]*)*)", block, re.M) + return re.findall(r"[A-Z][A-Z0-9-]+-T\d+|[A-Z][A-Z0-9-]+-WP-\d+", m[1]) if m else [] + + def load(root, repos): tasks, wps = {}, {} for r in repos: @@ -38,7 +44,7 @@ def load(root, repos): tid = field(b, "id") if not tid: continue - deps = re.findall(r"[A-Z][A-Z0-9-]+-T\d+|[A-Z][A-Z0-9-]+-WP-\d+", field(b, "depends_on")) + deps = list(dict.fromkeys(dependencies(fm) + dependencies(b))) tasks[tid] = {"id": tid, "status": field(b, "status"), "deps": deps, "human": field(b, "needs_human") == "true", "blocked_on": field(b, "blocked_on"), diff --git a/tests/test_security_flow_report.py b/tests/test_security_flow_report.py index c89bc84e..63a88b0c 100644 --- a/tests/test_security_flow_report.py +++ b/tests/test_security_flow_report.py @@ -82,3 +82,16 @@ def test_human_flag_prevents_ready_even_if_status_has_not_been_requalified(tmp_p result = report(tmp_path) assert not result["READY"] assert result["ATTENDED"][0]["id"] == "USER-WP-0027-T04" + + +def test_workplan_and_multiline_task_dependencies_both_gate_successor(tmp_path): + workplan(tmp_path, "railiance-platform", + "id: RPF-WP-0048-T02\nstatus: todo\npriority: high\n" + "depends_on:\n - ACTIVITY-WP-0041-T03\n - ACTIVITY-WP-0041-T04") + source = tmp_path / "railiance-platform/workplans/test.md" + source.write_text(source.read_text().replace( + "flavor: implementation", "flavor: implementation\ndepends_on: [ACTIVITY-WP-0042]")) + result = report(tmp_path) + assert not result["READY"] + assert result["DEPENDENT"][0]["pending_dependencies"] == [ + "ACTIVITY-WP-0042", "ACTIVITY-WP-0041-T03", "ACTIVITY-WP-0041-T04"] diff --git a/workplans/CUST-WP-0079-deterministic-security-flow.md b/workplans/CUST-WP-0079-deterministic-security-flow.md index 6260539a..cd17dd76 100644 --- a/workplans/CUST-WP-0079-deterministic-security-flow.md +++ b/workplans/CUST-WP-0079-deterministic-security-flow.md @@ -133,6 +133,13 @@ also retain their intervention note in the generated report instead of a blank reason. CLI regression checks cover the actual owner completion transition and the default Custodian lane. +The report also excludes todo/progress tasks with unresolved explicit task +dependencies, an owner gate or a human flag from READY. They remain visible +under DEPENDENT or ATTENDED, without agent polling of wait bodies. Regression +tests prove that owner completion admits the successor and that an unknown +predecessor or stale progress label cannot produce readiness. This is queue +qualification, not evidence that the corresponding live work has finished. + ## Attended window #1 ```task