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>
5.0 KiB
INTENT — issue-core
Why it exists
The Coulomb org needs a single, observable place where tasks land — regardless of whether they were created by a human typing a CLI command, by an automation like activity-core acting on a rule, or by an agent acting on instructions.
Without a single landing zone, task creation fragments across:
- Per-repo Gitea issue trackers (siloed, no cross-repo view)
- Ad hoc files and TODO comments (invisible, unaudited)
- Agent-local memory and notebooks (lost when the agent ends)
- External SaaS trackers (rate-limited, off-network)
issue-core gives every actor — human or machine — one stable, observable place to file work, and one stable surface to consume work from.
What it is
A task lifecycle manager with a pluggable-backend architecture.
Responsibilities:
- Ingestion: accept new tasks via CLI, REST (
POST /issues/), and — in the future — NATS subscriptions. - Storage: route each task to the configured backend (Gitea, SQLite, GitHub).
- Lifecycle: create → assign → update → close, with state transitions that hold regardless of backend.
- Querying: list, search, filter across the active backend.
- Synchronization: bidirectional sync between local SQLite (source of truth for offline work) and remote backends.
Backends today: local SQLite, Gitea. Planned: GitHub, GitLab, JIRA.
The CLI entry points are issue (primary) and issue-core (explicit alias).
What it is NOT
issue-core is intentionally narrow. The following live elsewhere:
-
Not a project manager. Phases, campaigns, milestones spanning multiple tasks, dependency graphs across tasks, gantt-style scheduling — that is the domain of
project-core(planned). issue-core deals in individual tasks, not in plans composed of tasks. -
Not a spawn audit trail. When activity-core fires a rule that creates a task, the spawn event (who fired, what rule, what triggering event) is recorded in activity-core's
task_spawn_log. issue-core only stores the resulting task and itstriggering_event_idreference back. The audit-of-creation belongs to the emitter. -
Not an event bus. Communication between services flows over NATS (and state-hub progress events). issue-core consumes events, but does not relay them.
-
Not a notification system. Surfacing "your task changed" to humans is the job of the relevant UI / digest / chatbot layer, not issue-core.
-
Not a workflow engine. State transitions are simple (open → closed, with a few in-between states). Conditional routing, approvals, multi-step workflows — out of scope.
How it fits
+-------------------+
| activity-core |
| IssueSink (REST) |
+---------+---------+
|
POST /issues/ (TaskSpec payload)
|
v
+------------+ +-------+--------+ +-----------------+
| Humans +----->| |<-----+ Agents |
| CLI: | | issue-core | | (CLI or REST) |
| $ issue | | | | |
+------------+ +-------+--------+ +-----------------+
|
+---------+----------+
| Backend router |
+---+------+------+--+
| | |
v v v
+------+ +-----+ +------+
|Gitea | |SQLite| |GitHub|
+------+ +-----+ +------+
Upstream of issue-core (emitters):
- activity-core — emits tasks via
IssueSinkwhen a rule fires or an instruction declares one. Payload:TaskSpecoverPOST /issues/. - Humans —
$ issue create ...from terminals; future web UI. - Agents — same REST surface or CLI.
Downstream of issue-core (consumers):
- Humans and agents assigned tasks consume them via
$ issue list, web UI, or per-backend native UIs (Gitea web, GitHub PR view, etc.). - state-hub receives progress events as tasks move through their lifecycle.
- Status updates flow back to issue-core, not to the original emitter — activity-core does not track what happened to the task it spawned.
Success looks like
- Every task in the Coulomb org is discoverable from one query surface.
- activity-core can fire a rule and have the resulting task land in the right backend with the right metadata, with no human in the loop.
- The CLI experience is identical across SQLite-only laptops and full Gitea- backed servers.
- Offline work syncs back cleanly when connectivity returns.
See also
SCOPE.md— concrete in/out-of-scope decisions and integration boundaries.ROADMAP.md— feature trajectory.workplans/— active workstreams.- activity-core
docs/adr/adr-001-event-bridge-architecture.md— the IssueSink contract that issue-core honors atPOST /issues/.