diff --git a/docs/intent-work-record-alignment-review.md b/docs/intent-work-record-alignment-review.md new file mode 100644 index 0000000..3c586bf --- /dev/null +++ b/docs/intent-work-record-alignment-review.md @@ -0,0 +1,339 @@ +# INTENT.md vs work-record framework — alignment review + +**Date:** 2026-07-21 +**Subject:** `INTENT.md` (issue-core) +**Compared to:** + +| Source | Role | +| --- | --- | +| `the-custodian/canon/standards/work-record-types_v0.1.md` | Ratified work-record types & identity (v0.1, CUST-WP-0060) | +| `the-custodian/research/WorkOrchestrationArchitectureDraft.md` v0.2 §4.2, §1, §8 | Founder-reviewed architecture (connector decision) | +| `the-custodian/canon/architecture/adr-001-workplans-as-repo-artefacts.md` | File-first origin of work items | +| `SCOPE.md` (post-2026-07-21 inventory rewrite) | What this repo actually ships | +| `docs/uuid-external-id-mapping.md` | Mapping design (not implemented) | + +**Method:** Line-level reading of INTENT against the closed kind registry, +identity layering, reconciliation loop, and §4.2 connector decision. Classify +each topic as **aligned**, **soft friction**, **hard collision**, or **gap** +(framework has it; INTENT is silent in a way that can mislead). + +**Verdict (one line):** INTENT is **strategically aligned** with the work-record +restructuring (connector, not origin / not core loop). Remaining problems are +**terminology precision**, **diagram topology**, **dual lifecycle silence**, and +**aspirational “What it is” vs shipped reality** — not a return to the landing-zone +role. + +--- + +## 1. Work-record framework (compressed) + +The fleet restructured coordination around one umbrella and one loop: + +1. **Work record** = any identified, lifecycle-bearing coordination artefact. +2. **Closed kinds:** `workplan`, `task`, `intake`, `decision`, `engagement`, + `register-entry` — each with id scheme + abstract lifecycle. +3. **Spine fields:** `id`, `uuid` (UUIDv7), `kind`, `lane`, `status`, `owner`, + `repo`, `tags`, `created`/`updated`. +4. **Identity layering:** UUIDv7 for bookkeeping; **canonical names** for + humans/agents; hub writes UUID back into the source file. +5. **Origin:** any repo file may host schema-valid records (ADR-001 extended); + hub is a **read model**; `fix-consistency` registers and write-backs. +6. **Views** are generated (`[auto]`); hand queues are retired. +7. **Promotion** is first-class: `intake.routed → workplan|task|decision|engagement`. +8. **issue-core** (architecture §4.2, kind table absorbs column): + *connector to third-party trackers; mapping UUID ↔ external issue id; + two-way boundary sync; not part of the internal execution loop; zero load + until an integration is switched on.* + Task-kind legacy note: *“issue-core issues become external projections only.”* + +--- + +## 2. Alignment matrix + +| Framework claim | INTENT stance | Rating | +| --- | --- | --- | +| Work originates as repo files (ADR-001) | Explicit in “Why”, “What it is NOT”, primary path | **Aligned** | +| Hub is read model / index | Primary path + diagram (hub as read model) | **Aligned** (diagram caveat in §3.2) | +| issue-core is connector, not core loop | Title framing, §4.2 quote in history, NOT list | **Aligned** | +| Mapping UUID ↔ external issue id | Stated as target responsibility + design link | **Aligned** (not shipped — see §4) | +| Two-way boundary sync when tracker on | Listed under “What it is” | **Soft friction** (sounds present; is target) | +| Zero load until integration on | Explicit success criterion | **Aligned** | +| Issues are not a work-record kind | No inventing an `issue` kind; “external projections” | **Aligned** | +| Task lifecycle is `wait/todo/progress/done\|cancel` | Silent; IssueState is separate universe | **Soft friction / gap** | +| Closed kind list (6 kinds) | Mentions workplan / task / intake only | **Soft friction** (incomplete, not wrong) | +| UUIDv7 + canonical name dual identity | “UUIDs” only | **Soft friction** | +| Lanes, tags, budgets on every work record | Silent | **Gap** (acceptable for connector INTENT if projection never re-encodes them) | +| Promotion (`intake → …`) as proper path for findings | Says “don’t IssueSink”; does not name intake | **Gap** | +| Reconciliation loop (file → CI → fix-consistency → views → NATS) | issue-core kept off-loop (correct) | **Aligned** | +| Direct CLI/REST without work-record birth | Secondary path allowed for tracker admin | **Aligned with caveat** (§3.4) | +| activity-core must not default-spam Forgejo | Explicit secondary-path note + WP follow-up | **Aligned** (operational debt remains outside INTENT) | + +No **hard collision** found: INTENT does not reassert “single landing zone” as +the product north star, does not claim issue-core authors workplans/tasks as +fleet origin, and does not place Forgejo inside the internal claim/execute loop. + +--- + +## 3. Soft frictions and near-collisions + +### 3.1 Identity: UUID-only vs two-layer identity + +**Framework:** UUIDv7 is primary for bookkeeping; **canonical names** +(`ISSUE-WP-0004-T01`, …) are primary for humans and agents. + +**INTENT:** Speaks of “work-record identity (UUIDs)” and “UUID ↔ issue id” +without naming UUIDv7 or the human-facing id. + +**Why it matters:** Mapping implementation and CLI (`issue project +ISSUE-WP-…`) will almost always start from the **canonical name**; storage +key should be UUID. INTENT’s UUID-only phrasing can steer readers to hide +canonical ids or treat Gitea numbers as peer identity to human task names. + +**Recommendation:** In INTENT “Why / Mapping”, say: + +> Mapping keys on work-record **UUIDv7** (bookkeeping); operators and agents +> still address records by **canonical id**; external side is +> `(backend, external_id)`. + +### 3.2 Diagram topology: hub as mapping peer + +INTENT diagram: + +```text +state-hub <---- mapping ------> issue-core +``` + +**Framework topology is closer to:** + +```text +repo file (work record) --index--> state-hub (read model / views) + | + | optional project + v + issue-core (mapping store + backends) --> Forgejo/GitHub/… +``` + +**Friction:** Drawing hub ↔ issue-core as the mapping edge suggests the hub +is the internal endpoint of the connector. Canon: the **source file** (plus +optional denorm back-reference) is authoritative; the hub indexes it. Mapping +authority lives in issue-core’s store (design) and optionally write-back fields +on the work-record file — not “hub owns the mapping.” + +**Recommendation:** Redraw so work-record **files** are the left box; hub is +an index/view layer; mapping sits on issue-core ↔ file (and/or issue-core +store). + +### 3.3 Dual lifecycles (silent dualism) + +| Layer | Status vocabulary | +| --- | --- | +| Work-record **task** | `wait → todo → progress → done \| cancel` | +| Work-record **intake** | `open → vetted → routed → closed(…)` | +| issue-core `IssueState` | `open`, `closed`, `in_progress`, `blocked` | + +**INTENT** correctly says issue-core is not the execution loop, but never +warns that **these state machines are not the same thing** and must not be +merged casually during boundary sync. + +**Risk:** Future “two-way sync” implementers map `progress ↔ in_progress` +loosely and write fleet status from Forgejo (or vice versa) without a defined +writer — colliding with ADR-001 file authority and flow profiles. + +**Recommendation:** One short “Boundary sync discipline” bullet under +NOT / How it fits: + +> Fleet `status` and tracker `IssueState` are distinct. Sync is explicit +> projection rules, never silent mutation of work-record files without a +> defined writer (see mapping design). + +### 3.4 Secondary path: tracker issues outside the spine + +INTENT allows direct `$ issue create` / intentional REST **without** creating +a work-record origin — correct for pure external collaboration. + +**Caveat vs framework:** Anything that is *fleet coordination work* must still +be a work record. Unmapped tracker issues are **external artefacts**, not +second-class work records. INTENT’s “without creating a work-record origin” +is right; it should not be read as “tracker issues are informal work records.” + +**Recommendation:** One clarifying sentence: + +> Unmapped backend issues are outside the work-record spine. They become +> fleet-visible only when mapped to a work-record UUID (or when humans look +> at the tracker UI for external collab only). + +### 3.5 Incomplete kind list + +INTENT diagram: `workplan / task / intake / …` +Framework closed list also includes **decision**, **engagement**, +**register-entry**. + +Not a collision — ellipsis is honest — but projection design should not +assume “only tasks project.” Engagements (counterparty-facing) and some +register entries may also need external issues. Mapping design already allows +`work_record_kind`; INTENT could point at the full registry once. + +### 3.6 “Intake” overloaded + +INTENT: “harness intake via NATS/activity-core.” +Framework: **`intake` is a work-record kind**. + +Readers can conflate “event/task intake path” with “`kind: intake` spark +items.” Soft terminology debt shared with the architecture draft’s own +wording (“harness intake”). + +**Recommendation:** Prefer “harness **claim/execute** on work records +(NATS/activity-core as feed)” and reserve **intake** for the kind when +possible. + +### 3.7 Promotion gap (findings path incomplete) + +Framework answer to “automation found something”: + +```text +finding → kind:intake (repo file) → promote → task|workplan|… + optional later: issue-core project → external tracker +``` + +INTENT answer: + +```text +finding ↛ IssueSink/Forgejo (good) +finding → ??? (unspecified) +``` + +Not a collision with architecture §4.2, but **incomplete operational intent** +after the landing-zone ban. Operators reading only INTENT may pause sinks and +have no named replacement. + +**Recommendation:** Point at intake kind + promotion as the fleet path; +reference ACTIVITY-WP-0022 for sink policy and CUST-WP-0060 follow-ups. + +### 3.8 Lanes / tags / budgets + +Framework makes `lane` mandatory on every work record; tags and budgets are +normative. + +INTENT is silent — **acceptable** if projections never invent parallel +lane/budget models on issues. Soft risk if Gitea labels start carrying a +second autonomy model (`lane:green` as issue labels without mapping rules). + +**Recommendation:** Mapping/projection: lane, tags, budget stay on the work +record; tracker gets only fields needed for external collab (title, body, +labels agreed for humans). + +--- + +## 4. Aspirational INTENT vs shipped reality + +INTENT’s “What it is” lists responsibilities that mix **shipped** and +**target**. Cross-check with SCOPE inventory: + +| Responsibility in INTENT | Shipped? | +| --- | --- | +| Projection / CRUD on backends | **Yes** (SQLite, Gitea) | +| Mapping UUID ↔ external id | **No** — design only | +| Two-way boundary sync | **No** — CLI backend sync ≠ work-record boundary sync | +| CLI + REST | **Yes** | +| Optional intentional ingestion | **Yes** (and still over-used operationally) | +| Zero load when off | **Partially** — process can still run; product rule is policy + idle mapping, not auto-enforced | + +**Friction with framework:** Architecture §4.2 presents mapping + boundary sync +as *the* connector role. INTENT correctly marks mapping as target in one +bullet but lists boundary sync without the same “target” qualifier. Readers +can believe the work-record-aware connector is done when only the pre-canon +CRUD shell exists. + +**Recommendation:** Split INTENT “What it is” into **Shipped today** vs +**Target connector (stage-3)**, mirroring SCOPE §1 vs §2. + +--- + +## 5. Hard collisions + +**None** between INTENT’s product north star and the ratified work-record +framework. + +Historical landing-zone text is retained only under “Honest history,” which +is the correct pattern (do not erase the pivot). + +Residual **ecosystem** collisions (not INTENT text, but still real): + +| Location | Collision | +| --- | --- | +| activity-core `ISSUE_SINK_TYPE=rest` default | Still implements the banned always-on path until ACTIVITY-WP-0022 | +| `pyproject.toml` description | Still “Authoritative task lifecycle manager…” (packaging drift) | +| Registry capability summary | Still “coordination” framing toward multi-agent issue boards | +| Older workplans / AGENT examples | May still read as “agents coordinate via issues” as primary | + +Those should not block INTENT; they are cleanup follow-ups. + +--- + +## 6. Recommended INTENT edits (priority) + +| Priority | Edit | Why | +| --- | --- | --- | +| P1 | Split **Shipped** vs **Target** under “What it is” | Stop overstating mapping/boundary sync | +| P1 | Fix diagram: file → (hub index) + optional project → issue-core → backends | Match ADR-001 topology | +| P1 | Dual-lifecycle / boundary-sync discipline note | Prevent status-machine merge bugs | +| P2 | UUIDv7 + canonical name wording | Match identity layering | +| P2 | Point findings path at **intake + promotion**, not only “don’t IssueSink” | Close the operational gap | +| P2 | Clarify unmapped issues are outside the work-record spine | Avoid informal parallel ontology | +| P3 | Name full kind registry or link it once | Completeness | +| P3 | Prefer “claim/execute” over overloaded “intake” for harness | Terminology | + +**Out of scope for INTENT alone:** Implementing mapping, changing IssueSink +defaults, rewriting AGENT_INTEGRATION examples — those are separate work. + +--- + +## 7. Consistency with SCOPE.md (2026-07-21) + +| Topic | INTENT | SCOPE inventory | Match? | +| --- | --- | --- | --- | +| Connector role | Yes | Yes | Yes | +| Not work origin | Yes | §3.1 | Yes | +| Mapping | Target | Design + not shipped | Yes if INTENT softens “What it is” | +| Backends | SQLite + Gitea (+ planned) | Same | Yes | +| REST TaskSpec | Optional intentional | Full contract | Yes | +| State-hub runtime events from package | Downstream mention | Explicitly not shipped | Mild aspirational gap in older SCOPE; current SCOPE honest | + +INTENT and SCOPE are **compatible**; SCOPE is more operationally precise after +the inventory rewrite. INTENT should borrow SCOPE’s shipped/not-shipped +honesty without becoming a second inventory. + +--- + +## 8. Conclusion + +**INTENT.md matches the work-record restructuring on the decisive axes:** + +- File-first work records vs tracker as optional external projection +- Connector / mapping role per architecture §4.2 +- Explicit rejection of landing-zone / default Forgejo spam +- No parallel “issue” kind inside the closed registry + +**It collides only softly**, where language or diagrams can still be read as: + +- hub-centric mapping rather than file-centric origin, +- UUID-only identity, +- tracker states interchangeable with fleet statuses, +- connector responsibilities already delivered, +- or “stop IssueSink” without a named intake/promotion destination. + +**Suggested next step:** apply the P1/P2 INTENT edits in a small docs PR (or +follow-up session); keep this report as the audit trail. + +--- + +## References + +- `INTENT.md` +- `SCOPE.md` +- `docs/uuid-external-id-mapping.md` +- `workplans/ISSUE-WP-0004-align-with-work-record-canon.md` +- `the-custodian/canon/standards/work-record-types_v0.1.md` +- `the-custodian/research/WorkOrchestrationArchitectureDraft.md` (§1, §4.2, §8) +- `the-custodian/canon/architecture/adr-001-workplans-as-repo-artefacts.md` +- activity-core `workplans/ACTIVITY-WP-0022-issuesink-no-default-forgejo.md`