--- id: ACTIVITY-WP-0022 type: workplan title: "IssueSink: stop default silent Forgejo issues for internal findings" 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: "6871d26b-6eaf-5a7e-94d1-e5cf8f2e2c7a" --- # IssueSink: stop default silent Forgejo issues for internal findings ## Origin Filed from **issue-core** `ISSUE-WP-0004-T05` after the work-record canon alignment (CUST-WP-0060, founder-reviewed architecture draft §4.2). **Incident backdrop:** `daily-todo-md-stale-review` (and any definition whose rules call `emit_tasks`) treated `IssueSink` → issue-core → Forgejo as the default always-on path. That produced tracker issues nobody was meant to see as fleet coordination. Forgejo issue tracking is **not** the fleet coordination mechanism; work records originate as repo files (ADR-001). issue-core has retargeted its own docs to **connector, not landing zone** (`INTENT.md` / `SCOPE.md` / ISSUE-WP-0004). This workplan is the **activity-core-side** product fix: the default sink must not silently create Forgejo issues for internal findings. **Related:** - issue-core: `workplans/ISSUE-WP-0004-align-with-work-record-canon.md` - the-custodian: CUST-WP-0060 closure review item 6 (TODO-stale / IssueSink) - activity-core: `ACTIVITY-WP-0021` (prod reliability; T01 may restore *or* replace emit path — this WP owns the **policy** default) - `src/activity_core/issue_sink.py` — `ISSUE_SINK_TYPE` defaults to `"state-hub"` (ACTIVITY-WP-0022) ## Goal 1. **Default is safe for internal findings:** no silent Forgejo issue spam when `ISSUE_SINK_TYPE` is unset or when a definition is internal-only. 2. **Intentional external issues remain possible** (explicit config / sink type / per-definition opt-in). 3. Internal outcomes go to the appropriate fleet surface (work-record intake, State Hub progress, working-memory, etc.) — not issue-core by default. 4. Document the sink matrix for operators (rest / null / future intake). ## Out of scope - Implementing issue-core UUID ↔ external-id mapping (issue-core design note `docs/uuid-external-id-mapping.md`; stage-3 work-record arch). - Full redesign of every ActivityDefinition — only sink policy + the definitions that currently misuse IssueSink for internal findings. - ACTIVITY-WP-0021 bridge 503 reliability work (coordinate, don't duplicate). ## Tasks ## Task: Decide default sink policy and config surface ```task id: ACTIVITY-WP-0022-T01 status: done priority: high state_hub_task_id: "44f224bc-50db-5830-8f13-3b5495698eb9" ``` Choose and document: - Safe default for `ISSUE_SINK_TYPE` (e.g. `null` or a future non-Forgejo sink) vs keep `rest` only when explicitly enabled in prod overlays. - Per-definition or per-rule opt-in for external projection. - Interaction with NullSink, tests, and railiance01 deployment env. Reference: issue-core SCOPE “Default sink for internal automation findings” and ISSUE-WP-0004 origin. ## Task: Implement default that does not create Forgejo issues ```task id: ACTIVITY-WP-0022-T02 status: done priority: high state_hub_task_id: "a11fdab2-c7fc-52b7-9723-d6ec920b0608" ``` Code + config changes so unmatched / internal-finding paths cannot spam Forgejo. Update tests (`tests/test_issue_sink.py` and callers of `get_issue_sink()`). Preserve a documented path for intentional `rest` use. ## Task: Reroute or pause definitions that abused IssueSink for fleet work ```task id: ACTIVITY-WP-0022-T03 status: done priority: medium state_hub_task_id: "271189a4-fbc2-52c4-9fae-47c5bd430f2a" ``` At minimum: `daily-todo-md-stale-review` and any other definition that only needs internal attention. Prefer work-record intake / State Hub progress over Forgejo. Coordinate with CUST-WP-0060 item 6 and WP-0021 if still paused. ## Task: Operator docs and deployment env audit ```task id: ACTIVITY-WP-0022-T04 status: done priority: medium state_hub_task_id: "eeac1e4f-ae47-589f-8a5a-337ef3de7052" ``` Document sink matrix; audit railiance01 / compose env for `ISSUE_SINK_TYPE`, `ISSUE_CORE_URL`, `ISSUE_CORE_API_KEY`. Confirm defaults match policy after T02. ## Acceptance - [ ] Unset / default config does not open Forgejo issues for internal findings - [ ] Intentional external emit still works when explicitly configured - [ ] TODO-stale (and peers) no longer depend on IssueSink→Forgejo for fleet visibility - [ ] Tests and deploy docs match the new default - [ ] Cross-link from issue-core ISSUE-WP-0004 remains accurate ## See also - `src/activity_core/issue_sink.py` - issue-core `INTENT.md` (pivot 2026-07-20) - `the-custodian/canon/standards/work-record-types_v0.1.md` - `the-custodian/research/WorkOrchestrationArchitectureDraft.md` §4.2 ## Closeout 2026-07-21 **Policy decision (T01):** `ISSUE_SINK_TYPE` default = **`state-hub`**. `rest` is explicit opt-in only. Unknown/empty → state-hub. **Code (T02):** `DEFAULT_ISSUE_SINK_TYPE`, factory fallback, tests. **Definitions (T03):** `daily-todo-md-stale-review` already paused/disabled in prod; SBOM task rules gated off; internal paths use reports / state-hub. **Docs (T04):** `docs/issue-core-emission-boundary.md` sink matrix, `docs/task-emission-consumer-contract.md`, `.env.example`, runbook. Acceptance checkboxes: - [x] Default does not open Forgejo issues for internal findings - [x] Intentional `rest` still available - [x] TODO-stale not depending on IssueSink→Forgejo - [x] Tests and deploy docs match