@magic-spells/constellation 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/README.md +13 -6
  2. package/constellation/agent/AGENT-GUIDANCE.md +22 -0
  3. package/constellation/component/COMPONENT-EDITABLE.md +9 -0
  4. package/constellation/component/COMPONENT-STATUS-PILL.md +9 -0
  5. package/constellation/component/COMPONENT-SYNC-PILL.md +9 -0
  6. package/constellation/decision/DECISION-FEATURE-RELEASE-TYPES.md +50 -0
  7. package/constellation/decision/DECISION-NATIVE-DECISION-TYPE.md +58 -0
  8. package/constellation/diagram/DIAGRAM-ARCHITECTURE.md +28 -0
  9. package/constellation/doc/DOC-CARD-TYPES.md +39 -0
  10. package/constellation/doc/DOC-CHANGE-TRACKING.md +26 -0
  11. package/constellation/doc/DOC-CONNECTED-REPOS.md +25 -0
  12. package/constellation/doc/DOC-DIAGRAMS.md +22 -0
  13. package/constellation/doc/DOC-FILE-FORMAT.md +54 -0
  14. package/constellation/doc/DOC-LINT-CODES.md +35 -0
  15. package/constellation/doc/DOC-MCP-SERVER.md +59 -0
  16. package/constellation/doc/DOC-MCP-UPGRADES.md +57 -0
  17. package/constellation/external/EXTERNAL-AJV.md +7 -0
  18. package/constellation/external/EXTERNAL-GIT.md +7 -0
  19. package/constellation/external/EXTERNAL-GRAY-MATTER.md +7 -0
  20. package/constellation/external/EXTERNAL-MCP-SDK.md +7 -0
  21. package/constellation/external/EXTERNAL-ZOD.md +7 -0
  22. package/constellation/file/FILE-CLI.md +9 -0
  23. package/constellation/file/FILE-CODE.md +9 -0
  24. package/constellation/file/FILE-EXTRACT.md +9 -0
  25. package/constellation/file/FILE-GIT.md +9 -0
  26. package/constellation/file/FILE-HANDLES.md +9 -0
  27. package/constellation/file/FILE-INDEXER.md +11 -0
  28. package/constellation/file/FILE-LINT.md +9 -0
  29. package/constellation/file/FILE-MCP-SEARCH.md +12 -0
  30. package/constellation/file/FILE-MCP-SERVER.md +9 -0
  31. package/constellation/file/FILE-PARSE.md +9 -0
  32. package/constellation/file/FILE-RENAME.md +18 -0
  33. package/constellation/file/FILE-REPOS.md +9 -0
  34. package/constellation/file/FILE-RESOLVE.md +9 -0
  35. package/constellation/file/FILE-SCAFFOLD.md +12 -0
  36. package/constellation/file/FILE-SERVE.md +9 -0
  37. package/constellation/file/FILE-SYNC.md +9 -0
  38. package/constellation/file/FILE-TYPES.md +9 -0
  39. package/constellation/file/FILE-VALIDATE.md +11 -0
  40. package/constellation/file/FILE-WRITER.md +11 -0
  41. package/constellation/flow/FLOW-DRIFT-DETECT.md +11 -0
  42. package/constellation/flow/FLOW-LINT-PIPELINE.md +14 -0
  43. package/constellation/flow/FLOW-SYNC-PLAN.md +13 -0
  44. package/constellation/page/PAGE-VIEWER-CARD.md +9 -0
  45. package/constellation/page/PAGE-VIEWER-HOME.md +9 -0
  46. package/constellation/plan.md +59 -0
  47. package/constellation/test/TEST-SUITE.md +9 -0
  48. package/dist/cli/index.js +37 -0
  49. package/dist/cli/index.js.map +1 -1
  50. package/dist/core/code.d.ts +4 -2
  51. package/dist/core/code.js +22 -7
  52. package/dist/core/code.js.map +1 -1
  53. package/dist/core/git.d.ts +2 -0
  54. package/dist/core/git.js +6 -0
  55. package/dist/core/git.js.map +1 -1
  56. package/dist/core/handles.d.ts +1 -1
  57. package/dist/core/handles.js +4 -1
  58. package/dist/core/handles.js.map +1 -1
  59. package/dist/core/indexer.js +1 -1
  60. package/dist/core/rename.d.ts +24 -0
  61. package/dist/core/rename.js +72 -0
  62. package/dist/core/rename.js.map +1 -0
  63. package/dist/core/repos.d.ts +2 -0
  64. package/dist/core/repos.js +5 -1
  65. package/dist/core/repos.js.map +1 -1
  66. package/dist/core/sync.d.ts +2 -0
  67. package/dist/core/sync.js +3 -1
  68. package/dist/core/sync.js.map +1 -1
  69. package/dist/core/types.d.ts +1 -1
  70. package/dist/core/types.js +3 -2
  71. package/dist/core/types.js.map +1 -1
  72. package/dist/core/validate.js +14 -1
  73. package/dist/core/validate.js.map +1 -1
  74. package/dist/core/writer.d.ts +29 -0
  75. package/dist/core/writer.js +98 -3
  76. package/dist/core/writer.js.map +1 -1
  77. package/dist/mcp/search.d.ts +2 -2
  78. package/dist/mcp/search.js +27 -5
  79. package/dist/mcp/search.js.map +1 -1
  80. package/dist/mcp/server.js +311 -101
  81. package/dist/mcp/server.js.map +1 -1
  82. package/dist/serve/server.js +6 -7
  83. package/dist/serve/server.js.map +1 -1
  84. package/examples/constellation/decision/DECISION-NO-HARD-DELETE.md +31 -0
  85. package/examples/constellation/feature/FEATURE-AUTO-ASSIGNMENT.md +24 -0
  86. package/examples/constellation/release/RELEASE-V1-1-0.md +14 -0
  87. package/package.json +2 -2
  88. package/schemas/decision.json +14 -0
  89. package/schemas/doc.json +1 -1
  90. package/schemas/feature.json +19 -0
  91. package/schemas/plan.json +1 -1
  92. package/schemas/release.json +14 -0
  93. package/skill/SKILL.md +39 -7
  94. package/skill/methodology.md +10 -3
  95. package/skill/types/decision.md +59 -0
  96. package/skill/types/doc.md +2 -2
  97. package/skill/types/feature.md +53 -0
  98. package/skill/types/plan.md +1 -1
  99. package/skill/types/release.md +37 -0
  100. package/viewer/dist/assets/{arc-YuzGWkw8.js → arc-DcXsmPgw.js} +1 -1
  101. package/viewer/dist/assets/architecture-7EHR7CIX-CXZxmtF5.js +1 -0
  102. package/viewer/dist/assets/{architectureDiagram-3BPJPVTR-BgksqMlF.js → architectureDiagram-3BPJPVTR-Cfq3OC2M.js} +1 -1
  103. package/viewer/dist/assets/{blockDiagram-GPEHLZMM-Bc6JILFK.js → blockDiagram-GPEHLZMM-CPuRJqEW.js} +1 -1
  104. package/viewer/dist/assets/{c4Diagram-AAUBKEIU-CRVt42df.js → c4Diagram-AAUBKEIU-CcVcItWo.js} +1 -1
  105. package/viewer/dist/assets/channel-DjvAjJNc.js +1 -0
  106. package/viewer/dist/assets/{chunk-2J33WTMH-CpuwKeX6.js → chunk-2J33WTMH-C_N821rH.js} +1 -1
  107. package/viewer/dist/assets/{chunk-3OPIFGDE-BG_ijJhE.js → chunk-3OPIFGDE-C5c2MY1i.js} +1 -1
  108. package/viewer/dist/assets/{chunk-4BX2VUAB-Bgz1tnDP.js → chunk-4BX2VUAB-BjYatXZ-.js} +1 -1
  109. package/viewer/dist/assets/{chunk-55IACEB6-NdWURd2K.js → chunk-55IACEB6-A3JXj2W_.js} +1 -1
  110. package/viewer/dist/assets/{chunk-5ZQYHXKU-wzW5x_7z.js → chunk-5ZQYHXKU-zDiW1Z3e.js} +1 -1
  111. package/viewer/dist/assets/{chunk-727SXJPM-BxKeJXYf.js → chunk-727SXJPM-CI3VBaXr.js} +1 -1
  112. package/viewer/dist/assets/{chunk-AQP2D5EJ-gPm6xhPX.js → chunk-AQP2D5EJ-DHpkJ1wF.js} +1 -1
  113. package/viewer/dist/assets/{chunk-BSJP7CBP-C30ZXEUD.js → chunk-BSJP7CBP-DXx1-_Zs.js} +1 -1
  114. package/viewer/dist/assets/{chunk-CSCIHK7Q-C9h7yfl1.js → chunk-CSCIHK7Q-DQOe6SQo.js} +6 -6
  115. package/viewer/dist/assets/{chunk-FMBD7UC4-BcSnkYc3.js → chunk-FMBD7UC4-DSvwBCfP.js} +1 -1
  116. package/viewer/dist/assets/{chunk-KSCS5N6A-rxSD5-MD.js → chunk-KSCS5N6A-C3haQOao.js} +1 -1
  117. package/viewer/dist/assets/{chunk-L5ZTLDWV-DGwFsVWy.js → chunk-L5ZTLDWV-DyHfVaRK.js} +1 -1
  118. package/viewer/dist/assets/{chunk-LZXEDZCA-BY3sTuvt.js → chunk-LZXEDZCA-CtMQqok_.js} +2 -2
  119. package/viewer/dist/assets/{chunk-ND2GUHAM-PqmKwdzq.js → chunk-ND2GUHAM-Cfp2zN_i.js} +1 -1
  120. package/viewer/dist/assets/{chunk-NZK2D7GU-BAZbzxhl.js → chunk-NZK2D7GU-Cn753oIP.js} +1 -1
  121. package/viewer/dist/assets/{chunk-O5CBEL6O-SvZfZ-0j.js → chunk-O5CBEL6O-BO32_B2k.js} +1 -1
  122. package/viewer/dist/assets/chunk-QZHKN3VN-uc4X3bta.js +1 -0
  123. package/viewer/dist/assets/chunk-WU5MYG2G-D-wARmLR.js +1 -0
  124. package/viewer/dist/assets/{chunk-XPW4576I-1OXPbRQX.js → chunk-XPW4576I-DQFQAfwD.js} +1 -1
  125. package/viewer/dist/assets/classDiagram-4FO5ZUOK-CosoTts2.js +1 -0
  126. package/viewer/dist/assets/classDiagram-v2-Q7XG4LA2-CosoTts2.js +1 -0
  127. package/viewer/dist/assets/{cose-bilkent-S5V4N54A-DtCvLpah.js → cose-bilkent-S5V4N54A-Ibe8V5Cm.js} +1 -1
  128. package/viewer/dist/assets/{dagre-BM42HDAG-B55Ilz10.js → dagre-BM42HDAG-BlOzR9WP.js} +1 -1
  129. package/viewer/dist/assets/{diagram-2AECGRRQ-ClqSMarp.js → diagram-2AECGRRQ-l8omQVTU.js} +1 -1
  130. package/viewer/dist/assets/{diagram-5GNKFQAL-Dx74UdxY.js → diagram-5GNKFQAL-_rHQzAtO.js} +1 -1
  131. package/viewer/dist/assets/{diagram-KO2AKTUF-Vj0buH8e.js → diagram-KO2AKTUF-DCLRVRMY.js} +1 -1
  132. package/viewer/dist/assets/{diagram-LMA3HP47-DpEm8RZd.js → diagram-LMA3HP47-14HnEIqk.js} +1 -1
  133. package/viewer/dist/assets/{diagram-OG6HWLK6-Crl3BdwC.js → diagram-OG6HWLK6-CVKNCbkR.js} +1 -1
  134. package/viewer/dist/assets/{dist-C2uHOEFB.js → dist-BcVVfWxM.js} +1 -1
  135. package/viewer/dist/assets/{erDiagram-TEJ5UH35-B-Mf-EHP.js → erDiagram-TEJ5UH35-CNjpEfJD.js} +1 -1
  136. package/viewer/dist/assets/eventmodeling-FCH6USID-Dv27utnc.js +1 -0
  137. package/viewer/dist/assets/{flowDiagram-I6XJVG4X-B9stChWN.js → flowDiagram-I6XJVG4X-Bvekb5gu.js} +1 -1
  138. package/viewer/dist/assets/{ganttDiagram-6RSMTGT7-DzWlclwM.js → ganttDiagram-6RSMTGT7-2TpeWF0N.js} +1 -1
  139. package/viewer/dist/assets/{gitGraph-WXDBUCRP-CdVI3GTp.js → gitGraph-WXDBUCRP-CPfybYvf.js} +1 -1
  140. package/viewer/dist/assets/{gitGraphDiagram-PVQCEYII-Dn9yRc1N.js → gitGraphDiagram-PVQCEYII-BWZNJ9lY.js} +1 -1
  141. package/viewer/dist/assets/index-BEJYsfzU.css +2 -0
  142. package/viewer/dist/assets/{index-BsGRgBOD.js → index-Cqx2pndu.js} +3 -3
  143. package/viewer/dist/assets/{info-J43DQDTF-CXV3Mm9T.js → info-J43DQDTF-CxgngY4X.js} +1 -1
  144. package/viewer/dist/assets/{infoDiagram-5YYISTIA-zIUka_J2.js → infoDiagram-5YYISTIA-CARF_viY.js} +1 -1
  145. package/viewer/dist/assets/{ishikawaDiagram-YF4QCWOH-DsZwNuE3.js → ishikawaDiagram-YF4QCWOH-DcxZvtur.js} +1 -1
  146. package/viewer/dist/assets/{journeyDiagram-JHISSGLW-BhSTSB2s.js → journeyDiagram-JHISSGLW-Wu7zolY5.js} +1 -1
  147. package/viewer/dist/assets/{kanban-definition-UN3LZRKU-sCAldj86.js → kanban-definition-UN3LZRKU--LMKLf5s.js} +1 -1
  148. package/viewer/dist/assets/{line-D7b3fopb.js → line-DH7DV7uw.js} +1 -1
  149. package/viewer/dist/assets/{linear-BWlvVc_d.js → linear-C6xJ2LrZ.js} +1 -1
  150. package/viewer/dist/assets/{mermaid-parser.core-BdEYBvaj.js → mermaid-parser.core-DkqLwTDu.js} +2 -2
  151. package/viewer/dist/assets/{mermaid.core-C9bGWeJU.js → mermaid.core-H-eI9axh.js} +3 -3
  152. package/viewer/dist/assets/{mindmap-definition-RKZ34NQL-DbTvvku-.js → mindmap-definition-RKZ34NQL-xjt8VE8m.js} +1 -1
  153. package/viewer/dist/assets/{packet-YPE3B663-DRfLruyq.js → packet-YPE3B663-BX0W_wIa.js} +1 -1
  154. package/viewer/dist/assets/{pie-LRSECV5Y-47xXMkK-.js → pie-LRSECV5Y-B8cD_uBh.js} +1 -1
  155. package/viewer/dist/assets/{pieDiagram-4H26LBE5-Ckno9E1M.js → pieDiagram-4H26LBE5-DpM-20zS.js} +1 -1
  156. package/viewer/dist/assets/{quadrantDiagram-W4KKPZXB-XB5kJ_2c.js → quadrantDiagram-W4KKPZXB-CLS4_FQ4.js} +1 -1
  157. package/viewer/dist/assets/{radar-GUYGQ44K-CLwIH5Zr.js → radar-GUYGQ44K-CQKcm4b5.js} +1 -1
  158. package/viewer/dist/assets/{requirementDiagram-4Y6WPE33-D3fApL0X.js → requirementDiagram-4Y6WPE33-ESLvOyQ5.js} +1 -1
  159. package/viewer/dist/assets/{sankeyDiagram-5OEKKPKP-6UdaRhuZ.js → sankeyDiagram-5OEKKPKP-BT6w9JdP.js} +1 -1
  160. package/viewer/dist/assets/{sequenceDiagram-3UESZ5HK-ClIrrs0w.js → sequenceDiagram-3UESZ5HK-DJNAaEbv.js} +1 -1
  161. package/viewer/dist/assets/{src-BPb55SrS.js → src-ituc2uBy.js} +1 -1
  162. package/viewer/dist/assets/{stateDiagram-AJRCARHV-CCsrcv5R.js → stateDiagram-AJRCARHV-Bw7VoMlA.js} +1 -1
  163. package/viewer/dist/assets/stateDiagram-v2-BHNVJYJU-DZdCGd2U.js +1 -0
  164. package/viewer/dist/assets/{timeline-definition-PNZ67QCA-BkiWQlVI.js → timeline-definition-PNZ67QCA-Ddr17PAT.js} +1 -1
  165. package/viewer/dist/assets/{treeView-BLDUP644-m1mGpAE8.js → treeView-BLDUP644-mqjp8QBZ.js} +1 -1
  166. package/viewer/dist/assets/{treemap-LRROVOQU-Bapvwi0Q.js → treemap-LRROVOQU-BeaxV5lr.js} +1 -1
  167. package/viewer/dist/assets/{vennDiagram-CIIHVFJN-BlH71Nmx.js → vennDiagram-CIIHVFJN-ySQYfWol.js} +1 -1
  168. package/viewer/dist/assets/{wardley-L42UT6IY-CPRSoKgV.js → wardley-L42UT6IY-BvtBpxdo.js} +1 -1
  169. package/viewer/dist/assets/{wardleyDiagram-YWT4CUSO-C-ptFJ9t.js → wardleyDiagram-YWT4CUSO-DRZFQiXX.js} +1 -1
  170. package/viewer/dist/assets/{xychartDiagram-2RQKCTM6-C4rfeH4W.js → xychartDiagram-2RQKCTM6-kXPrRy2n.js} +1 -1
  171. package/viewer/dist/index.html +2 -2
  172. package/docs/001-file-format.md +0 -265
  173. package/docs/002-mcp.md +0 -186
  174. package/docs/003-mcp-upgrade-plan.md +0 -138
  175. package/viewer/dist/assets/architecture-7EHR7CIX-BAboPvK1.js +0 -1
  176. package/viewer/dist/assets/channel-D8YnBgqu.js +0 -1
  177. package/viewer/dist/assets/chunk-QZHKN3VN-ClYnv9g5.js +0 -1
  178. package/viewer/dist/assets/chunk-WU5MYG2G-CvL2Yleq.js +0 -1
  179. package/viewer/dist/assets/classDiagram-4FO5ZUOK-B8YUd1jx.js +0 -1
  180. package/viewer/dist/assets/classDiagram-v2-Q7XG4LA2-B8YUd1jx.js +0 -1
  181. package/viewer/dist/assets/eventmodeling-FCH6USID-CZ5gxAxG.js +0 -1
  182. package/viewer/dist/assets/index-Bqs39Itl.css +0 -2
  183. package/viewer/dist/assets/stateDiagram-v2-BHNVJYJU-C1phrPNi.js +0 -1
