diff --git a/README.md b/README.md index 06adb4f..132f618 100644 --- a/README.md +++ b/README.md @@ -413,7 +413,8 @@ Your agent can then read plans/work items/tech debt and (with a write-scope key) - [x] **v0.4.3 — AI drafting (feature-flagged):** release notes & design notes drafted from delivered work, always landing in an editor - [x] **v0.4.4 — Asset Record (Phase A):** per-asset capabilities register with delivery lineage, graduation from resolved work items, derived known-issues/debt sections, tombstoned removals, `get_asset_record` + `graduate_work_item` MCP tools (41 total) - [x] **v0.4.5 — Asset Atlas** (see [`docs/specs/asset-atlas-spec.md`](docs/specs/asset-atlas-spec.md)): top-level Assets view — a live system map (products as columns, dependency edges, health/debt/activity lenses, blast-radius hover) plus grid and sortable table views -- [ ] **v0.4.6+ — Reconciliation & round-trip engineering** (see [`docs/specs/asset-record-spec.md`](docs/specs/asset-record-spec.md)): agent reconciliation proposals, release publishing +- [ ] **v0.4.6 — Layers & model boundaries** (see [`docs/specs/layers-and-boundaries-spec.md`](docs/specs/layers-and-boundaries-spec.md)): asset `layer` field, Atlas layer columns for single-product systems, `move_asset` model refactoring, boundary guidance in MCP +- [ ] **v0.4.7+ — Reconciliation & round-trip engineering** (see [`docs/specs/asset-record-spec.md`](docs/specs/asset-record-spec.md)): agent reconciliation proposals, release publishing - [ ] AI-assisted effort estimation - [ ] Billing / subscription management (hosted tier, optional & feature-flagged) diff --git a/docs/app-spec.md b/docs/app-spec.md index 829ad95..9fd81f3 100644 --- a/docs/app-spec.md +++ b/docs/app-spec.md @@ -4,7 +4,7 @@ > design and rationale, see `docs/specs/design-spec-v3.md` (all phases shipped), > `docs/specs/releases-and-asset-history-spec.md` (Phases A–D shipped), and > `docs/specs/asset-record-spec.md` (Phase A shipped; Phases B–C are the next -> tranche, v0.4.6+). +> tranche, v0.4.7+). ### Overview diff --git a/docs/guides/concepts.md b/docs/guides/concepts.md new file mode 100644 index 0000000..f630edd --- /dev/null +++ b/docs/guides/concepts.md @@ -0,0 +1,141 @@ +# How CodePlans Thinks + +CodePlans has a small object model with strong opinions. Most questions about +"where should this go?" answer themselves once you know what each object is +*for* — not just what it's called. This guide is the conceptual map: the +objects, the boundaries between them, and the design principles the whole tool +keeps returning to. + +## The object model in one pass + +``` +Product ──▶ Asset ──▶ (targeted by) Code Plan ──▶ Task + │ │ │ + │ │◀── Work Item (demand, linked many-to-many to plans) + │ │ + └─ Release ─┴─ stamps asset versions; groups the plans that ship together + +Per asset: History (derived diary) · Record (delivered reality) +``` + +| Object | What it is for | What it carries | +|---|---|---| +| **Product** | The unit you *ship, version, and grant access to* | Access control, code plans, releases, integrations targeting | +| **Asset** | The unit you *change* — the work surface | Health, tech debt, dependencies, owners, history, record | +| **Work item** | Demand — a feature, bug, UX issue, or debt someone wants addressed | Type, severity, status, target asset, links to plans | +| **Code plan** | A coordinated change — the bridge from demand to execution | Tasks, target assets (with branch/PR per asset), linked work items, its release | +| **Task** | The unit of execution | Status, assignee, effort, schedule | +| **Release** | What ships *together* — always an explicit human act | Attached plans, per-asset version stamps, derived release notes | +| **Record** | What an asset *is* today — delivered capabilities with receipts | Capabilities (with lineage), known issues, debt register | +| **History** | How the asset *got here* — a derived diary | Version stamps, delivered plans, resolved items, design notes | + +Two of these are load-bearing in ways that are easy to miss, and they're where +modeling questions concentrate: **products** and **assets**. + +## The boundary rule: products ship, assets change + +> **A product is something you ship, version, and grant access to as a unit. +> An asset is something you change.** + +Products aren't folders. Three mechanisms hang off the product boundary: + +1. **Access** — visibility is scoped by product. Splitting one system into + many products fragments who can see what. +2. **Plans** — every code plan belongs to one product, and can only target + that product's assets. Split a real system across products and a + cross-cutting change needs two plans where one is true. +3. **Releases** — a release is per-product, and its whole purpose is + coordinating a revision *across* assets: "Platform v2.4.0 takes Auth to + v1.8.0 and Search to v1.2.0." Products drawn too small make coordinated + releases structurally impossible to express. + +So the test for "should this be a product?" is not "does it have a clear +system boundary?" — most good *assets* have clear system boundaries. The test +is: **does it ship on its own cadence, under its own version, to its own +audience?** + +### Worked examples + +- **A single SaaS** (one app, one API, shared libraries, a datastore or + three): **one product**, many assets. Even at 30–40 assets, this is a + well-modeled instance, not an under-split one. Your releases coordinate + the whole surface; that's the point. +- **A portfolio** (the demo dataset): a web platform, mobile apps with + app-store release trains, and a public API with its own versioning + contract — **three products**, because each genuinely ships on its own + cadence to its own audience. +- **A monorepo** is orthogonal: one repo can host several products, and one + product can span several repos. Model the shipping boundary, not the + folder structure — assets carry `repoPath` for the folder mapping (see + [Modeling Monorepos](modeling-monorepos.md)). +- **A shared internal platform** consumed by other teams *is* a product if + it versions and publishes on its own contract — that's an audience. + +When in doubt, prefer **fewer products with more assets**. Assets are cheap, +carry all the operational texture (health, debt, dependencies, history, +record), and — by design — can be moved and refined later. Products are +commitments. + +### The second axis: layers + +Deep single-product systems still want internal structure — a backend API, +a domain library, and a web app are different *kinds* of asset even though +they ship together. That structure is a **layer**, not a product: an +attribute of the asset (edge, frontend, backend, domain, data, infra, +shared…) rather than a boundary around it. Layers give the +[Asset Atlas](asset-atlas.md) its columns when the product axis degenerates +(one product = one column), and give agents a vocabulary for structural +modeling. The layer concept is specced in +[`layers-and-boundaries-spec.md`](../specs/layers-and-boundaries-spec.md). + +## The design principles + +Five rules explain most of CodePlans' behavior. They're worth knowing because +new features keep being judged against them. + +**1. Derived, not maintained.** Anything that must be manually kept in sync +will rot — so wherever possible, views are *projections* of data the team +already maintains to run its work. Asset history is projected from plans, +work items, and releases. Release notes derive from the work items the +attached plans delivered. The Atlas map is drawn from the asset inventory and +dependency edges — there is deliberately no way to drag a node or pin a +layout, because stored layout would make the map a document again, and +documents rot. + +**2. Reality, not intent.** The asset Record only ever contains *delivered or +verified* claims — a capability enters it by graduating from a resolved work +item (with full lineage: work item → plan → release) or by being verified +against code. Intent lives upstream in work items and PM tools and links out. +This one rule is what keeps the record from becoming a second backlog. + +**3. Shipping is a human act.** Releases have an explicit lifecycle and an +explicit "Mark Shipped" — nothing infers shipping from merges or deploy +events. Shipped releases become read-only, because the record of what shipped +must stay trustworthy. Corrections reopen deliberately. + +**4. Agents are first-class users.** Everything the UI can do to the model, +the MCP server exposes — currently 41 tools, with the same access rules and +guardrails enforced at the tool layer (shipped releases reject mutation, +mirrored items reject writes to tracker-owned fields). Modeling guidance +ships *inside* the tools (`get_modeling_guide`, and heuristics in tool +descriptions), because for agent-driven modeling, the tool description *is* +the UX. Agent-authored artifacts (design notes) are attributed and badged, +never disguised as human. + +**5. Models are refinable.** Your first model of a system will be wrong +somewhere, and an agent's first pass more so. The tool is built so +refinement is cheap and history survives it: modeling operations are +idempotent (re-running a capture or modeling pass reconciles rather than +duplicates), records tombstone rather than delete, lineage text survives +foreign-key changes, and structural refactoring (moving an asset to the +right product, assigning layers) is a supported operation — not a data +migration. + +## Where to go next + +- [The Asset Atlas](asset-atlas.md) — the system map these boundaries feed +- [Releases & Versions](releases-and-versions.md) — the shipping boundary in practice +- [Asset History & the Design Log](asset-history.md) — the derived diary +- [Modeling Monorepos](modeling-monorepos.md) — repo structure vs model structure +- [Working with AI Agents](ai-agents.md) — the MCP tool catalog and agent workflows +- [`docs/app-spec.md`](../app-spec.md) — the authoritative current state diff --git a/docs/index.html b/docs/index.html index 2c04ad4..5538e5e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -558,6 +558,12 @@

