# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview `activity-core` is the backbone service for a robust, event-driven "task factory" architecture. The core concept: an `ActivityDefinition` (stored in Postgres) defines a trigger (time-based or event-driven), a context resolver, and task templates. When triggered, a durable workflow evaluates the current context and spawns 0..N `TaskInstance`s. **Technology choices (from planning docs in `wiki/`):** - **Temporal** (self-hosted) as the orchestration engine — replaces Celery/APScheduler/cron - **PostgreSQL** for app data (ActivityDefinitions, run logs, task instances) and Temporal persistence - **Python SDK** (primary) for Temporal workflows and activities **Domain model:** - `ActivityDefinition` — versioned record with trigger config (cron/event), context sources, task templates - `TriggerEvent` — time-based (Temporal Schedule) or external event (broker → Event Router → `client.start_workflow`) - `RunActivityWorkflow` — durable Temporal workflow: load definition → resolve context → evaluate rules → spawn tasks → log run - `TaskInstance` — child workflow or activity; human-facing tasks persisted to DB **Planned directory structure (not yet scaffolded):** ``` workplans/ # ADR-001: workplan .md files (created before hub registration) contrib/ # upstream contribution artifacts (bug-reports/, feature-requests/, extension-points/, upstream-prs/) workflows.py # Temporal workflow definitions activities.py # Temporal activity implementations ``` --- ## Custodian State Hub Integration This project is tracked as the **custodian** domain in the Custodian State Hub. Hub topic ID: `cee7bedf-2b48-46ef-8601-006474f2ad7a` The State Hub runs locally at http://127.0.0.1:8000. The MCP server (`state-hub`) exposes tools for reading and writing state without touching the API directly. ### Session Protocol **On receiving your first message — before writing any response text — execute this orientation sequence. Do not greet, do not ask what to do first.** **Step 1 — Call the State Hub** ``` get_domain_summary("custodian") # workstreams, blocking decisions, recent progress, SBOM status ``` If the call fails, the API is offline: `cd ~/the-custodian/state-hub && make api` **Step 2 — Scan local workplans** Read every `.md` file under `workplans/`. For each file with `status: active`, extract and note: - The workplan title and ID - All tasks whose `status` is `todo` or `in_progress` **Step 3 — Present orientation to the user** Output a concise brief covering: 1. **Active workstreams** (from state hub) for the `custodian` domain — title, task counts, any blocking decisions 2. **Pending tasks for this repo** — from local `workplans/` files plus any state hub tasks with `[repo:activity-core]` in their title 3. **Suggested next action** — the highest-priority open item across both sources 4. **SBOM status** — is `last_sbom_at` set for this repo? If not, note it as a gap If there are no workstreams at all: follow the First Session Protocol below. **During work:** - Use `record_decision()` for any decision that affects direction or dependencies. - Use `add_progress_event()` for notable events (milestones, blockers, insights). - Use `resolve_decision()` to close a decision once the choice is made. > **Design boundary:** The State Hub is a *read model*. Two write operations are > permanently sanctioned: **Resolving Decisions** and **Suggesting Next Steps**. > The bootstrap tools (`create_workstream`, `create_task`, `update_task_status`) > are only for First Session Protocol. Formal work structure — workplans, tasks — > belongs in the domain repo as files (ADR-001), not managed through the hub alone. **At the end of every session:** - Call `add_progress_event()` with a summary of what was accomplished or decided. Include `topic_id: cee7bedf-2b48-46ef-8601-006474f2ad7a` and the relevant `workstream_id`. --- ### Repo Boundary Rule This agent is responsible for files **in this repo only**. - **Do not** write files or make commits in any other repository - When you identify work for another registered repo (**ecosystem todo**): create a state hub task with `[repo:]` in the title - When you identify work for an upstream repo (**third-party todo**): create a contribution artifact in `contrib/` and register it --- ### First Session Protocol Triggered when `get_state_summary()` shows **no workstreams** for the `custodian` topic. **Step 1 — Understand the project (read, don't write)** - `~/the-custodian/canon/projects/custodian/project_charter_v0.1.md` — purpose, scope - `~/the-custodian/canon/projects/custodian/roadmap_v0.1.md` — planned phases - `wiki/` — proto-plans from ChatGPT and Grok (architecture reference, not yet compiled into a workplan) **Step 2 — Survey in-progress work** — look for TODOs, open branches, half-finished files. **Step 3 — Propose workstreams to Bernd.** Wait for approval before creating. **Step 4 — Create workplan file first, then DB record (ADR-001):** ``` workplans/-WP-NNNN-.md ← write this first ``` Then register in the hub: ``` create_workstream(topic_id="cee7bedf-2b48-46ef-8601-006474f2ad7a", title="...", owner="...", description="...") create_task(workstream_id="", title="...", priority="high|medium|low") ``` **Step 5 — Record the setup:** ``` add_progress_event(summary="First session: ...", event_type="milestone", topic_id="cee7bedf-2b48-46ef-8601-006474f2ad7a", detail={...}) ``` --- ### Workplan Convention (ADR-001) Work items MUST originate as files in this repo before being registered in the hub. **File location:** `workplans/-.md` **Frontmatter required:** `id`, `type: workplan`, `domain`, `repo`, `status`, `state_hub_workstream_id`, `state_hub_task_id` (per task) --- ### Contribution Tracking Track upstream contributions in `contrib/`: ``` contrib/ bug-reports/ # br-YYYY-MM-DD--org--repo--slug.md feature-requests/ # fr-YYYY-MM-DD--org--repo--slug.md extension-points/ # EP-custodian-NNN--org--repo--slug.md upstream-prs/ # upr-YYYY-MM-DD--org--repo--slug.md ``` Templates: `~/the-custodian/canon/standards/contrib-templates/` ``` register_contribution(type="br|fr|ep|upr", title="...", target_org="...", target_repo="...", body_path="contrib/...", related_workstream_id="") ``` --- ### SBOM After updating dependencies: ```bash cd ~/the-custodian/state-hub make ingest-sbom REPO=activity-core SCAN=1 REPO_PATH=$(pwd) ``` --- ### Quick Reference `~/the-custodian/state-hub/mcp_server/TOOLS.md` — compact MCP tool reference