activity-core/SCOPE.md
tegwick e73575dcd6
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 4s
Refresh SCOPE.md intent gap analysis; add ACTIVITY-WP-0023
Document production posture after WP-0020/0021, list INTENT↔practice gaps
G1–G10, and open a workplan for gap closure plus operational follow-ups.
2026-07-21 21:19:47 +02:00

297 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
domain: capabilities
repo: activity-core
updated: "2026-07-21"
---
# SCOPE
> This file helps you quickly understand what this repository is about,
> when it is relevant, and when it is not.
---
## One-liner
activity-core is the org-wide Event Bridge for the Coulomb organization — a
rule-governed event loop that receives time-based and domain events, evaluates
declarative rules and LLM instructions against current org context, and emits
structured task, report, and evidence outputs without owning downstream task
lifecycle.
---
## Core Idea
An `ActivityDefinition` (a markdown file checked into a repo) declares a trigger
(cron, one-off scheduled datetime, or named event type), context sources to
resolve before evaluation, and a set of rules and instructions that determine
what work or evidence to produce. When triggered, a durable Temporal workflow
loads the definition, resolves context, evaluates the rule/instruction set, and
emits outputs via configured sinks:
- **Tasks** — via `IssueSink` (`rest` → issue-core, `state-hub` progress, or
`null` dry-run).
- **Reports** — instruction reports to working memory and/or State Hub progress.
- **Evidence** — compact non-secret summaries from selected resolvers (ops
inventory, package prune, legacy-meter, etc.).
Everything is auditable: `activity_runs` records the activation; `task_spawn_log`
records emissions; report sinks leave progress/working-memory artifacts.
The two evaluation modes:
- **Rule** — deterministic condition (sandboxed Python-like DSL) → fixed task
templates. Fast, testable, no LLM cost.
- **Instruction** — optional pre-filter → LLM or **deterministic** report path
(`model: deterministic` / `none` / `unused`) → structured tasks and/or
reports. LLM reserved for genuine judgement; deterministic for pure context
summaries.
---
## In Scope
- **ActivityDefinition model**: trigger config (cron / scheduled / event),
context sources, rules (condition + action), instructions (trusted-field
prompt + model + output schema + report sinks).
- **Event type registry**: publisher-declared markdown definitions with
attribute schemas, example payloads, and intent documentation.
Curator-gating configurable per runtime environment.
- **Trigger types**: 5-field cron with timezone and misfire policy; one-off
scheduled datetime; event-type subscription via NATS; manual one-shot API
trigger; one-shot schedule smoke tests for recurring definitions.
- **Schedule reconcile**: Temporal Schedule upsert/pause with per-row error
isolation (`sync_schedules` continues after `ScheduleAlreadyRunningError`).
- **Context resolution adapters**: repo-scoping, State Hub (domain/workplan
state, SBOM status, daily triage digest, coding retro, Binky rhythm status,
consistency sweep, RecentlyOnScope hourly), shell queries (e.g. Forgejo
package prune), and ops inventory probes. Registry is extensible.
- **Rule evaluator**: sandboxed AST walker; `for_each` binding; no `exec()`.
- **Instruction executor**: trusted-field rendering, llm-connect, structured
validation, item-granular recovery, deterministic report path, report sinks.
- **Task emission adapter**: `IssueCoreRestSink`, `StateHubProgressSink`,
`NullSink` selected by `ISSUE_SINK_TYPE`. Production railiance01 currently
uses **`state-hub`** as the safe default for internal findings (see
ACTIVITY-WP-0021/0022); restore `rest` only when issue-core→Forgejo is healthy
**and** policy allows external issues.
- **Report / evidence sinks**: working memory, State Hub progress
(`daily_triage`, `sbom_staleness`, `forgejo_package_prune`,
`ops_inventory_probe`, `activity_task_spawn`, etc.).
- **Spawn audit log**: `task_spawn_log` with rule/instruction id and sink ref.
- **Webhook receiver**: Gitea/GitHub → EventEnvelope → NATS.
- **Worker and workflow infrastructure**: Temporal `RunActivityWorkflow`
(load → resolve → evaluate → report → **log_run** → emit). Emit failures no
longer skip `activity_runs` rows.
- **REST admin API** (FastAPI): CRUD, manual trigger, admin sync, metrics.
- **Automation status surface**: `make automation-status` and
`make prod-automation-status` / `scripts/prod_automation_status.sh` for
railiance01 evidence without LLM authority.
- **Operational runbook**: `docs/runbook.md`, emission boundary docs.
---
## Out of Scope
- **Task lifecycle** — create/assign/track/close remains issue-core (or fleet
work-record connectors). activity-core holds a spawn audit trail only.
- **Project and initiative management** — project-core (future).
- **General execution workers** — scans, patches, privileged API writes that
are not explicitly declared as **bounded ActivityDefinition side-effects**
(e.g. retention prune with dry-run/apply gates) belong to per-repo workers
or platform tools.
- **General ops control plane** — Kubernetes, SSH, tunnels, secret custody,
OpenBao policy administration.
- **Event broker / Temporal server hosting** — consume, do not own lifecycle.
- **End-user task UI**.
- **Coding assistant schedulers** as production authority.
**Boundary note (side-effect resolvers):** A small set of shell/context
resolvers intentionally invoke platform tools (e.g. Forgejo package prune).
That is allowed only when the side-effect is the *declared purpose* of the
ActivityDefinition, is credential-routed, evidence-posted, and not general
task execution. It must not expand into an unbounded ops executor.
---
## Relevant When
- Org-wide recurring maintenance (SBOM, package prune, legacy-meter, Binky
rhythm, consistency sweeps) without bespoke per-service cron.
- Reactive task/report generation from org events and context.
- One-off future scheduling.
- Auditable activation history (runs, spawn log, progress).
- Answering “how did automations go since Sunday?” from deterministic
repo-native / prod evidence.
## Not Relevant When
- Tracking task completion/reassignment → issue-core / work records.
- Multi-phase project orchestration → project-core.
- Simple host cron with no durability or evidence needs.
---
## Current State (2026-07-21)
### Status
Production on **railiance01** (`activity-core` namespace). Recent finished
workplans:
| WP | Outcome |
| --- | --- |
| ACTIVITY-WP-0018 | Own-infra automation status CLI |
| ACTIVITY-WP-0019 | Automation inventory targets |
| ACTIVITY-WP-0020 | Weekly Forgejo package prune **enabled**; first apply 38 deletes |
| ACTIVITY-WP-0021 | Prod reliability: state-hub sink, log_run-before-emit, schedule harden, DB probes, prod status path |
| ACTIVITY-WP-0006/0008 | Marked finished historically; enablement evidence has moved |
Open product/policy workplan: **ACTIVITY-WP-0022** (IssueSink no-default-Forgejo).
### Live posture (railiance01)
- Image: `activity-core:railiance01-prod` (locally imported).
- `ISSUE_SINK_TYPE=state-hub` (internal findings → State Hub progress, not
Forgejo issues).
- Edge relay: `actcore-statehub-edge-relay` → in-cluster `state-hub`.
- Weekly prune: worker has `FORGEJO_TOKEN` + hostPath `/opt/railiance-platform`
+ `live_images_file` (kubectl absent in pod).
- Proven one-shots (2026-07-21): Binky daily/mail COMPLETED with tasks_spawned=1;
SBOM deterministic report; daily triage progress; prune apply.
### Definitions (repo files + prod DB)
| Definition | Role |
| --- | --- |
| `weekly-sbom-staleness` | Deterministic SBOM report; task emit gated off |
| `weekly-forgejo-package-prune` | Sunday 03:30 UTC apply prune + evidence |
| `weekly-legacy-meter-review` / `legacy-meter-8h-capture` | Meter evidence |
| `weekly-coding-retro` | Present; enablement depends on `coding_retro` feed |
| Binky daily / mail / review-prep | Rhythm tasks via IssueSink |
| Railiance ConfigMap bundle | Daily triage, ROS hourly, consistency sweep, etc. |
### Task emission posture
- **Canonical REST sink** to issue-core remains implemented and documented.
- **Production default is `state-hub`** after Forgejo PAT/backend failures and
fleet policy against silent Forgejo issues (WP-0021 path B, WP-0022).
- Restoring `rest` requires healthy issue-core→Forgejo **and** explicit policy
opt-in per definition.
---
## Assessment Against Intent
### Alignment
| INTENT promise | Status |
| --- | --- |
| Answers **when / what / where** | Met — Temporal schedules, rules/instructions, sinks |
| Markdown definitions | Met — `activity-definitions/`, event-types, external ConfigMaps |
| Rules before instructions | Met — SBOM/prune/Binky rules; triage uses LLM when needed |
| Durable recurring automation | Met — railiance01 schedules fire; status surface exists |
| Audit trail | Met — `activity_runs`, spawn log, progress/working-memory |
| Does not own task lifecycle | Met — no completion tracking |
| Does not own project phases | Met |
### Gaps and tensions (INTENT ↔ practice)
| Gap | Severity | Notes |
| --- | --- | --- |
| **G1. Sink default vs INTENT “emit to issue-core”** | High (policy) | INTENT names issue-core as the task landing zone. Practice and work-record canon push **State Hub / repo work records** for internal findings. WP-0022 owns policy; code already supports `state-hub` / `null` / `rest`. |
| **G2. Executor gap** | High (value) | Tasks are emitted (progress refs or issue-core), but **no per-repo executor** reliably consumes them (Binky briefs still need harness/agent pickup). INTENT assigns execution to per-repo Temporal workers — that substrate is thin. |
| **G3. Side-effect resolvers** | Medium | Forgejo prune `apply: true` runs platform deletes inside a context resolver. Allowed only as declared, gated side-effect; needs clearer SCOPE language (above) and operator refresh of live-images protection. |
| **G4. Review queue** | Medium | `review_required` remains metadata-only; no downstream review queue. |
| **G5. TaskExecutorWorkflow stub** | Lowmedium | Still registered; risk of attracting real execution. |
| **G6. ROS digest completeness** | Medium (ops) | Template file mounted; MarkiTect CLI missing in state-hub image → digests still fail per domain. |
| **G7. Credential delivery** | Medium (ops) | `FORGEJO_TOKEN` bootstrap-injected; ESO 403 on forgejo-admin path. issue-core `GITEA_BACKEND_TOKEN` still broken for path A rest sink. |
| **G8. Live-images hygiene** | Medium (ops) | Multi-cluster `live-images-all.txt` must be refreshed after deploys or prune can delete live tags (incident 2026-07-21, restored). |
| **G9. Evidence federation** | Low | Progress often lands on railiance01 edge/hub; workstation primary hub may not show the same feed without tunnel/outbox health. |
| **G10. API external access** | Low | ClusterIP-only; intentional until auth policy. |
### Drift risks
1. **Convenience execution** — growing shell resolvers into a general ops runner.
2. **Silent sink restore** — flipping `ISSUE_SINK_TYPE=rest` without policy +
healthy Forgejo backend reintroduces issue spam / 503s.
3. **Protection file staleness** — weekly prune with `apply: true` depends on
fresh live-image lists.
4. **Stub workflow attraction**`TaskExecutorWorkflow` looks like an
execution home.
---
## How It Fits
```
[NATS JetStream / Temporal Schedules / manual trigger]
[activity-core] Event type registry · rules · instructions · context resolvers
[IssueSink: rest | state-hub | null] → issue-core or State Hub progress
[report/evidence sinks] → State Hub / working memory
[bounded shell side-effects] → platform tools (e.g. package prune)
```
- **Upstream**: NATS, Temporal, PostgreSQL, State Hub, repo-scoping, llm-connect.
- **Downstream**: issue-core (optional), State Hub, platform tools, future
per-repo executors / agent-harness.
- **Ops**: railiance01 k3s; workstation status via SSH helper.
---
## Terminology
- **ActivityDefinition** — markdown policy unit (trigger + context + rules/instructions).
- **EventEnvelope** — canonical inbound event shape.
- **Rule / Instruction** — deterministic vs judgement (or deterministic report) paths.
- **IssueSink** — task emission adapter (`rest` / `state-hub` / `null`).
- **Report sink / Evidence sink** — non-task activation outputs.
- **Spawn audit trail** — local emission record; not authoritative task state.
- **Activity** (Temporal) vs **ActivityDefinition** (app policy) — different concepts.
---
## Related / Overlapping
- `issue-core` — task connector / external tracker mapping (not fleet work-record origin).
- `repo-scoping`, State Hub / the-custodian, `llm-connect`, `agent-harness`.
- `railiance-platform` — Forgejo package prune tool and credential lanes.
- `ops-warden` — credential routing (not secret vending for non-SSH).
- `project-core` (future), `ops-bridge` tunnels.
---
## Architecture Decisions
- `docs/adr/adr-001-event-bridge-architecture.md`
- `docs/adr/adr-002-definition-format.md`
- `docs/adr/adr-003-rule-instruction-model.md`
- `docs/adr/adr-004-producer-trust-boundary.md`
---
## Getting Oriented
- Start: `INTENT.md`, this file, `docs/adr/`, `docs/runbook.md`.
- Key code: `workflows.py`, `activities.py`, `issue_sink.py`, `report_sinks.py`,
`context_resolvers/`, `automation_status.py`, `sync_schedules.py`.
- Definitions: `activity-definitions/`, `event-types/`, Railiance ConfigMaps.
- Status: `make automation-status SINCE=sunday` ·
`make prod-automation-status SINCE=sunday`.
---
## Provided Capabilities
```capability
type: data
title: Durable event-triggered task factory
description: >
Org-wide Event Bridge that receives time-based and domain events, evaluates
declarative rules and LLM instructions against current org context, and emits
structured task, report, and evidence outputs with a full spawn/report audit
trail while leaving task lifecycle ownership downstream.
keywords: [temporal, workflow, event-bridge, task, report, evidence, cron, event, rule, instruction, org-automation]
```