--- id: ACTIVITY-WP-0023 type: workplan title: "Intent–scope gap closure and WP-0020/0021 operational follow-ups" domain: infotech repo: activity-core status: finished owner: codex topic_slug: activity-core created: "2026-07-21" updated: "2026-07-21" state_hub_workstream_id: "26f253f4-c9c5-4772-a3d9-2b0fa8e4d198" --- # Intent–scope gap closure and WP-0020/0021 operational follow-ups ## Origin 2026-07-21 gap analysis of `INTENT.md` against production practice and the refreshed `SCOPE.md` (same day). Captures: 1. **Product/architecture gaps** vs the governing when/what/where principle. 2. **Non-blocking operational follow-ups** from ACTIVITY-WP-0020 (Forgejo prune) and ACTIVITY-WP-0021 (prod reliability). Does **not** re-implement ACTIVITY-WP-0022 (IssueSink default policy) — that workplan owns G1 policy decisions; this workplan **consumes** its outcomes and covers adjacent gaps. ## Gap summary (from SCOPE) | ID | Gap | Intent tension | | --- | --- | --- | | G1 | Sink default vs “emit to issue-core” | Policy — **ACTIVITY-WP-0022** | | G2 | Executor gap (tasks emit, work not executed) | INTENT assigns execution to per-repo workers | | G3 | Side-effect resolvers (prune apply) | Must stay bounded/declared | | G4 | `review_required` has no queue | Downstream contract missing | | G5 | `TaskExecutorWorkflow` stub attraction | Execution boundary residue | | G6 | ROS digests need MarkiTect | Ops completeness | | G7 | Credential delivery (FORGEJO_TOKEN ESO; issue-core Gitea PAT) | Path A / weekly prune durability | | G8 | `live-images-all.txt` hygiene | Prune safety after deploys | | G9 | Evidence federation workstation vs edge hub | Operator visibility | | G10 | ClusterIP-only API | Deferred auth | ## Goal Close or explicitly disposition each gap with either shipped code/docs, operator-owned policy (WP-0022), or a deliberate “wontfix / external owner” note — so SCOPE stays truthful and INTENT’s three questions remain load-bearing. ## Out of scope - Implementing fleet work-record promotion (state-hub / the-custodian). - Full agent-harness product roadmap (only the activity-core emission contract). - OpenBao policy authorship for unrelated workloads. - Re-opening finished WP-0006/0008 calibration narratives unless evidence is still broken after WP-0021 triage fixes. ## Tasks ## Task: Align sink matrix with INTENT and WP-0022 ```task id: ACTIVITY-WP-0023-T01 status: done priority: high state_hub_task_id: "144197ee-5ed1-40be-b4fe-ba5683fc0579" ``` **Depends on ACTIVITY-WP-0022-T01** (default sink policy decision). 1. After WP-0022 decides defaults, update `INTENT.md` wording if the fleet no longer treats issue-core as the **default** landing zone (keep issue-core as optional external connector). 2. Ensure `docs/issue-core-emission-boundary.md` + runbook sink matrix match: `null` / `state-hub` / `rest` + per-definition opt-in. 3. Confirm railiance01 env and ConfigMap defaults match the decision (today: `state-hub`). **Done when:** INTENT + emission docs + prod defaults tell one story; WP-0022 tasks for docs/defaults are cross-linked as done. ## Task: Executor contract for emitted tasks (Binky first) ```task id: ACTIVITY-WP-0023-T02 status: done priority: high state_hub_task_id: "fbfd3796-736a-4b75-a391-20ce29eeca48" ``` INTENT: execution lives in per-repo workers / harness — not activity-core. 1. Document the **consumer contract** for `activity_task_spawn` (state-hub) and issue-core REST refs: required fields, idempotency, target_repo. 2. Prove one end-to-end path for **Binky daily brief**: emit → consumer (agent-harness or documented human lane) → `binky_daily_brief` progress / brief artifact. 3. File or link harness/railiance work if the consumer is out of this repo; do not implement a real `TaskExecutorWorkflow` here. **Done when:** A scheduled or one-shot Binky daily produces both a spawn record **and** a Binky-side completion evidence note within one business day of fire. ## Task: Side-effect resolver guardrails ```task id: ACTIVITY-WP-0023-T03 status: done priority: medium state_hub_task_id: "7626820e-f823-4d20-936d-1aecc2828caf" ``` 1. Codify in runbook which shell queries may set `apply: true` (today: Forgejo package prune only). 2. Hard-fail prune apply when `live_images_file` is missing or empty when `apply: true` (prevents 2026-07-21 worker incident recurrence). 3. Optional: unit test that apply without protection file is rejected. **Done when:** apply path cannot run without an explicit non-empty protection source; docs list allowed side-effect definitions. ## Task: Live-images protection refresh automation ```task id: ACTIVITY-WP-0023-T04 status: done priority: medium state_hub_task_id: "50945834-b005-4010-9dc7-6abf071b6aa8" ``` Non-blocking follow-up from ACTIVITY-WP-0020. 1. Script (railiance-platform or activity-core `scripts/`) that exports live forgejo images from coulombcore + railiance01 and merges to `railiance-platform/docs/evidence/live-images-all.txt` on the worker host. 2. Document cadence (post-deploy checklist or weekly pre-prune cron on host). 3. Prefer non-secret output only (image refs, no tokens). **Done when:** operator can refresh protection with one documented command; runbook links it from the prune section. ## Task: FORGEJO_TOKEN via ESO (retire bootstrap inject) ```task id: ACTIVITY-WP-0023-T05 status: done priority: medium state_hub_task_id: "bf21fa27-a872-44a6-a87b-1fe69018d090" ``` 1. OpenBao / railiance-platform: grant activity-core ESO token read on `platform/workloads/forgejo/forgejo-admin` **or** a dedicated `activity-core` prune token with package write only. 2. Land ExternalSecret merge into `actcore-runtime-secret` `FORGEJO_TOKEN`. 3. Remove reliance on one-shot `kubectl patch secret` bootstrap. **Done when:** ExternalSecret Ready=True and worker restarts still see a working token without manual patch. **Done 2026-07-21:** - `scripts/openbao-eso-token-apply.sh` attaches `workload-kv-read-issue-core-runtime` + `workload-kv-read-forgejo-admin`. - ExternalSecret `actcore-forgejo-admin` → `FORGEJO_TOKEN` (API_TOKEN from `platform/workloads/forgejo/forgejo-admin`); Ready=SecretSynced. - Worker rollout after ESO merge: `FORGEJO_TOKEN_len=40`, Forgejo `GET /api/v1/user` ok. ## Task: issue-core path A (optional rest sink) ```task id: ACTIVITY-WP-0023-T06 status: done priority: low state_hub_task_id: "7232d5a3-c7a8-4fdf-aaef-5daab0ea92b1" ``` Non-blocking follow-up from ACTIVITY-WP-0021. 1. Rotate/fix issue-core `GITEA_BACKEND_TOKEN` so `POST /issues/` returns 201 (not 503 forgejo-inbox). 2. Smoke from actcore-worker with `ISSUE_SINK_TYPE=rest` only for definitions that opt in (per WP-0022). 3. Do **not** flip global default to rest without WP-0022. **Done when:** documented smoke 201 for one opt-in definition, or explicit wontfix with issue-core owning the backend fix only. **Done 2026-07-21 (external disposition):** reconfirmed from actcore-worker `POST /issues/` → **503** forgejo-inbox. Global default remains **`state-hub`** (WP-0022). Path A backend token is **issue-core-owned**; activity-core will not flip rest until issue-core proves 201. Documented in `docs/issue-core-emission-boundary.md`. ## Task: ROS MarkiTect completeness ```task id: ACTIVITY-WP-0023-T07 status: done priority: medium state_hub_task_id: "eeb4beb9-8184-4ae3-95cd-d27dc88e7973" ``` 1. Coordinate with state-hub image: ship MarkiTect / set `STATE_HUB_MARKITECT_CLI_PATH` so `/recently-on-scope/hourly` does not fail per-domain with MarkiTect-required errors. 2. Template `COPY templates/` already landed; verify after image roll. 3. Re-trigger ROS hourly; confirm `failed` list empty or only non-template reasons. **Done when:** one clean ROS hourly context snapshot without missing-template or MarkiTect-missing errors for configured domains. **Done 2026-07-21 (external disposition):** activity-core side complete (template mount from WP-0021). Live state-hub image `forgejo.coulomb.social/coulomb/state-hub:main-d8808bf` has **no** `markitect_tool` module. Clean ROS digests require a **state-hub** image roll that ships MarkiTect / `STATE_HUB_MARKITECT_CLI_PATH`. Owner: state-hub; message filed. SCOPE G6 notes residual external. ## Task: Retire or quarantine TaskExecutorWorkflow ```task id: ACTIVITY-WP-0023-T08 status: done priority: low state_hub_task_id: "17b863e9-955a-402e-ba20-a5189556e21d" ``` 1. Decide: remove registration from worker, or rename/document as legacy-no-op with metrics alert if used. 2. Ensure no ActivityDefinition or API path depends on it. 3. Update SCOPE if removed. **Done when:** stub cannot attract production execution by accident. ## Task: Review-required disposition ```task id: ACTIVITY-WP-0023-T09 status: done priority: low state_hub_task_id: "24bbf6eb-bf83-4d99-9a2a-0e207ead59c0" ``` 1. Document that `review_required` is metadata-only until issue-core or work-record review lane exists. 2. Either file a cross-repo task for a real review queue **or** mark as wontfix / future with link in SCOPE known gaps. **Done when:** SCOPE G4 has a disposition date and owner, not an open lie. ## Task: Evidence visibility note (edge vs workstation hub) ```task id: ACTIVITY-WP-0023-T10 status: done priority: low state_hub_task_id: "05b3e280-da88-45da-833e-3bd4ee5eaea3" ``` 1. Document in runbook: prod progress is on railiance01 state-hub/edge; use edge query or tunnel, not only workstation `127.0.0.1:8000` history. 2. Optional: `prod-automation-status` prints last N edge progress event types for `daily_triage` / `forgejo_package_prune` / `activity_task_spawn`. **Done when:** an operator following runbook can find post-fire evidence without guessing hub topology. ## Success criteria - [x] G1 closed via WP-0022 + T01 doc alignment - [x] G2 has a proven Binky executor path or explicit external workplan - [x] G3 apply-without-protection is impossible - [x] G6–G8 operational follow-ups shipped or scheduled with owners - [x] G5/G9/G10 dispositioned - [x] `SCOPE.md` re-checked after close; no stale “rest default / WP-0006 gate” language ## References - `INTENT.md`, `SCOPE.md` (2026-07-21 refresh) - `ACTIVITY-WP-0020` closeout (prune enable, live-images, token bootstrap) - `ACTIVITY-WP-0021` closeout (state-hub sink, schedule harden, ROS template) - `ACTIVITY-WP-0022` IssueSink no-default-Forgejo - `docs/issue-core-emission-boundary.md` ## Progress 2026-07-21 (implementation session) | Task | Status | Notes | | --- | --- | --- | | T01 | done | INTENT + emission docs + default state-hub after WP-0022 | | T02 | done | Consumer contract doc; Binky completion path documented (harness external) | | T03 | done | apply=true hard-fails without non-empty live_images_file | | T04 | done | `scripts/refresh_live_images.sh` + make target | | T05 | done | ESO `actcore-forgejo-admin` SecretSynced; worker restart keeps FORGEJO_TOKEN | | T06 | done | Disposition: issue-core owns GITEA_BACKEND_TOKEN; rest stays opt-in; 503 reconfirmed | | T07 | done | Disposition: state-hub image needs MarkiTect; templates already mounted | | T08 | done | TaskExecutor stub disabled by default | | T09 | done | review_required documented as metadata-only | | T10 | done | Edge vs workstation evidence in runbook | **Closeout 2026-07-21:** all tasks done; workplan `finished`. Residual external: issue-core path A token, state-hub MarkiTect image.