generated from coulomb/repo-seed
chore(workplan): stub ISSC-WP-0001 rename to issue-core and task ingestion
Workplan for renaming issue-facade → issue-core and implementing the POST /issues/ task ingestion endpoint required by activity-core's IssueSink adapter. Covers rename, state hub registration, INTENT.md, SCOPE.md, REST endpoint, and NATS design stub. Hub workstream: 1135fc1d-1f46-4e35-886d-04cc3b8050b6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
230
workplans/ISSC-WP-0001-rename-and-task-ingestion.md
Normal file
230
workplans/ISSC-WP-0001-rename-and-task-ingestion.md
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
---
|
||||||
|
id: ISSC-WP-0001
|
||||||
|
type: workplan
|
||||||
|
domain: custodian
|
||||||
|
repo: issue-facade
|
||||||
|
status: active
|
||||||
|
state_hub_workstream_id: 1135fc1d-1f46-4e35-886d-04cc3b8050b6
|
||||||
|
tasks:
|
||||||
|
- id: T01
|
||||||
|
title: Rename package issue-facade → issue-core throughout
|
||||||
|
state_hub_task_id: b7054428-82a9-4d81-bfa8-5b5ee2eaf69f
|
||||||
|
status: todo
|
||||||
|
- id: T02
|
||||||
|
title: Register issue-core in state hub under capabilities domain
|
||||||
|
state_hub_task_id: b1d36996-44ff-48b9-b208-709d6874453c
|
||||||
|
status: todo
|
||||||
|
- id: T03
|
||||||
|
title: Write INTENT.md
|
||||||
|
state_hub_task_id: 265c6338-0310-409d-a081-6446042f6274
|
||||||
|
status: todo
|
||||||
|
- id: T04
|
||||||
|
title: Update or write SCOPE.md
|
||||||
|
state_hub_task_id: f95ac730-7ba0-4eae-bcae-de1e7d24b164
|
||||||
|
status: todo
|
||||||
|
- id: T05
|
||||||
|
title: Implement task ingestion REST endpoint POST /issues/
|
||||||
|
state_hub_task_id: 26af07e4-c072-42ad-bb5c-facb196156c9
|
||||||
|
status: todo
|
||||||
|
- id: T06
|
||||||
|
title: Document NATS subscriber interface (design stub)
|
||||||
|
state_hub_task_id: dff61fed-1e8c-4eb3-bbd6-1e3742329945
|
||||||
|
status: todo
|
||||||
|
created: "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:
|
||||||
|
|
||||||
|
1. **Rename**: `issue-facade` is a misleading name — it is not a facade, it is
|
||||||
|
the authoritative task lifecycle manager for the org. Renaming to `issue-core`
|
||||||
|
aligns with the naming pattern (`activity-core`, `rules-core`, `project-core`)
|
||||||
|
and signals its role clearly.
|
||||||
|
|
||||||
|
2. **Task ingestion endpoint**: activity-core's `IssueSink` adapter emits tasks to
|
||||||
|
issue-core via REST. That endpoint must exist, be stable, and accept `TaskSpec`
|
||||||
|
payloads from activity-core. Without it, activity-core's task emission is a
|
||||||
|
no-op.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
- **activity-core WP-0003** (in progress): implements `IssueSinkAdapter` in
|
||||||
|
`src/activity_core/issue_sink.py`. It calls `POST /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:
|
||||||
|
|
||||||
|
```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"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The endpoint must return:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"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):
|
||||||
|
|
||||||
|
```python
|
||||||
|
@router.post("/issues/")
|
||||||
|
async def ingest_task(payload: TaskIngestionRequest) -> TaskIngestionResponse:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
The endpoint must:
|
||||||
|
1. Validate the payload against `TaskIngestionRequest` schema
|
||||||
|
2. Route to the correct backend based on `target_repo` (look up backend config)
|
||||||
|
3. Create the issue/task in the backend
|
||||||
|
4. Return `{issue_id, issue_url, backend}`
|
||||||
|
5. Log the ingestion with `triggering_event_id` for 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 `TaskIngestionRequest` as 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
|
||||||
|
|
||||||
|
1. Package renamed to issue-core; all tests pass after rename
|
||||||
|
2. issue-core registered in state hub
|
||||||
|
3. INTENT.md and SCOPE.md committed and accurate
|
||||||
|
4. `POST /issues/` endpoint implemented and tested with a TaskSpec payload
|
||||||
|
5. activity-core agent confirmed IssueSink integration works end-to-end
|
||||||
|
6. 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.
|
||||||
Reference in New Issue
Block a user