App Spec

Complete spec of the current app: schemas, views, query/mutation API, access rules, and wiring gaps.

Read →
+ +
Guide
+

How CodePlans Thinks

+

The conceptual map: what products, assets, plans, and releases are each for, the boundary rule between them, and the five design principles behind the tool.

+
Read →
+
Guide

Capturing a Docs Corpus

@@ -615,7 +621,7 @@

Releases & Asset History Spec

Design

Asset Record Spec

-

The capabilities register per asset shipped in v0.4.4. Next (v0.4.6+): agent-driven reconciliation against code and round-trip release publishing.

+

The capabilities register per asset shipped in v0.4.4. Next (v0.4.7+): agent-driven reconciliation against code and round-trip release publishing.

Read →
@@ -624,6 +630,12 @@

Asset Atlas Spec

The map shipped in v0.4.5, and its path from picture to planning surface: lens thresholds, transitive blast radius, and plans started from the map.

Read →
+ +
Design
+

Layers & Boundaries Spec

+

Next (v0.4.6): the product-vs-asset rule made operational — asset layers, layer columns on the Atlas, and move_asset for refining a model.

+
Read →
+
Design

MCP Server Spec

@@ -941,7 +953,7 @@

Current feature status

AI drafting — release notes & design notes (feature-flagged)Available Asset Record — per-asset capabilities register with delivery lineage (v0.4.4)Available Asset Atlas — live system map with health/debt/activity lenses (v0.4.5)Available - Asset Record — agent reconciliation & round-trip publishing (v0.4.6+)Planned + Asset Record — agent reconciliation & round-trip publishing (v0.4.7+)Planned AI-assisted effort estimationPlanned diff --git a/docs/specs/asset-atlas-spec.md b/docs/specs/asset-atlas-spec.md index f9f42c9..3af87f3 100644 --- a/docs/specs/asset-atlas-spec.md +++ b/docs/specs/asset-atlas-spec.md @@ -178,6 +178,11 @@ shows humans. Write flows stay on the existing `create_code_plan` / Phases B–D are deliberately unversioned: they slot into the 4.x line as capacity allows, interleaved with the asset-record reconciliation work -(`v0.4.6+`), which remains the strategic priority. B is small and can ride +(`v0.4.7+`), which remains the strategic priority. B is small and can ride along with any release; C unlocks D and should precede it; D touches the plan-create flow and deserves its own release. + +The Atlas's second grouping axis — **layer columns** for single-product +systems — is specced separately in `layers-and-boundaries-spec.md` +(`v0.4.6`) together with the boundary guidance and `move_asset` it belongs +with. diff --git a/docs/specs/asset-record-spec.md b/docs/specs/asset-record-spec.md index fb7e423..eebd5b7 100644 --- a/docs/specs/asset-record-spec.md +++ b/docs/specs/asset-record-spec.md @@ -334,14 +334,14 @@ known issues/debt); resolve-time graduation prompt + backfill checklist; *Exit criteria: a team can build and browse a receipted capabilities register with zero agent involvement.* -### Phase B — Reconciliation `v0.4.6` +### Phase B — Reconciliation `v0.4.7` `record_proposals` + review queue UI; `propose_record_change`, `list_record_proposals`, `resolve_record_proposal` MCP tools; the reconcile guide; AI-drafted capability descriptions on graduation (flagged, Phase D plumbing). *Exit criteria: an agent-run reconcile pass on this repo files sensible proposals end-to-end.* -### Phase C — Round-trip `v0.4.7` +### Phase C — Round-trip `v0.4.8` Publish-to-GitHub-Releases action on shipped releases; spec-audit section in the reconcile guide; Record freshness surfaced on the asset header (oldest `verifiedAt` drives a "record last verified" hint). *Exit criteria: the litmus diff --git a/docs/specs/layers-and-boundaries-spec.md b/docs/specs/layers-and-boundaries-spec.md new file mode 100644 index 0000000..674a66d --- /dev/null +++ b/docs/specs/layers-and-boundaries-spec.md @@ -0,0 +1,162 @@ +# Layers & Model Boundaries — Design Spec + +> **Status: PROPOSED** (2026-08), targeting `v0.4.6`. Companion to +> `asset-atlas-spec.md` (this supplies the Atlas's second grouping axis) and +> the concepts guide (`docs/guides/concepts.md`, which states the boundary +> rule this spec operationalizes). Shifts asset-record reconciliation to +> `v0.4.7+` — and serves it: reconciliation agents will propose *structural* +> corrections too, and `move_asset` is the tool they need. + +--- + +## 1. Problem + +Between a product and its assets there is room for interpretation, and real +instances land on both sides of it. The demo dataset models a portfolio +(three products that genuinely ship separately); a production single-SaaS +instance correctly models **one product with ~40 assets** — and gets a +degenerate Atlas (one column), no vocabulary for internal structure, and no +supported way to refactor the model if the first pass drew a boundary wrong. + +Three gaps, one tranche: + +1. **Guidance** — the product-vs-asset rule exists in heads, not in the tool. + For agent-driven modeling, guidance must live in the MCP tool layer. +2. **Structure** — single-product systems need a second axis (*layer*) that + is an attribute of an asset, not a boundary around it. +3. **Mobility** — refining a model must be a supported operation with defined + semantics, not a data migration. + +## 2. Design rule (normative) + +> **A product is something you ship, version, and grant access to as a +> unit. An asset is something you change. Layers describe where an asset +> sits inside its product. When in doubt, prefer fewer products with more +> assets — assets are movable; products are commitments.** + +This rule is documented in the concepts guide, embedded in the MCP modeling +guide, and repeated in one-line form in the relevant tool descriptions. + +--- + +## 3. The `layer` field + +### 3.1 Schema + +`assets.layer` — nullable text, both dialects. Free text by design (teams' +vocabularies differ), with a **conventional taxonomy** promoted everywhere +the field is surfaced: + +`edge · frontend · backend · domain · data · infra · shared` + +### 3.2 Effective layer (display-time default) + +A null layer never renders as "unknown". The **effective layer** is derived +from asset type when unset: + +| Asset type | Default layer | +|---|---| +| app | frontend | +| service | backend | +| datastore | data | +| platform | infra | +| library | shared | + +Existing instances therefore get a sensible layered map with zero migration +or backfill. The default is computed at display/query time, never written to +the row — an explicit layer is a human (or agent) statement; a default is +not. + +### 3.3 Where it surfaces + +- **Asset edit** (product page dialog + MCP): a layer input offering the + taxonomy plus free entry. +- **Asset detail header**: a small layer chip beside the type badge (only + when explicitly set). +- **Atlas**: the grouping axis below. + +## 4. Atlas: layer columns + +- A **"Columns: Product | Layer"** toggle joins the Atlas toolbar. +- **Auto behavior**: when exactly one product is in scope (global product + filter, `?product=`, or the org simply has one product), the map defaults + to Layer columns; multi-product scope defaults to Product columns. The + toggle always overrides. +- Layer columns order by the conventional taxonomy sequence (edge → frontend + → backend → domain → data → infra → shared, unknown layers appended + alphabetically) — which matches typical dependency flow, so most edges + point one direction. +- In Layer mode, node sublabels show the product name when scope is + multi-product (the inverse of Product mode, where the lens detail shows). + Lenses, hover blast radius, filters, and the legend are unchanged. +- Grid gains a layer chip on cards; Table gains a Layer column (sortable, + effective layer, explicit ones marked). + +## 5. `moveAsset` — model refactoring with semantics + +`moveAsset(assetId, targetProductId)` — mutation + MCP tool (`move_asset`, +write scope). Not an `update_asset` side effect: the guardrails need a home. + +**Semantics:** + +1. **Blocked by open plans.** If any *draft or active* plan in the current + product targets the asset, the move fails with the list of blocking plans + (`{ error, blockingPlans: [{id, title, status}] }`). Retarget or complete + them first — silently detaching live work would falsify plans. +2. **Work items follow.** Work items with `assetId = asset` update their + `productId` to the target. Demand belongs to the asset. +3. **History is history.** Completed-plan links (`code_plan_assets`), + release version stamps (`release_assets`), sync-log entries, design-log + entries, capabilities and their lineage are all left untouched. An + asset's past does not change because its home does — same principle as + `originSummary` surviving FK nulling. Cross-product historical stamps + render as normal history entries. +4. **Access re-scopes automatically** — visibility follows the new product's + org scope; the mutation validates the caller can see both products. +5. Owners, dependencies, notes, health, debt, layer ride along unchanged + (dependency edges are asset-to-asset and product-agnostic). + +UI: a "Move to product…" action in the asset edit dialog exposing the same +mutation and surfacing blocking plans. MCP is the primary interface — model +refactoring is agent work. + +## 6. MCP changes + +- `create_asset` / `update_asset`: add optional `layer` param (taxonomy + named in the description, free text accepted). +- **New tool `move_asset`** (write): the §5 semantics, with the blocking-plan + error shaped for agent recovery. Tool count 41 → **42**. +- `get_modeling_guide`: new **Boundaries** section — the §2 rule, the layer + taxonomy with defaults table, the worked examples from the concepts guide + (single SaaS / portfolio / monorepo / internal platform), and a + "refining a model" recipe (audit → assign layers → `move_asset` where a + boundary was wrong → re-check the Atlas). +- One-line boundary heuristics added to `create_product` and `create_asset` + descriptions ("create a product only for something shipped, versioned, + and access-controlled as a unit — subsystems are assets with layers"). + +## 7. Demo seed + +Assign explicit layers to a representative subset of demo assets (leaving +some null to demonstrate effective-layer defaults), so a single-product +scope shows a credible layered map out of the box. + +## 8. Testing + +- Effective-layer derivation (explicit beats default; defaults per type). +- Inventory carries layers; Atlas grouping is pure client logic over it. +- `moveAsset`: blocks on draft/active plans with the correct list; moves + work items' product; preserves stamps, completed-plan links, and + capabilities; validates access on both ends; idempotent no-op when + already in the target product. + +## 9. Out of scope + +- Layer-scoped access control, per-layer health rollups, or any mechanism + hanging off layers — layers are *description*, not *boundary*. The moment + layers carry permissions they become products with extra steps. +- Auto-assigning persisted layers by heuristic or agent without an explicit + write — defaults stay display-time. +- Moving assets *across organizations*. +- Bulk/merge operations on products (merge two products = move assets one + by one, deliberately).