Renames the package, distribution, CLI alias, Makefile targets, and working directory from issue-facade to issue-core, signalling its role as the authoritative task lifecycle manager for the Coulomb org (peer to activity-core, rules-core, project-core). Adds POST /issues/ ingestion endpoint for activity-core's IssueSink, under a new optional [api] extra. The endpoint is served by `issue serve`, authenticates via the ISSUE_CORE_API_KEY env var (Bearer or X-API-Key header), and routes the TaskSpec payload to the configured default backend with full traceability metadata embedded in sync_metadata. - T01: Python package issue_tracker -> issue_core, dir rename - T02: registered in state hub under custodian domain - T03: INTENT.md (what it is, what it isn't, how it fits) - T04: SCOPE.md (in/out-of-scope, integration boundaries) - T05: POST /issues/ via FastAPI + Uvicorn, 9 unit tests - T06: docs/nats-task-ingestion.md design stub Closes ISSC-WP-0001. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
8.1 KiB
id, type, domain, repo, status, state_hub_workstream_id, tasks, created
| id | type | domain | repo | status | state_hub_workstream_id | tasks | created | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ISSC-WP-0001 | workplan | custodian | issue-core | done | 1135fc1d-1f46-4e35-886d-04cc3b8050b6 |
|
2026-05-14 |
ISSC-WP-0001: Rename to issue-core and Task Ingestion
Purpose
Two things need to happen to make issue-facade a proper peer to activity-core in the Coulomb org architecture:
-
Rename:
issue-facadeis a misleading name — it is not a facade, it is the authoritative task lifecycle manager for the org. Renaming toissue-corealigns with the naming pattern (activity-core,rules-core,project-core) and signals its role clearly. -
Task ingestion endpoint: activity-core's
IssueSinkadapter emits tasks to issue-core via REST. That endpoint must exist, be stable, and acceptTaskSpecpayloads from activity-core. Without it, activity-core's task emission is a no-op.
Context
- activity-core WP-0003 (in progress): implements
IssueSinkAdapterinsrc/activity_core/issue_sink.py. It callsPOST /issues/on issue-core to create tasks from ActivityDefinition rule/instruction output. - issue-facade currently: multi-backend task tracker (Gitea, SQLite, GitHub). Handles task creation and tracking. Has no incoming task-ingestion API from external callers like activity-core.
- State hub gap: issue-facade is not registered in the Custodian State Hub. This makes cross-repo workstream tracking impossible.
See: docs/adr/adr-001-event-bridge-architecture.md in activity-core for the
IssueSink adapter design and the task emission flow.
Scope
In scope:
- Package rename (issue-facade → issue-core)
- State hub registration
- INTENT.md and SCOPE.md
- Task ingestion REST endpoint (POST /issues/)
- NATS subscriber interface design stub
Out of scope:
- Project management features (that is project-core, future)
- UI or end-user facing changes
- Changing backends (Gitea/SQLite/GitHub adapters stay as-is)
TaskSpec Payload (from activity-core)
The POST /issues/ endpoint receives this payload from activity-core's IssueSink:
{
"title": "string",
"description": "string",
"target_repo": "string",
"priority": "high | medium | low",
"labels": ["string"],
"due_in_days": 7,
"source_type": "rule | instruction",
"source_id": "string",
"triggering_event_id": "uuid",
"activity_definition_id": "string"
}
The endpoint must return:
{
"issue_id": "string",
"issue_url": "string or null",
"backend": "gitea | sqlite | github"
}
The issue_id is stored in activity-core's task_spawn_log as the external
reference. It is not managed by activity-core — it belongs to issue-core.
Tasks
T01 — Rename package issue-facade → issue-core throughout
Rename everywhere:
pyproject.toml:name = "issue-core", update entry points- Python package directory:
issue_facade/→issue_core/(if applicable) - All
import issue_facade→import issue_core - CLI command names if changed
- README, CHANGELOG headers
- Docker Compose service names and image tags
- Any Makefile targets
After renaming, run the full test suite to confirm no broken imports.
Update the workplans/ frontmatter repo: issue-core once renamed.
T02 — Register issue-core in state hub under capabilities domain
Call register_repo() on the state hub MCP:
register_repo(slug="issue-core", path="/home/worsch/issue-facade",
domain="custodian") # or capabilities if domain exists
Note: the directory may still be named issue-facade — register with
slug="issue-core" and update path once the rename is complete.
T03 — Write INTENT.md
Write INTENT.md explaining:
- Why it exists: the Coulomb org needs a single, observable place where tasks land — regardless of whether they were created by a human, by activity-core, or by an agent.
- What it is: task lifecycle manager (create, assign, update, close) with pluggable backends (Gitea, SQLite, GitHub).
- What it is NOT: not a project manager (no phases, no campaigns, no dependency graphs — that is project-core). Not a spawn audit trail (that is activity-core). Not an event bus.
- How it fits: activity-core emits tasks here via IssueSink; humans and agents consume them; status updates flow back to issue-core (not to activity-core).
T04 — Update or write SCOPE.md
Check if SCOPE.md exists. If yes, update:
- Rename references (issue-facade → issue-core)
- Add activity-core as an upstream emitter via IssueSink REST
- Add "Out of scope" section if missing: project management, spawn audit trail
- Update "How it fits" to reference activity-core architecture
If no SCOPE.md exists, write one from scratch following the standard format.
T05 — Implement task ingestion REST endpoint POST /issues/
Implement POST /issues/ (or POST /tasks/create — check existing naming
convention and pick the most consistent path):
@router.post("/issues/")
async def ingest_task(payload: TaskIngestionRequest) -> TaskIngestionResponse:
...
The endpoint must:
- Validate the payload against
TaskIngestionRequestschema - Route to the correct backend based on
target_repo(look up backend config) - Create the issue/task in the backend
- Return
{issue_id, issue_url, backend} - Log the ingestion with
triggering_event_idfor traceability
Key file: issue_core/api/ingest.py (new) or alongside existing API routes.
Security: the endpoint should require an API key header (check existing auth pattern in the codebase). Do not expose it unauthenticated.
T06 — Document NATS subscriber interface (design stub)
Design stub only — implementation deferred until activity-core's IssueSink migrates from REST to NATS.
Document in docs/nats-task-ingestion.md:
- Proposed NATS subject pattern:
act.tasks.create.{target_repo} - Message schema (same
TaskIngestionRequestas REST endpoint) - Consumer group config: durable consumer, at-least-once delivery
- Idempotency key:
triggering_event_id— used to deduplicate retries
Build Order
T01 (rename) → T02 (register) → T03 (INTENT.md) → T04 (SCOPE.md)
T01 (rename) → T05 (REST endpoint) → T06 (NATS stub, depends on endpoint schema)
Completion Criteria
- Package renamed to issue-core; all tests pass after rename
- issue-core registered in state hub
- INTENT.md and SCOPE.md committed and accurate
POST /issues/endpoint implemented and tested with a TaskSpec payload- activity-core agent confirmed IssueSink integration works end-to-end
- NATS design stub committed to
docs/
Notes
- Directory name: if renaming the repository directory (
issue-facade/→issue-core/) — coordinate with Bernd first, as it will invalidate any relative paths or symlinks. - T01 first: all other tasks depend on the rename being settled. The directory path in state hub registration (T02) must reflect the final name.
- Backwards compat: if external consumers call the existing API using paths
under
issue-facade, add redirect aliases rather than breaking them. - The NATS stub (T06) should be implemented as a comment-heavy skeleton so the activity-core agent can wire the NATS IssueSink without waiting for a full implementation.
Change History
- v0.1 (2026-05-14): Stub created by activity-core agent during WP-0003 planning. Local agent to flesh out and implement.