Files
issue-core/INTENT.md
tegwick b605d970e3 feat: rename to issue-core and add task ingestion endpoint
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>
2026-05-17 05:16:27 +02:00

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 its triggering_event_id reference 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 IssueSink when a rule fires or an instruction declares one. Payload: TaskSpec over POST /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 at POST /issues/.