# SCOPE — issue-core Concrete in-scope / out-of-scope decisions for issue-core. Paired with `INTENT.md`, which explains *why*; this file states *what* and *what not*. ## In scope ### Task CRUD across backends - **Create** issues with title, description, labels, priority, type, milestone, assignee, due date. - **Read** individual issues and lists with filters (state, labels, priority, assignee, text search). - **Update** any mutable field on existing issues. - **Close / reopen** with state transitions enforced at the domain layer. - **Delete** where the backend allows (local SQLite; soft-archive elsewhere). - **Comment** threads on issues. ### Backend abstraction - A single `IssueBackend` ABC contract that every backend implements. - `BackendCapabilities` declares which optional features a backend supports (bulk update, search, milestones, etc.). - A `BackendFactory` registry that maps config to backend instances. ### Backends shipped today - **Local SQLite** — offline source of truth. - **Gitea** — REST API integration. ### Backends planned - **GitHub** — Issues + PRs. - **GitLab** — Issues. - **JIRA** — issues with story-points. ### Ingestion surfaces - **CLI** (`issue` / `issue-core`) for humans and agents on a shell. - **REST** (`POST /issues/`) for automation — primarily activity-core's `IssueSink`, but open to any well-authenticated client. - **NATS subscriber** (design stub only — implementation deferred until activity-core migrates from REST to NATS, see `docs/nats-task-ingestion.md`). ### Synchronization - Local SQLite ↔ remote backends, bidirectional. - `get_issues_modified_since()` on `SyncableBackend` for incremental sync. - Conflict resolution via `SyncableBackend.resolve_sync_conflict()`. - Sync metadata (last-synced timestamps, remote IDs) stored on `Issue.sync_metadata`. ### State Hub integration - Registered as a custodian-domain repo. - Emits `add_progress_event()` calls on significant task lifecycle moments. - Surfaces blocked tasks via the hub's `list_blocked_tasks()` view. ## Out of scope ### Project management Phases, campaigns, milestones-as-plans, dependency graphs between tasks, gantt-style scheduling, OKR linkage. **That is `project-core` (planned).** issue-core operates on individual tasks. A milestone field exists for flat grouping, not for multi-stage plans. ### Spawn audit trail When activity-core's IssueSink files a task here, the *spawn event* (who fired the rule, against which activity definition, on which triggering event) is recorded in **activity-core's `task_spawn_log`**. issue-core stores the resulting task and a back-reference (`triggering_event_id`) — nothing more. Symmetrically: issue-core does not push status updates back to activity-core. Lifecycle updates stay here; activity-core does not care what happens to a task it spawned. ### Event bus / message broker Inter-service communication runs on NATS managed elsewhere. issue-core consumes specific subjects (future) and exposes a REST surface; it does not relay events between other services. ### Notifications Telling a human "your task changed" is the job of the relevant UI, digest, chatbot, or notification service — not issue-core. issue-core emits progress events; downstream consumers decide what to do with them. ### Workflow / approval engine State machine is intentionally small (OPEN, CLOSED, IN_PROGRESS, BLOCKED). Conditional routing, approval chains, multi-step workflows, SLA timers — all out of scope. ### UI issue-core is CLI + REST first. Each backend brings its own native UI (Gitea web, GitHub web, etc.) and that is enough. A web UI for issue-core itself is not on the roadmap. ### Identity / access management Authentication relies on backend credentials (Gitea tokens, GitHub tokens) and on a service-level API key for the REST ingestion endpoint. issue-core is not a user directory. ## Integration boundaries ### Upstream emitters | Emitter | Transport | Payload | Notes | |----------------|----------------------|--------------------------|-------| | Human CLI | local process call | CLI args | The classic path. | | activity-core | REST `POST /issues/` | `TaskSpec` (see below) | Primary integration; planned NATS migration. | | Agents | REST or CLI | `TaskSpec` or CLI args | Same surfaces as humans/automation. | ### Downstream consumers | Consumer | Mechanism | Notes | |----------------------|------------------------------------|-------| | Humans / agents | `issue list`, web UI, backend UI | Standard task pickup. | | state-hub | `add_progress_event()` calls | Lifecycle visibility. | | Backend remote (e.g. Gitea) | direct backend write | Pass-through for the storage layer. | ### `TaskSpec` payload (from activity-core's IssueSink) ```json { "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" } ``` ### `POST /issues/` response ```json { "issue_id": "string", "issue_url": "string or null", "backend": "gitea | sqlite | github" } ``` The `issue_id` is the canonical back-reference activity-core stores in its `task_spawn_log`. It is owned and managed by issue-core; activity-core does not mutate it. ## See also - `INTENT.md` — why issue-core exists and how it fits in the Coulomb org. - `ROADMAP.md` — feature trajectory. - `workplans/ISSC-WP-0001-rename-and-task-ingestion.md` — current rename + ingestion workstream. - activity-core `docs/adr/adr-001-event-bridge-architecture.md` — the upstream side of the IssueSink contract.