Phase 0 contracts (event envelope, ActivityDefinition, idempotency doc, naming conventions) and Phase 1 Temporal cluster setup (docker-compose.dev.yml, Temporal dynamic config) are complete. Includes Pydantic models, JSON schemas, wiki architecture docs, and ADR-001 workplan files for both workstreams. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.6 KiB
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 TaskInstances.
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 templatesTriggerEvent— 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 runTaskInstance— 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
statusistodoorin_progress
Step 3 — Present orientation to the user
Output a concise brief covering:
- Active workstreams (from state hub) for the
custodiandomain — title, task counts, any blocking decisions - Pending tasks for this repo — from local
workplans/files plus any state hub tasks with[repo:activity-core]in their title - Suggested next action — the highest-priority open item across both sources
- SBOM status — is
last_sbom_atset 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. Includetopic_id: cee7bedf-2b48-46ef-8601-006474f2ad7aand the relevantworkstream_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:<slug>]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 phaseswiki/— 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/<DOMAIN>-WP-NNNN-<slug>.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="<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/<ID>-<slug>.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="<uuid>")
SBOM
After updating dependencies:
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