issue-core/SCOPE.md
tegwick d60175c354
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
docs: align issue-core with work-record connector role (ISSUE-WP-0004)
Retarget INTENT, SCOPE, README, ROADMAP, and agent docs from "task landing
zone" to external-tracker connector per work-record canon and architecture
draft §4.2. Add UUID↔external-id mapping design; mark ISSUE-WP-0004 finished
and cross-file activity-core ACTIVITY-WP-0022 for IssueSink policy.
2026-07-21 04:22:12 +02:00

9.2 KiB

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.

Fleet framing (2026-07-20): issue-core is a connector to external issue trackers and the home of the UUID ↔ external-id mapping concept. Work records originate as repo files (ADR-001 / work-record canon). See INTENT.md and docs/uuid-external-id-mapping.md.

In scope

External-issue CRUD across backends

  • Create issues with title, description, labels, priority, type, milestone, assignee, due date — when a tracker projection or direct tracker use is intentional.
  • 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 cache / source of truth for disconnected work.
  • Gitea — REST API integration (Forgejo-compatible in deployment).

Backends planned

  • GitHub — Issues + PRs.
  • GitLab — Issues.
  • JIRA — issues with story-points.

UUID ↔ external-id mapping (target shape)

Primary fleet responsibility of issue-core going forward — design only in this repo until stage-3 work-record architecture lands; see docs/uuid-external-id-mapping.md.

Concept Meaning
Internal id Work-record UUID (UUIDv7, hub-assigned / written back to source file as state_hub_*_id-style fields)
External id Backend issue id / number + backend identity (gitea, github, …)
Mapping row Durable association: which work record projects to which external issue
Direction Create projection outward; optional two-way sync of status/comments at the boundary

Named here so scope and design agree before implementation.

Operator / automation surfaces

  • CLI (issue / issue-core) for humans and agents on a shell — direct backend use.
  • REST (POST /issues/) for intentional external-issue creation by authenticated clients. Remains useful; is not the primary fleet path for originating work.
  • REST worker surface (GET/PATCH /issues/) for executors that operate on external issues when a tracker is in the loop: list, claim (in_progress + assignee), close.
  • NATS subscriber (design stub only — see docs/nats-task-ingestion.md). Any NATS path must respect the same rule: external projection only when explicitly configured, never silent origin of fleet work.

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 / infotech repo.
  • May emit add_progress_event() on significant connector lifecycle moments (e.g. projection created, mapping updated) when wired.
  • Does not replace work-record indexing; state-hub remains the fleet read model for work records.

Out of scope

Origin of fleet work

Creating workplans, tasks, intake items, decisions, or engagements. Those originate as repo files (or schema-valid blocks in context) and are indexed by fix-consistency / state-hub. issue-core may project an existing work record to a tracker; it does not birth the work record.

Default sink for internal automation findings

activity-core (and similar) must not treat POST /issues/ as the always-on default for every matched rule. That product decision lives in the emitter; issue-core will keep accepting authenticated POSTs but will not redefine itself as the landing zone. Follow-up: activity-core IssueSink policy (filed from ISSUE-WP-0004-T05).

Project management

Phases, campaigns, milestones-as-plans, dependency graphs between tasks, gantt-style scheduling, OKR linkage. That is workplan / project tooling. issue-core operates on individual external issues. A milestone field exists for flat grouping, not for multi-stage plans.

Spawn audit trail

When an emitter files an issue here, the spawn event (who fired, which rule, which triggering event) is recorded by the emitter (e.g. activity-core's task_spawn_log). issue-core stores the resulting issue and traceability fields (triggering_event_id today; work-record UUID in the mapping design) — nothing more.

Symmetrically: issue-core does not push fleet work-record status updates back to activity-core. Lifecycle of external issues stays here; lifecycle of work records stays in repo files + hub.

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.

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 endpoint. issue-core is not a user directory.

Integration boundaries

Fleet primary path (work records)

Step Owner Notes
Author / promote work record Repo files + tools ADR-001 / work-record canon
Index + UUID write-back state-hub fix-consistency Hub is read model
Claim / execute Humans, agents, harness On work records, not on Forgejo by default
Optional external projection issue-core Mapping table + backend CRUD

Surfaces into issue-core

Client Transport Payload Role
Human CLI local process CLI args Direct tracker use / admin
Agents REST or CLI issue fields or CLI args Tracker ops when in the loop
activity-core IssueSink REST POST /issues/ TaskSpec Optional, intentional external issues only — not default for internal findings
Future mapping API REST/CLI (TBD) work_record_uuid + project request Primary fleet connector path once designed

Downstream consumers

Consumer Mechanism Notes
Humans / external collab backend UI, issue list Third-party tracker collaboration
state-hub work-record index; optional progress events Fleet orientation
Backend remote (e.g. Gitea) direct backend write Storage / projection layer

TaskSpec payload (activity-core IssueSink — retained contract)

Still accepted for backward compatibility and intentional emits:

{
  "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": "event uuid or stable source key",
  "activity_definition_id": "string"
}

triggering_event_id is accepted as a non-empty string. Event-driven emissions should send the upstream activity event UUID. Scheduled or cron emissions that do not have a concrete event row may send a stable source key such as scheduled; issue-core stores the value verbatim in ingestion metadata for traceability.

Relation to mapping design: triggering_event_id is emitter-side traceability, not a work-record UUID. The mapping surface will add an explicit work-record identity field (and durable mapping rows). See docs/uuid-external-id-mapping.md — extend rather than overload triggering_event_id.

POST /issues/ response

{
  "issue_id": "string",
  "issue_url": "string or null",
  "backend": "gitea | sqlite | github"
}

The issue_id is the external-issue back-reference an intentional emitter may store (e.g. activity-core task_spawn_log). It is owned by issue-core's backend; it is not a work-record UUID.

See also

  • INTENT.md — why issue-core exists and the connector pivot.
  • ROADMAP.md — feature trajectory.
  • docs/uuid-external-id-mapping.md — mapping design (not yet implemented).
  • workplans/ISSUE-WP-0004-align-with-work-record-canon.md — alignment work.
  • the-custodian/canon/standards/work-record-types_v0.1.md — work-record kinds; task kind notes that issue-core issues are external projections only.
  • activity-core docs/adr/adr-001-event-bridge-architecture.md — IssueSink contract (emitter side; policy follow-up separate).