@@ -1,265 +0,0 @@
1
- # Constellation File Format (v2)
2
-
3
- Constellation stores a project's architecture plan as markdown files in the repo, under a
4
- `constellation/` folder. Each file is one **card** — one typed piece of the plan,
5
- linked to other cards by **connections**. ("Node" is reserved for diagram elements
6
- inside DIAGRAM cards; everything else is a card.)
7
- Git provides branching, diffing, merging, and history for the plan; the Constellation
8
- tooling (lint, MCP, viewer) provides validation, graph queries, and rendering on top.
9
-
10
- This document is the normative format spec. The JSON Schemas in `schemas/` define the
11
- per-type frontmatter fields; the skill in `skill/` teaches AI agents to author cards.
12
-
13
- ## Design principles
14
-
15
- 1. **The files are the source of truth.** Everything else — reverse indexes, catalogs,
16
- rollups, subgraph diagrams, diffs — is derived in memory and never stored.
17
- 2. **A card with no frontmatter is valid.** The file path gives identity; the body gives
18
- content. All structure is opt-in.
19
- 3. **Git is the change-tracking system.** `git diff -- constellation/` *is* the plan diff.
20
- Lifecycle state (`status`) is a property of a card; "what changed" is a property of
21
- history — the format never conflates them.
22
- 4. **Cheap to connect.** Connections are a plain list of handles. Friction on
23
- connecting cards produces sparse graphs, and a sparse graph is useless.
24
-
25
- ## Folder layout
26
-
27
- ```
28
- constellation/
29
- plan.md ← the project plan (handle PLAN-PROJECT)
30
- api/
31
- API-TICKETS.md
32
- datatype/
33
- DATATYPE-TICKET.md
34
- db/
35
- DB-TICKETS.md
36
- doc/ file/ test/ external/ event/ component/
37
- page/ job/ flow/ state/ diagram/ agent/ role/ plan/
38
- ```
39
-
40
- - The plan root is a folder named `constellation/`, normally at the repo root. Tooling
41
- finds it by walking up from the working directory (like `.git`).
42
- - Each card lives in the folder matching its type (see table below). Folder placement is
43
- a **convention**: the handle prefix is authoritative for type; a card in the wrong
44
- folder lints as a warning, not an error.
45
- - `plan.md` at the plan root is the one special file: it is the card `PLAN-PROJECT`
46
- (type PLAN). Additional PLAN cards (e.g. `PLAN-FRONTEND`) live in `plan/`.
47
-
48
- ## Files and handles
49
-
50
- **The filename is the handle.** `api/API-TICKETS.md` defines the card `API-TICKETS`.
51
- There is no `handle:` or `type:` field in frontmatter — the path already says it, and one
52
- source of truth means they can never disagree.
53
-
54
- Handle grammar:
55
-
56
- ```
57
- ^[A-Z][A-Z0-9]*-[A-Z0-9][A-Z0-9-]*$ (3–135 characters)
58
- ```
59
-
60
- Uppercase letters, digits, and dashes. The prefix (everything before the first dash)
61
- determines the type and MUST be one of the 17 canonical prefixes. v1 alias prefixes
62
- (`TYPE-`, `COMP-`, `RULE-`) are not valid in v2.
63
-
64
- | Type | Prefix | Folder | What it is |
65
- |-----------|--------------|--------------|---------------------------------------------|
66
- | API | `API-` | `api/` | HTTP/RPC endpoints |
67
- | DB | `DB-` | `db/` | Database tables / collections |
68
- | DATATYPE | `DATATYPE-` | `datatype/` | Data type schemas (interfaces, Zod, etc.) |
69
- | ROLE | `ROLE-` | `role/` | User roles / permission groups |
70
- | DOC | `DOC-` | `doc/` | Documentation cards |
71
- | FILE | `FILE-` | `file/` | Source file references |
72
- | TEST | `TEST-` | `test/` | Test specs |
73
- | EXTERNAL | `EXTERNAL-` | `external/` | External services / integrations |
74
- | EVENT | `EVENT-` | `event/` | Domain events / signals |
75
- | COMPONENT | `COMPONENT-` | `component/` | Reusable UI components |
76
- | PAGE | `PAGE-` | `page/` | Frontend routes / screens |
77
- | JOB | `JOB-` | `job/` | Background / scheduled / queued work |
78
- | FLOW | `FLOW-` | `flow/` | Multi-step sequenced processes |
79
- | STATE | `STATE-` | `state/` | State machines |
80
- | DIAGRAM | `DIAGRAM-` | `diagram/` | Architecture diagrams |
81
- | AGENT | `AGENT-` | `agent/` | AI agent instructions / policies |
82
- | PLAN | `PLAN-` | `plan/` | Plan documents (`plan.md` = `PLAN-PROJECT`) |
83
-
84
- ## Card anatomy
85
-
86
- ```markdown
87
- ---
88
- name: List & create tickets
89
- status: built
90
- path: /api/v1/tickets
91
- methods:
92
- GET:
93
- query_params:
94
- - { name: status, type: string }
95
- response_schema: DATATYPE-TICKET
96
- POST:
97
- request_schema: DATATYPE-CREATE-TICKET-INPUT
98
- response_schema: DATATYPE-TICKET
99
- connections:
100
- - DB-TICKETS
101
- ---
102
-
103
- # Tickets API
104
-
105
- Returns tickets for the active inbox. POST validates the requester exists
106
- before inserting — see [[FLOW-CREATE-TICKET]] for the full sequence.
107
- ```
108
-
109
- ### Frontmatter
110
-
111
- YAML frontmatter is optional. Four keys are **reserved** (defined in
112
- `schemas/card.json`); every other key is a type-specific field (defined in
113
- `schemas/<type>.json`):
114
-
115
- | Key | Type | Meaning |
116
- |---------------|----------|--------------------------------------------------------------|
117
- | `name` | string | Display name (the handle is the identity; this is the label) |
118
- | `kind` | string | Subtype discriminator, lowercase slug (`sql-table`, `e2e`, `decision`) |
119
- | `status` | enum | Lifecycle: `planned` \| `building` \| `built` \| `verified` |
120
- | `connections` | string[] | Plain list of handles this card is connected to |
121
-
122
- Beyond the reserved keys, `schemas/card.json` also defines a few **cross-type metadata
123
- fields** — valid on *any* card and managed by tooling rather than hand-authored:
124
-
125
- | Key | Type | Meaning |
126
- |----------------|----------|------------------------------------------------------------------------|
127
- | `code_refs` | string[] | Code the card is bound to (`path` or `path:symbol`), for drift detection and code attach. The *primary* binding stays a connected `FILE` card's `path:`; `code_refs` adds precision where it earns its keep. |
128
- | `verified_sha` | string | Git sha the card was last verified against — the drift baseline (see *Change tracking* below). |
129
- | `verified_at` | string | ISO-8601 time the card was last verified. |
130
- | `notes` | object[] | Append-only typed memory: `{ kind, text, sha? }`, `kind ∈ decision \| gotcha \| state \| deviation \| verified`. Ordered newest-last (position is recency); no timestamps. |
131
-
132
- Type-specific fields sit at the top level of frontmatter (not nested under a `data` key).
133
- Schemas are permissive: almost nothing is required, known fields are typed, unknown
134
- fields are allowed (lint warns so typos get caught).
135
-
136
- ### Body
137
-
138
- The body is markdown — the card's narrative. Two constructs are graph-aware:
139
-
140
- - **Wiki-links**: `[[API-TICKETS]]` connects this card to `API-TICKETS`. Use them freely
141
- in prose; they are the cheapest way to wire the graph.
142
- - **Mermaid blocks**: inside ` ```mermaid ` fences, any node identifier shaped like a
143
- handle counts as a connection (see Diagrams below).
144
-
145
- ## Graph rules
146
-
147
- The indexer derives the connection set from four sources, in all cards:
148
-
149
- 1. The `connections:` list in frontmatter.
150
- 2. Handle-shaped string values anywhere else in frontmatter (so
151
- `response_schema: DATATYPE-TICKET` connects automatically — no need to repeat it in
152
- `connections`).
153
- 3. `[[HANDLE]]` wiki-links in the body.
154
- 4. Handle-shaped identifiers inside ` ```mermaid ` blocks in the body.
155
-
156
- Connections are **undirected** and deduped by pair: declare a connection on whichever
157
- card you are editing; both cards see it when queried. Self-references are ignored. The reverse
158
- view ("what points at X?") is the indexer's job — it is never written into files.
159
-
160
- ## Diagrams and flows
161
-
162
- Three tiers, cheapest first:
163
-
164
- 1. **Derived subgraphs** (default for "what does this area look like"): the viewer/MCP
165
- render any card's neighborhood from the real connection graph on demand. Never stored,
166
- never stale.
167
- 2. **Authored Mermaid** (default for conceptual diagrams): a DIAGRAM card whose body is a
168
- ` ```mermaid ` block. Use handles as Mermaid node IDs so the diagram joins the graph.
169
- Sequence diagrams (`sequenceDiagram`) and state diagrams (`stateDiagram-v2`) work the
170
- same way in FLOW and STATE cards.
171
- 3. **Pinned layouts** (escape hatch for curated diagrams): structured `nodes` / `edges` /
172
- `phases` in DIAGRAM frontmatter with explicit positions — see `schemas/diagram.json`. Use
173
- only when layout carries meaning; positions make noisy diffs.
174
-
175
- **FLOW cards are linear.** Steps are a numbered markdown list in the body, with nested
176
- list items for error/edge cases. If a flow needs real branching, it is either a Mermaid
177
- flowchart or actually a STATE card.
178
-
179
- ```markdown
180
- 1. [[PAGE-INBOX]] submits the new ticket form
181
- 2. [[API-CREATE-TICKET]] validates the requester
182
- - if the requester is unknown → 422, form shows inline error
183
- 3. Ticket row inserted into [[DB-TICKETS]]
184
- 4. [[EVENT-TICKET-CREATED]] fires → [[JOB-AUTO-ASSIGN]]
185
- ```
186
-
187
- ## Lint policy
188
-
189
- **Errors** (break the graph; non-zero exit, CI should block):
190
-
191
- | Code | Rule |
192
- |------|------|
193
- | E001 | Filename is not a valid handle |
194
- | E002 | Handle prefix is not one of the 17 canonical prefixes |
195
- | E003 | Duplicate handle (two files resolve to the same handle) |
196
- | E004 | `connections` entry is not a handle-shaped string |
197
- | E005 | `connections` or frontmatter-field target resolves to no card |
198
- | E006 | Frontmatter is not valid YAML |
199
-
200
- **Warnings** (style/quality; reported, exit 0):
201
-
202
- | Code | Rule |
203
- |------|------|
204
- | W001 | Card is not in the folder matching its type |
205
- | W002 | Frontmatter violates the type's JSON Schema |
206
- | W003 | Unknown frontmatter field (not a reserved/cross-type key from `card.json`, not in the type schema) |
207
- | W004 | Body `[[link]]` or Mermaid reference resolves to no card |
208
-
209
- The split between E005 and W004 is deliberate: structured references (frontmatter) are
210
- contracts and must resolve; prose references may legitimately point at cards that are
211
- planned but not yet written.
212
-
213
- ## Change tracking and sync
214
-
215
- - **What changed**: `git diff <ref> -- constellation/` . Plan changes ride branches and
216
- PRs like any other change; reviewing a plan PR is the human approval gate before an
217
- AI syncs code to it.
218
- - **Sync marker**: a reconciling agent records the last plan commit it synced code against in
219
- `constellation/.sync.json` (plan-global, written by `set_sync_point`). "Drifted" = anything
220
- in `git diff <synced>..HEAD -- constellation/` (the plan moved) or code commits since the
221
- marker (the code moved).
222
- - **Lifecycle**: `status` tracks where a card is in its life (`planned` → `building` →
223
- `built` → `verified`), orthogonal to git history. An agent that verifies a card
224
- against the actual code sets `status: verified`.
225
- - **Verification provenance vs. change tracking.** "What changed" is never stamped into a card
226
- — that's git's job: no dirty flags, no changelogs, no per-card *change* marks. The one
227
- recorded per-card baseline that *is* kept is `verified_sha`/`verified_at`: when a card is
228
- verified against code, `set_verified` stamps the sha it was checked at. That is the basis of
229
- a *claim*, not a change flag — and the drift *verdict* ("has the bound code moved since?") is
230
- always recomputed live by `stale_report`/`check_sync`, never stored. This is what lets a
231
- `built`/`verified` claim be re-verified later instead of taken on faith.
232
-
233
- ## Connected repos (multi-repo)
234
-
235
- A project that spans several repos can declare its siblings on `PLAN-PROJECT`. This is the
236
- one cross-repo concept in the format, and it is deliberately minimal: each repo's
237
- `constellation/` is identical to a standalone one, references only its own cards, and lints
238
- clean on its own — connections never cross repos.
239
-
240
- `plan.md` frontmatter may carry a `connected_repos` list (validated by `schemas/plan.json`):
241
-
242
- ```yaml
243
- connected_repos:
244
- - name: pyramid-server # lowercase id; the `repo` selector in MCP tools
245
- path: ../pyramid-server # relative to this repo's root (or absolute)
246
- description: Back-end API for Pyramid, written in Go.
247
- ```
248
-
249
- These are **repo-level links only** — never card-to-card connections, never a merged graph.
250
- The path is local topology (it may differ per machine), so it is **never validated by lint**;
251
- tooling reports reachability only when something actually uses it. The MCP server's `repo`
252
- selector resolves a name (or path) to that sibling's plan, so one agent can read or write
253
- across repos; the per-repo plan remains the unit, and **plan resolution still never crosses a
254
- repo boundary** on its own — a sibling is reached only when explicitly named.
255
-
256
- ## What is deliberately not in the format
257
-
258
- - No IDs other than handles. No UUIDs/ULIDs.
259
- - No cross-repo card references. Cards connect only within their own plan; sibling repos are
260
- linked at the project level via `connected_repos` (above), not by handle.
261
- - No connection kinds, directions, or metadata. If a relationship needs explanation,
262
- explain it in prose in the body — structure is for navigation, prose is for meaning.
263
- - No revision/branch/diff machinery. Git does that.
264
- - No required fields beyond the filename (single exception: `FILE` cards require `path`,
265
- because a file reference without a path refers to nothing).
package/docs/002-mcp.md DELETED
@@ -1,186 +0,0 @@
1
- # Constellation MCP (v2)
2
-
3
- The MCP server gives AI agents graph queries, hydrated retrieval, validated writes,
4
- and git-powered change tracking over a plan folder. It is a thin layer over
5
- `src/core/`: every tool call reloads the index from disk (tens of milliseconds at
6
- realistic plan sizes), so it is always correct while files are being edited in
7
- parallel — no watcher, no cache invalidation.
8
-
9
- Entry point: `constellation mcp` (stdio). Bootstrap is folder discovery: the server
10
- walks up from the working directory to find `constellation/`, **bounded by the repo
11
- root** (the first ancestor with `.git`) — it never crosses into another repo's plan,
12
- so a repo with no plan returns `NO_PLAN_FOUND` rather than silently adopting a
13
- sibling's. No accounts, no tokens, no settings handshake. When no plan exists yet,
14
- `init_plan` scaffolds `constellation/` + starter `plan.md` (same shared scaffold the
15
- CLI `constellation init` uses); every other tool works immediately after — no restart.
16
-
17
- Every tool also accepts an optional **`repo`** selector to act on a *sibling* repo declared
18
- in `connected_repos` (see [Connected repos](#connected-repos-multi-repo) below). Without it,
19
- everything operates on the repo found by walk-up, exactly as before — the boundary above is
20
- never crossed implicitly, only when a sibling is named.
21
-
22
- ## Vocabulary
23
-
24
- **Card** (a file in the plan), **connection** (an undirected link between two cards).
25
- Tool responses use `connected_cards`, never `connected_nodes`.
26
-
27
- ## Hydrated retrieval (core requirement)
28
-
29
- Any read tool can return connected cards **with their full data** in one call. Three
30
- levels, chosen by the caller because the cost is context tokens, not compute:
31
-
32
- - `none` — the card(s) only
33
- - `summary` — connected cards as `{ handle, type, kind, name, status }`
34
- - `full` — connected cards with complete `frontmatter` and `body`
35
-
36
- The acceptance test: one `get_card` call returns an API card plus the complete
37
- content of every card connected to it (its datatypes, table, tests, docs).
38
-
39
- ## Tools
40
-
41
- ### Read
42
-
43
- | Tool | Input | Returns |
44
- |---|---|---|
45
- | `get_card` | `handle`, `connected?` (default `summary`), `code?` (`none`/`paths`/`direct`), `notes_kind?`, `notes_limit?` | `{ card, connected_cards, code? }` |
46
- | `list_cards` | `types?`, `kind?`, `status?`, `connected?`, `limit?` | `{ cards: summary[], total }` (`connected:false` → orphans only) |
47
- | `search` | `q`, `types?`, `limit?` (20), `connected?` (default `none`) | `{ matches: [{ card, score, excerpt, connected_cards? }] }` |
48
- | `traverse` | `start` (handle or array), `depth?` (2, max 5), `types?`, `detail?` (`summary`/`full`) | `{ cards: [{ …, distance }], connections }` |
49
- | `assemble` | `handles?` (else the delta since `base?`), `depth?` (1), `code?` (`none`/`paths`/`direct`) | `{ base, seeds, reached_handles, suggested_order, units: [{ handles, files, cards }], fanout }` |
50
- | `describe_type` | `type?` | No arg → catalog of all 17 types (`{ type, prefix, folder, purpose }`); a type → `{ schema, reference, reserved, prefix, folder }` (frontmatter JSON Schema + golden example). Plan-independent — works with no plan loaded. |
51
-
52
- `search` scoring: handle match ≫ name match > kind/type match > body occurrences;
53
- excerpt is the first matching body line. Seeding `traverse` with multiple handles
54
- (e.g. the output of `diff_plan`) is the impact-analysis pattern.
55
-
56
- ### Write
57
-
58
- | Tool | Input | Notes |
59
- |---|---|---|
60
- | `create_card` | `handle`, `name?`, `kind?`, `status?`, `connections?`, `fields?`, `body?`, `validate?` | Writes `<folder>/<HANDLE>.md`; `fields` = type-specific frontmatter. `validate:false` skips lint (bulk import) |
61
- | `create_cards` | `cards: [...]` (1–500) | Bulk create: validates all up front, writes all, lints ONCE → intra-batch references resolve. `{ created, failed, cards, issues }` |
62
- | `update_card` | `handle`, `patch?`, `body?` | See merge semantics below |
63
- | `append_note` | `handle`, `kind` (`decision`/`gotcha`/`state`/`deviation`/`verified`), `text`, `sha?` | Appends one typed note to `notes` — append-only, no full-body rewrite |
64
- | `edit_section` | `handle`, `section`, `text` | Replaces one `##` section in the body, the rest byte-for-byte; errors if no such heading |
65
- | `set_verified` | `handle`, `sha?` (default HEAD), `note?` | Stamps `verified_sha`+`verified_at`, sets `status: verified`, optional verified note |
66
- | `delete_card` | `handle` | Returns `referenced_by` so the caller can clean up |
67
- | `add_connection` | `from`, `to` | Appends to `from`'s connections (no-op if already connected from any source) |
68
- | `add_connections` | `connections: [{from,to}]` (1–1000) | Bulk connect, idempotent/undirected, one lint pass. `{ added, failed, issues }` |
69
- | `remove_connection` | `a`, `b` | Removes from either card's list; reports if the connection survives via other sources (frontmatter field, body link, mermaid) |
70
-
71
- Every write reloads the index, lints, and returns the issues touching the written
72
- file — an agent finds out immediately if it created a dangling reference. **A card
73
- is created even when issues are returned** — `issues` are the current lint state,
74
- not a failure. For migrations, prefer `create_cards` + `add_connections` (batched,
75
- one lint pass, no transient dangling-reference noise) or `create_card validate:false`
76
- followed by a single `check_integrity`.
77
-
78
- **Merge semantics for `update_card`:** `patch.name/kind/status` set (or delete with
79
- `null`); `patch.connections` replaces the list wholesale (use add/remove_connection
80
- for incremental edits); `patch.fields` deep-merges into type-specific frontmatter —
81
- objects merge recursively, arrays replace, `null` deletes a key. `body` replaces the
82
- whole body.
83
-
84
- **Formatting preservation:** a body-only update never touches frontmatter bytes.
85
- A frontmatter update re-serializes **only the top-level keys whose values
86
- changed** — unchanged keys keep their original text byte-for-byte (flow-style
87
- maps, comments, and all), so a status flip is a one-line diff. Key order is
88
- preserved; new keys append. Only a changed key's value normalizes to canonical
89
- YAML style.
90
-
91
- ### Git
92
-
93
- | Tool | Input | Returns |
94
- |---|---|---|
95
- | `diff_plan` | `base?`, `head?` | `{ base, base_source, head, changes: [{ handle, file, change, changed_keys?, body_changed? }] }` |
96
- | `plan_log` | `handle`, `limit?` (20) | commits touching that card |
97
- | `set_sync_point` | `sha?` (default `HEAD`) | writes `constellation/.sync.json`; `warning` if the plan is uncommitted |
98
- | `stale_report` | `base?` | Cards whose bound code changed since their `verified_sha` (else `base`, else marker): `{ checked, stale_count, stale: [{ handle, name, status, baseline, baseline_source, changed_files, missing_files }], no_baseline }` |
99
- | `check_sync` | `base?` | Definition-of-done verdict: plan-global `state` + drift counts + integrity + `status_rollup` + per-card `stale_cards`. Advisory (cannot block) |
100
- | `check_integrity` | — | lint result + `orphans` (zero-connection cards) |
101
-
102
- `diff_plan` base resolution: explicit argument → sync marker (`.sync.json`) →
103
- `HEAD` (i.e. uncommitted plan changes). `head` defaults to the working tree.
104
- `change` is `added` / `modified` / `removed` / `renamed`; for modified cards the
105
- old and new versions are parsed and compared, yielding `changed_keys` (frontmatter)
106
- and `body_changed`.
107
-
108
- The sync workflow ("sync the plan to the code"): the plan is the source of truth, so
109
- a code-sync agent brings code up to a changed plan — it calls `diff_plan` (base =
110
- marker), traverses the changed handles for blast radius, updates code, then
111
- `set_sync_point` to move the marker. For a large diff it acts as an **orchestrator**:
112
- it partitions the blast radius into non-overlapping neighborhoods and fans out a
113
- sub-agent per neighborhood (split on file boundaries so no two agents touch the same
114
- file), which keeps the orchestrator's context clean and on the macro view. It always
115
- verifies the sub-agents' work — against the cards, and via build/tests — after they
116
- finish, and only then sets the sync point (once). `.sync.json` is versioned, rides
117
- branches, and the indexer ignores dotfiles so it is never treated as a card.
118
-
119
- ### Code binding, drift & assembly (the durability loop)
120
-
121
- A card binds to code two ways: a connected `FILE` card's `path:` (the primary binding) or the
122
- card's own `code_refs` (`path` or `path:symbol` — optional precision). That binding powers three
123
- things, all sharing one resolver (`src/core/code.ts`):
124
-
125
- - **Attach** — `get_card(handle, code: "paths" | "direct")`. `paths` returns the resolved bound
126
- file paths (cheap; the agent Reads what it wants); `direct` attaches their contents under
127
- per-file (64 KB) and total (256 KB) caps, skipping binaries, lockfiles, and generated output,
128
- truncation noted. Same-repo only — cards never bind across repos, so use the `repo` selector to
129
- attach a sibling's code from the sibling's card.
130
- - **Detect** — `stale_report` / `check_sync` flag every `built`/`verified` card whose bound code
131
- changed since its `verified_sha` baseline (reverse drift), plus bound files that have vanished.
132
- The verdict is computed live from git; nothing is stored.
133
- - **Assemble** — `assemble` turns a delta (or handle set) into a work package: the seed cards +
134
- their neighborhood (full) + bound code + a heuristic build order + **file-disjoint units**, so a
135
- large change can be fanned out one sub-agent per unit with no two touching the same file.
136
-
137
- Cheap writes keep the memory honest: `append_note` (append-only typed notes) and `edit_section`
138
- (replace one `##` section) are byte-preserving, so recording a correction the moment you learn it
139
- costs far less than rewriting a card — removing the friction that otherwise causes drift.
140
-
141
- ### Viewer
142
-
143
- | Tool | Input | Returns |
144
- |---|---|---|
145
- | `start_viewer` | `port?` (default 4747; `0` = any free port), `readonly?`, `open?` | `{ url, port, plan_root, editable }`; idempotent — if already running, `{ already_running, url, plan_root }` |
146
- | `stop_viewer` | — | `{ stopped, was }`, or `{ running: false }` if it wasn't running |
147
-
148
- `start_viewer` renders the plan as a browsable, editable site and scans forward from the
149
- requested port for a free one, so always read the actual `port` from the response and post
150
- the `url` back to the user. The viewer runs until `stop_viewer` or until the MCP process exits.
151
-
152
- ### Connected repos (multi-repo)
153
-
154
- A project can declare sibling repos on `PLAN-PROJECT` `connected_repos` (name + path +
155
- description; see `docs/001-file-format.md`). These are repo-level links, not card
156
- connections — each repo's plan stays self-contained.
157
-
158
- Every read and write tool takes an optional **`repo`** selector: omit it for the current plan
159
- (default, unchanged), or pass a `connected_repos` name (or a path) to read or write **that**
160
- sibling's plan instead. An unknown `repo` is refused (`UNKNOWN_REPO`, listing the declared
161
- names) rather than landing in the wrong place. Three tools manage the links:
162
-
163
- | Tool | Input | Returns |
164
- |---|---|---|
165
- | `list_connected_repos` | `repo?` | `{ connected_repos: [{ name, path, description, reachable }] }` |
166
- | `add_connected_repo` | `name`, `path`, `description?`, `reciprocate?`, `reverse_description?`, `repo?` | Upserts the link on the selected repo's `PLAN-PROJECT`; `reciprocate` also writes the reverse link into the target repo |
167
- | `remove_connected_repo` | `name`, `repo?` | Removes the link from the selected repo's `PLAN-PROJECT` |
168
-
169
- Paths are local topology and are **never** linted; `reachable` is computed at call time.
170
- Cross-repo investigation has two modes: read a sibling's *plan* in-process with `repo:`, or —
171
- for the sibling's real code, or when its plan can't answer — spawn a sub-agent scoped to that
172
- repo's path. For one change spanning repos, the orchestrator writes the per-repo card updates
173
- with `repo:` set on every write, then fans out a per-repo implementer sub-agent (each in plain
174
- single-repo mode) and sets each repo's sync point.
175
-
176
- ## What v1 tools deliberately died
177
-
178
- - `expand_handles` — handles ARE the identifiers; nothing to resolve.
179
- - `init_project` / `link_project` / `check_health` — bootstrap is finding a folder.
180
- (`init_plan` exists for MCP-only environments, but it just creates the folder —
181
- no server, no settings file, no linking.)
182
- - `read_plan` / `update_plan` — `get_card("PLAN-PROJECT")` / `update_card`.
183
-
184
- (Bulk variants were *not* dropped — v1 punted on them, but `create_cards` /
185
- `add_connections` now exist: batching lints once, so intra-batch references resolve
186
- without transient dangling-reference noise. See the Write table above.)
@@ -1,138 +0,0 @@
1
- # 003 — Constellation MCP Upgrade Plan
2
-
3
- _Status: **implemented** (branch `feat/mcp-upgrades-003`). Authored 2026-06-19 from two agents using Constellation as cross-session memory during a real build (a Claude building `pyramid-server`'s GitHub integration + a Claude building `pyramid-web`). Companion to [002-mcp.md](./002-mcp.md)._
4
-
5
- > **Implementation status (2026-06-19).** Phases 0–6 all landed, with tests:
6
- > - **0** framing → MCP `instructions` + `skill/SKILL.md` + `skill/methodology.md` (all three copies).
7
- > - **1** cheap writes → `append_note`, `edit_section` (byte-preserving).
8
- > - **2** binding + baseline → `set_verified`; cross-type `code_refs` / `verified_sha` / `verified_at` / `notes` live in `schemas/card.json`, blessed on all 17 types via `validate.ts`.
9
- > - **3** detect → `stale_report` (per-card reverse drift vs `verified_sha`).
10
- > - **4** attach → `get_card(code: "paths" | "direct")` with size caps + skips (`src/core/code.ts`).
11
- > - **5** assemble → `assemble` (work package + file-disjoint fan-out units).
12
- > - **6** enforcement → `check_sync` (exposes the existing `computeSyncStatus` over MCP + per-card drift; advisory, can't block).
13
- >
14
- > **Deferred / decided:** the optional *memory-structure* extras — a dedicated `DECISION` card type and a structured partial-status model — are **not** built; typed `notes` (`kind: decision | state | …`) cover most of that need for now. Code *attach* is intentionally **same-repo** (cards never bind across repos — the invariant holds; reach a sibling's code via the `repo` selector). The "no per-card stamping" format rule was reconciled, not broken: `verified_sha` is verification *provenance* (a recorded claim baseline), while the drift *verdict* is still computed live and never stored.
15
-
16
- ## Why this plan exists
17
-
18
- Constellation is used as **durable, cross-session, cross-agent memory** for AI coding agents. Every session an agent pays a "discovery tax" — building a mental model of the code before it can act. Without a place to bank that understanding it evaporates at session end and the next agent re-pays it in full. Constellation's value is that the understanding **compounds** instead.
19
-
20
- Two failure modes erode that value; this plan attacks both:
21
-
22
- 1. **Drift** — a card's claim (`status: built`, a DDL block, a "not built yet" note) silently diverges from the code. *A card you can't trust is worse than no card.*
23
- 2. **Friction** — updating a card is expensive (today it's a full-body replace), so agents skip it — which *causes* drift.
24
-
25
- ### Design principles (apply to every change below)
26
-
27
- - **`built` is a claim that outlives its author.** The agent reading a card next isn't the one who verified it and can't see the basis; code drifts after marking; even a careful agent can miss a path. So claims must be **re-verifiable**, not taken on faith forever. This is *durability, not distrust* — the same reason you keep tests even though you trust the author.
28
- - **Card what code can't say** — intent, decisions, current state, gotchas, cross-cutting rules. **Don't duplicate** DDL / signatures / code that lives in the repo; link to it. Copies drift; the repo is the source of truth.
29
- - **Make the honest path the cheap path.** Most drift is just skipped updates. Lower the cost of a small correction and cards stay true.
30
- - **Purpose belongs in the intro.** The MCP `instructions` are loaded every session; stating what Constellation is *for* and how to treat it changes agent defaults more than any tool.
31
-
32
- ---
33
-
34
- ## The two headline capabilities
35
-
36
- Everything else ladders up to two things agents actually want the MCP to *do*.
37
-
38
- ### A. "Hand me the delta" — what changed since I last looked
39
-
40
- Given a sync marker (or explicit handles), report what changed and hand back a ready-to-work bundle. Two directions:
41
-
42
- - **Plan-side** — which cards changed. ✅ **Already exists** — `diff_plan` reports per-card changes since the sync marker / HEAD.
43
- - **Code-side** — which cards are bound to code that changed *without the card moving* (reverse drift). ❌ **Missing — the core new capability.**
44
- - **Assemble** — turn that delta into a work package: changed cards + their connected cards (full) + the bound code + a suggested dependency order, optionally split into file-disjoint units for fan-out.
45
-
46
- ### B. "Hand me the code behind a card"
47
-
48
- When a card connects to FILE cards (which carry a `path:`), optionally attach the live file — so an agent starts from *intent + current reality* in one call instead of a card describing code it then has to hunt down.
49
-
50
- ```
51
- get_card(handle, connected: "full", code: "none" | "paths" | "direct")
52
- ```
53
- - **`paths`** — return resolved file paths of *directly*-connected FILE cards. Cheap; the agent Reads what it wants. Default for interactive agents.
54
- - **`direct`** — attach the *contents* of directly-connected FILE cards (capped). For background / fan-out coders that shouldn't need a second round-trip.
55
- - Resolves **cross-repo** via `connected_repos` — a `pyramid-web` card can pull the real `pyramid-server` file it's bound to.
56
-
57
- These two share machinery: **Assemble (A) reuses B's path-resolution** to attach each coder's files to its work package.
58
-
59
- ---
60
-
61
- ## Supporting infrastructure (what A and B need underneath)
62
-
63
- ### Binding — how a card points at code _(foundational; A and B both need it)_
64
- Today the only binding is a FILE card's `path:`. Keep that as the primary binding; add an optional `code_refs` (`path` or `path:symbol`) on any card for precision. **Recommendation:** FILE-`path:` is the default; `code_refs` only where drift precision earns its keep, so you don't tax every card.
65
-
66
- ### `verified_sha` / `verified_at` _(foundational; A's code-side drift needs a baseline)_
67
- When a card is marked `built`/`verified`, stamp the git sha + timestamp it was verified against. Code-side drift then = "bound files changed since `verified_sha`." Without a baseline there's nothing to diff against.
68
-
69
- ### Cheap writes _(kills the #1 drift cause)_
70
- - `append_note(handle, kind, text)` — append-only, **no full-body rewrite**. `kind ∈ {decision, gotcha, state, deviation, verified}`. _(Audit `plan_log` first — it may already cover part of this; if so, surface it in the intro so agents reach for it.)_
71
- - Section-level edit — replace a single `##` section.
72
- - **Compaction / filtering** so append-only notes don't bloat a card — retrieval returns latest-N or filters by kind.
73
-
74
- ### Memory structure _(so the gold is queryable, not buried in prose)_
75
- - First-class typed notes (state / gotcha / decision / deviation) instead of free-text provenance, so a tool can answer *"show every known limitation in area X."*
76
- - **Partial status** for half-built cards: `{ built: [...], pending: [...] }` or per-section — instead of jamming "inbound done, outbound not" into one enum + prose.
77
- - Optional `DECISION` card type (or decision log): rationale + rejected alternatives — the highest-value "don't re-litigate" memory.
78
-
79
- ---
80
-
81
- ## Phased rollout (by leverage-per-effort)
82
-
83
- | Phase | What | Why here | Effort |
84
- |---|---|---|---|
85
- | **0** | **Reframe the MCP `instructions`** — purpose (memory/compounding), discipline (update cards as part of *done*), content rule (intent yes / code-copies no), durability framing, "a card you can't trust is worse than none." | Loaded every session; changes defaults; **zero code**. | XS |
86
- | **1** | **Cheap writes** — `append_note`, section edit, note compaction. | Removes the friction that causes drift. | S |
87
- | **2** | **Binding + `verified_sha`** — FILE `path:` (+ optional `code_refs`); stamp sha/time on verify. | Foundational for 3–5. | S–M |
88
- | **3** | **Detect** — code-side drift report (`stale_report`) atop the existing `diff_plan`. | Makes `built` re-verifiable. | M |
89
- | **4** | **Attach** — `get_card(..., code: "paths"\|"direct")` with guardrails. | Capability B; high value every session. | M |
90
- | **5** | **Assemble** — `assemble(delta\|handles)` → work package + file-disjoint fan-out units. | Capability A; bridges to multi-agent orchestration. | M–L |
91
- | **6** | **Enforcement** — `check_sync` / definition-of-done hook: code changed without bound cards re-verified → surface/block. | Takes "remember to sync" off the human. | M |
92
-
93
- **If you only do three:** Phase 0 (framing), Phase 1 (cheap writes), Phase 4 `paths` mode. They change every future session for modest code.
94
-
95
- **Sequencing:** 0 → 1 → 2 → (3 ‖ 4) → 5 → 6, with the memory-structure track folded into 1 and 3.
96
-
97
- ---
98
-
99
- ## Guardrails for Attach (B) — the craft is here
100
-
101
- Without these, attaching files backfires (token blow-up buries the one file you wanted):
102
-
103
- - **Opt-in + scoped** — `code: "direct"` attaches only *directly*-connected FILE cards, never the whole neighborhood.
104
- - **Size caps** — per-file cap with truncation noted; total budget reported.
105
- - **Missing / moved file → drift warning, not an error** — a stale `path:` is a useful signal (feeds Detect).
106
- - **Skip** binaries, lockfiles, generated output.
107
- - **`paths` is the cheap 80%** — return resolved paths, let the agent Read selectively. Default for interactive use; `direct` for background coders.
108
-
109
- ---
110
-
111
- ## Proposed tool surface (sketch)
112
-
113
- ```
114
- # existing
115
- diff_plan(base?) # plan-side delta (per-card changes) ✅ have
116
-
117
- # new
118
- append_note(handle, kind, text) # append-only; no full-body rewrite P1
119
- set_verified(handle, sha?, note?) # stamp verified_sha + verified_at P2
120
- stale_report(base?) # cards whose bound code changed since verify P3
121
- get_card(handle, connected, code) # code: "none" | "paths" | "direct" (+ caps) P4
122
- assemble(delta | handles, code?) # work package: cards + connected + code + order P5
123
- check_sync() # code touched without bound cards re-verified P6
124
- ```
125
-
126
- ---
127
-
128
- ## The one decision everything hinges on
129
-
130
- **Code-binding granularity.** FILE-`path:` only is simplest but coarse (file-level drift). `path:symbol` gives precise drift detection at higher authoring cost. **Recommendation:** FILE-`path:` as the default binding for most cards; `code_refs` with symbols only where precision earns its keep. Detect's precision, Attach's accuracy, and Assemble's bundles all ride on this choice.
131
-
132
- ---
133
-
134
- ## Provenance
135
-
136
- Synthesized 2026-06-19 from two Claude agents using Constellation as working memory across the `pyramid-server` + `pyramid-web` build:
137
- - **Intro-purpose framing, write-friction, memory-structure, phasing** — pyramid-server Claude.
138
- - **Durability-not-suspicion framing for verification, the Detect/Assemble split, attach guardrails + `paths`-vs-`direct` modes** — pyramid-web Claude.
@@ -1 +0,0 @@
1
- import"./chunk-NNHCCRGN-DlpIbxXb.js";import{x as e}from"./mermaid-parser.core-BdEYBvaj.js";export{e as createArchitectureServices};
@@ -1 +0,0 @@
1
- import{at as e,ot as t}from"./chunk-CSCIHK7Q-C9h7yfl1.js";var n=(n,r)=>t.lang.round(e.parse(n)[r]);export{n as t};
@@ -1 +0,0 @@
1
- import{h as e}from"./src-BPb55SrS.js";var t=class{constructor(e){this.init=e,this.records=this.init()}static{e(this,`ImperativeState`)}reset(){this.records=this.init()}};export{t};
@@ -1 +0,0 @@
1
- import{h as e,p as t}from"./src-BPb55SrS.js";import{x as n}from"./chunk-CSCIHK7Q-C9h7yfl1.js";var r=e(e=>{let{securityLevel:r}=n(),i=t(`body`);return r===`sandbox`&&(i=t((t(`#i${e}`).node()?.contentDocument??document).body)),i.select(`#${e}`)},`selectSvgElement`);export{r as t};
@@ -1 +0,0 @@
1
- import{h as e}from"./src-BPb55SrS.js";import"./chunk-CSCIHK7Q-C9h7yfl1.js";import"./chunk-5ZQYHXKU-wzW5x_7z.js";import"./chunk-O5CBEL6O-SvZfZ-0j.js";import"./chunk-FMBD7UC4-BcSnkYc3.js";import"./chunk-BSJP7CBP-C30ZXEUD.js";import"./chunk-L5ZTLDWV-DGwFsVWy.js";import"./chunk-ND2GUHAM-PqmKwdzq.js";import"./chunk-55IACEB6-NdWURd2K.js";import"./chunk-2J33WTMH-CpuwKeX6.js";import"./chunk-NZK2D7GU-BAZbzxhl.js";import"./chunk-3OPIFGDE-BG_ijJhE.js";import"./chunk-KSCS5N6A-rxSD5-MD.js";import"./chunk-LZXEDZCA-BY3sTuvt.js";import{i as t,n,r,t as i}from"./chunk-727SXJPM-BxKeJXYf.js";var a={parser:n,get db(){return new i},renderer:r,styles:t,init:e(e=>{e.class||={},e.class.arrowMarkerAbsolute=e.arrowMarkerAbsolute},`init`)};export{a as diagram};
@@ -1 +0,0 @@
1
- import{h as e}from"./src-BPb55SrS.js";import"./chunk-CSCIHK7Q-C9h7yfl1.js";import"./chunk-5ZQYHXKU-wzW5x_7z.js";import"./chunk-O5CBEL6O-SvZfZ-0j.js";import"./chunk-FMBD7UC4-BcSnkYc3.js";import"./chunk-BSJP7CBP-C30ZXEUD.js";import"./chunk-L5ZTLDWV-DGwFsVWy.js";import"./chunk-ND2GUHAM-PqmKwdzq.js";import"./chunk-55IACEB6-NdWURd2K.js";import"./chunk-2J33WTMH-CpuwKeX6.js";import"./chunk-NZK2D7GU-BAZbzxhl.js";import"./chunk-3OPIFGDE-BG_ijJhE.js";import"./chunk-KSCS5N6A-rxSD5-MD.js";import"./chunk-LZXEDZCA-BY3sTuvt.js";import{i as t,n,r,t as i}from"./chunk-727SXJPM-BxKeJXYf.js";var a={parser:n,get db(){return new i},renderer:r,styles:t,init:e(e=>{e.class||={},e.class.arrowMarkerAbsolute=e.arrowMarkerAbsolute},`init`)};export{a as diagram};
@@ -1 +0,0 @@
1
- import"./chunk-NNHCCRGN-DlpIbxXb.js";import{y as e}from"./mermaid-parser.core-BdEYBvaj.js";export{e as createEventModelingServices};