docs: align INTENT with work-record framework; propose ISSUE-WP-0005
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s

Rewrite INTENT for UUIDv7+canonical identity, file-first topology, dual
lifecycles, intake+promotion findings path, and shipped vs target connector
surface. Add ISSUE-WP-0005 to implement mapping/store/CLI and close SCOPE
gaps; mark alignment-review remediation done.
This commit is contained in:
tegwick 2026-07-22 00:03:40 +02:00
parent e804c4e15f
commit 058b1b96f6
4 changed files with 438 additions and 134 deletions

287
INTENT.md
View file

@ -2,179 +2,206 @@
## Why it exists
The Coulomb org collaborates through **external issue trackers** (Forgejo /
Gitea, GitHub, Jira, …) when a human counterparty, open-source workflow, or
third-party process requires it. Those systems are not the fleet's internal
coordination substrate — that role belongs to **work records** authored as
repo files (ADR-001) and indexed by state-hub.
The Coulomb org coordinates work through **work records**: identified,
lifecycle-bearing artefacts authored as **repo files** (ADR-001), indexed by
state-hub, under a closed kind registry (`workplan`, `task`, `intake`,
`decision`, `engagement`, `register-entry`). That framework is defined in
`the-custodian/canon/standards/work-record-types_v0.1.md` and the founder-
reviewed architecture draft (`WorkOrchestrationArchitectureDraft.md` v0.2).
External issue trackers (Forgejo / Gitea, GitHub, Jira, …) remain necessary
when a human counterparty, open-source workflow, or third-party process lives
there. They are **not** the fleet coordination substrate and are **not** a
work-record kind. Canon is explicit: *issue-core issues become external
projections only.*
issue-core exists so that, **when an external tracker is actually in use**,
every actor can project, query, and update issues through one backend-agnostic
interface — and so the fleet can keep a stable **mapping** between internal
work-record identity (UUIDs) and external issue ids.
the fleet has one backend-agnostic surface to project, query, and update
tracker issues — and (target) a durable **mapping** between:
Without a connector layer, external-tracker access fragments across:
- Per-repo Gitea / Forgejo API clients (siloed, no shared mapping)
- Ad hoc `gh` / `glab` / curl scripts (untyped, unaudited)
- Agent-local integrations (lost when the agent ends)
- Direct SaaS API calls (rate-limited, off-network, no UUID back-reference)
| Side | Identity |
| --- | --- |
| Internal work record | **UUIDv7** (bookkeeping / mapping key) + **canonical name** for humans and agents (`ISSUE-WP-0005-T01`, …) |
| External issue | `(backend, external_id)` (+ URL) |
issue-core gives humans and machines one stable surface to talk to external
trackers, and (target shape) one place that records which internal work record
projects to which external issue.
Without a connector layer, external-tracker access fragments across per-repo
API clients, ad hoc `gh`/`glab`/curl, agent-local integrations, and SaaS
calls with no stable back-reference to the work record.
## Honest history (pivot, 2026-07-20)
issue-core was originally built and documented as a **task landing zone**: a
single observable place where humans, activity-core, and agents filed work via
CLI / REST / future NATS, with Gitea as the default store. That framing
contradicted the fleet decision that work originates as **repo files** and
that Forgejo issues are not the coordination mechanism.
single place where humans, activity-core, and agents filed work via CLI /
REST, with Gitea as the default store. That framing contradicted file-first
work records and produced a live incident (`daily-todo-md-stale-review`
IssueSink → Forgejo issues that were never fleet work).
The pivot was ratified while reviewing a live incident: activity-core's
`daily-todo-md-stale-review` ActivityDefinition routed findings through
`IssueSink` → issue-core → Forgejo, producing issues nobody was meant to see
as fleet work. Founder-reviewed architecture draft §4.2
(`the-custodian/research/WorkOrchestrationArchitectureDraft.md` v0.2,
2026-07-20) and the work-record canon
(`the-custodian/canon/standards/work-record-types_v0.1.md`, CUST-WP-0060)
settled the role below. Capability (CRUD, backends, REST, sync) stays; the
*purpose* is retargeted to connector, not origin.
Architecture draft §4.2 and the work-record types standard (CUST-WP-0060)
retargeted purpose: **connector, not origin**. Capability (CRUD, backends,
REST, backend-to-backend sync) stays; product north star is projection and
mapping at the boundary.
## What it is
A **connector framework to external issue-tracking systems**, with a
pluggable-backend architecture.
pluggable-backend architecture. Issue-core is **not** part of the internal
execution loop.
Responsibilities:
- **Projection / CRUD**: create, read, update, close, and comment on issues in
the configured backend (Gitea/Forgejo, SQLite offline cache, planned GitHub /
GitLab / Jira).
- **Mapping (target)**: maintain internal work-record UUID ↔ external issue id
so a work record can carry a back-reference to its tracker projection
(design: `docs/uuid-external-id-mapping.md`).
- **Boundary sync**: two-way, transclusion-like sync *at the boundary* when
collaboration runs through a third-party tracker — not as the internal
execution loop.
- **CLI + REST**: human and automation surfaces for direct backend use when a
tracker is intentionally switched on.
- **Optional ingestion**: `POST /issues/` remains for authenticated clients that
deliberately create tracker issues; it is **not** the primary fleet path for
internal findings or work origin.
### Shipped today
Backends today: **local SQLite**, **Gitea**. Planned: **GitHub**, **GitLab**, **JIRA**.
- **Tracker CRUD** on configured backends: create, read, update, close /
reopen, comment (and related label / assignee / milestone operations).
- **Backends:** local SQLite (offline store / cache), Gitea (Forgejo-
compatible in deployment). Further backends (GitHub, GitLab, Jira) are
product growth, not yet implemented.
- **CLI** (`issue` / `issue-core`) and **Python library** for direct backend use.
- **REST** (`issue serve`, optional `[api]` extra): intentional create
(`POST /issues/`), list/get/claim (`GET`/`PATCH /issues/`).
- **Backend↔backend sync** via CLI (e.g. Gitea ↔ SQLite) — *not* the same as
work-record boundary sync below.
- **Optional intentional ingestion** of TaskSpec payloads for clients that
deliberately create tracker issues (not the fleet path for internal findings).
The CLI entry points are `issue` (primary) and `issue-core` (explicit alias).
### Target connector (stage-3 work-record architecture)
Until an external integration is actually switched on for a given workflow, the
connector layer should add **zero load** to the internal coordination loop.
- **Mapping store:** durable work-record **UUIDv7**`(backend, external_id)`,
resolvable also by canonical work-record id; design in
`docs/uuid-external-id-mapping.md`.
- **Project / link CLI and API:** project an existing work record outward, or
link an existing external issue; idempotent on active mapping.
- **Boundary sync (when enabled):** optional two-way, transclusion-like sync
*at the boundary* for fields needed by external collab. **Zero load** when
no mapping/integration is configured.
- **Extend TaskSpec** with optional `work_record_uuid` (and kind/id denorm);
do **not** overload `triggering_event_id` (activity lineage only).
- Optional work-record file back-reference (canon-owned field names), mirroring
hub `state_hub_*_id` write-back patterns.
Until an external integration is **switched on** for a given workflow, the
connector must add **no coordination load** to the internal loop.
## What it is NOT
issue-core is intentionally narrow. The following live elsewhere:
- **Not the origin of work records.** Work records originate as repo files
(or schema-valid blocks in context) per ADR-001 and the work-record types
standard. issue-core does not create workplans, tasks, intake items,
decisions, engagements, or register entries as fleet artefacts.
- **Not the origin of work records.** Work records originate as repo files per
ADR-001 (`the-custodian/canon/architecture/adr-001-workplans-as-repo-artefacts.md`
and the work-record types standard). issue-core provides the
**external-tracker projection** when one is in use. Internal tasks, intake
items, workplans, and decisions are not created here.
- **Not a work-record kind.** Tracker issues are not registered in
`work-record-types`. Unmapped backend issues sit **outside** the work-record
spine; they are external artefacts for tracker UI collaboration until mapped
to a work-record UUID.
- **Not the internal execution / coordination loop.** Claiming and execution
run on work records directly (harness intake via NATS/activity-core per its
stated target). Fleet orientation is state-hub + repo files, not Forgejo
issue lists.
- **Not the internal execution / coordination loop.** Humans and agents
**claim and execute** on work records (harness / NATS / activity-core as
feeds). Fleet orientation is state-hub views over indexed files — not
Forgejo issue lists. (Avoid calling this “intake” when you mean claim/execute;
**`intake` is a work-record kind** for sparks/findings.)
- **Not a project manager.** Phases, campaigns, milestones spanning multiple
tasks, dependency graphs across tasks, gantt-style scheduling — that is the
domain of workplans / project tooling. issue-core deals in individual
external issues, not in plans composed of tasks.
- **Not the default home for automation findings.** Internal findings belong
as **`kind: intake`** (then **promotion** to task / workplan / decision /
engagement). They must not silently become Forgejo issues via IssueSink.
Emitter policy: activity-core **ACTIVITY-WP-0022** (from ISSUE-WP-0004-T05 /
CUST-WP-0060).
- **Not a spawn audit trail.** When an upstream service deliberately emits an
issue here, the *spawn event* belongs to the emitter (e.g. activity-core's
`task_spawn_log`). issue-core stores the resulting issue and optional
traceability fields (`triggering_event_id`, future work-record UUID) — not
the audit-of-creation.
- **Not a second autonomy or budget model.** `lane`, `tags`, and budgets live
on the work record. Projections carry only what external collab needs
(title, body, agreed labels); they must not invent parallel lane/budget
semantics on Gitea labels without explicit rules.
- **Not an event bus.** Communication between services flows over NATS (and
state-hub progress events). issue-core consumes or serves specific
boundaries; it does not relay events between other services.
- **Not a project manager, spawn audit trail, event bus, notification
system, or workflow engine.** Plans and dependencies are workplan tooling;
spawn audit stays with emitters; NATS/hub own inter-service events;
notifications and approval chains live elsewhere. Tracker state machine
stays small (`open` / `in_progress` / `blocked` / `closed`).
- **Not a notification system.** Surfacing "your task changed" to humans is
the job of the relevant UI / digest / chatbot layer, not issue-core.
### Boundary sync discipline
- **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.
Fleet work-record **`status`** (e.g. task `wait → todo → progress → done |
cancel`) and tracker **`IssueState`** (`open` / `in_progress` / `blocked` /
`closed`) are **distinct vocabularies**. They must not be merged casually.
- Outward / inward projection uses **explicit mapping rules**.
- Inward changes never **silently mutate** ADR-001 work-record files without
a defined writer (see mapping design open questions).
- Backend↔backend CLI sync is orthogonal to work-record boundary sync.
## How it fits
```
Work records (repo files, ADR-001) External collaboration
───────────────────────────────── ──────────────────────
workplan / task / intake / … Counterparty, OSS, Jira, …
│ │
│ optional project when │
│ a tracker is switched on │
v v
+------------------+ UUID ↔ issue id +------------------+
| state-hub | <---- mapping ------> | issue-core |
| (read model) | | (connector) |
+------------------+ +--------+---------+
|
+---------+----------+
| Backend router |
+---+------+------+--+
| | |
v v v
+------+ +-----+ +------+
|Gitea | |SQLite| |GitHub|
|Forgejo| |cache| | … |
+------+ +-----+ +------+
Direct use (human CLI / intentional REST) still goes to issue-core
without creating a work-record origin — useful for tracker admin and
collaboration, not for fleet task birth.
Repo files (ADR-001 / work-record kinds) External collaboration
workplan · task · intake · decision · Counterparty, OSS, Jira, …
engagement · register-entry
│ fix-consistency: register, UUIDv7 write-back
v
+------------------+
| state-hub | read model + generated views (not mapping authority)
+------------------+
│ optional project / link when a tracker is switched on
v
+------------------+ UUIDv7 (+ canonical id) +------------------+
| work-record | <---- mapping (target) ------> | issue-core |
| source (+ opt. | ↔ (backend, external_id) | (connector) |
| back-ref) | +--------+---------+
+------------------+ |
+---------+----------+
| Backend router |
+---+------+------+--+
| | |
v v v
Gitea/ SQLite GitHub
Forgejo cache (planned)
```
**Primary fleet path (coordination):**
1. A work record exists in a repo file (or is registered from one).
2. Humans/agents claim and execute against that record (and state-hub views).
3. **Optionally**, issue-core projects the record to an external tracker and
records the UUID ↔ external-id mapping.
1. Author or promote a **work record** in a repo file (`kind` from the closed
registry; findings enter as **intake**, then promote).
2. `fix-consistency` indexes the record and write-backs UUIDv7.
3. Claim / execute against the work record (and hub views).
4. **Optionally**, issue-core **projects or links** the record to an external
tracker and records the mapping (target).
**Secondary path (direct tracker use):**
- **Humans**`$ issue create ...` when deliberately working in a backend.
- **Authenticated automation**`POST /issues/` only when the product decision
is "create an external issue," not "spawn fleet work."
- **activity-core IssueSink** — must not be the default always-on path for
internal findings (see ISSUE-WP-0004-T05 / activity-core follow-up).
- Humans/agents use CLI/REST when deliberately operating on a backend
(tracker admin, pure external collab).
- Authenticated `POST /issues/` only when the product decision is “create an
**external** issue,” not “spawn fleet work.”
- Unmapped issues remain outside the work-record spine.
**Downstream:**
- Backend native UIs (Gitea web, GitHub, …) for external collaboration.
- state-hub for fleet lifecycle visibility of *work records*, not of every
issue-core row.
- Backend native UIs for external collaboration.
- state-hub for fleet lifecycle of *work records*, not of every issue-core row.
## Success looks like
- External trackers are usable through one CLI/API without each agent learning
platform-specific clients.
- When a work record is projected outward, the UUID ↔ external-id mapping is
durable and inspectable (once implemented per the design note).
- Internal automation does **not** silently open Forgejo issues for findings
that belong in repo work records.
- Offline SQLite work syncs cleanly to a remote backend when connectivity
- External trackers usable through one CLI/API without per-platform clients.
- When a work record is projected, UUIDv7 ↔ external-id mapping is durable and
resolvable by canonical name (once implemented).
- Fleet `status` and tracker state stay cleanly separated under explicit rules.
- Internal automation does **not** open Forgejo issues for findings that belong
as intake / promoted work records.
- Unmapped tracker issues are not mistaken for fleet work records.
- With no integration switched on, the connector adds no load to the internal
loop.
- Offline SQLite backend sync still works for tracker data when connectivity
returns.
- With no external integration switched on, issue-core adds no load to the
internal loop.
## See also
- `SCOPE.md` — concrete in/out-of-scope decisions and integration boundaries.
- `ROADMAP.md` — feature trajectory (connector-aligned).
- `docs/uuid-external-id-mapping.md` — design for the mapping surface.
- `workplans/ISSUE-WP-0004-align-with-work-record-canon.md` — this pivot.
- `the-custodian/canon/standards/work-record-types_v0.1.md` — work-record canon.
- `SCOPE.md` — shipped inventory, product boundary, TaskSpec contract.
- `docs/uuid-external-id-mapping.md` — mapping design (not implemented).
- `docs/intent-work-record-alignment-review.md` — audit that drove this rewrite.
- `workplans/ISSUE-WP-0004-align-with-work-record-canon.md` — initial pivot.
- `workplans/ISSUE-WP-0005-connector-alignment-implementation.md` — close
shipped-scope gaps against this intent.
- `the-custodian/canon/standards/work-record-types_v0.1.md` — kind registry,
spine, identity, promotion.
- `the-custodian/research/WorkOrchestrationArchitectureDraft.md` §4.2 —
founder-reviewed connector role.
- activity-core `docs/adr/adr-001-event-bridge-architecture.md` — IssueSink
contract at `POST /issues/` (optional, intentional use only).
connector decision.
- `the-custodian/canon/architecture/adr-001-workplans-as-repo-artefacts.md`.
- activity-core **ACTIVITY-WP-0022** — IssueSink default policy (emitter side).