pi-outpost 0.32.4 → 0.34.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 (188) hide show
  1. package/dist/contract/README.md +120 -1
  2. package/dist/contract/conformance/README.md +29 -5
  3. package/dist/contract/conformance/index.json +115 -0
  4. package/dist/contract/conformance/invalid/unknown-version.json +1 -1
  5. package/dist/contract/conformance/invalid/v3-timeline-comparison-without-reference.json +123 -0
  6. package/dist/contract/conformance/invalid/v3-timeline-contradictory-change.json +128 -0
  7. package/dist/contract/conformance/invalid/v3-timeline-dependency-cycle.json +124 -0
  8. package/dist/contract/conformance/invalid/v3-timeline-dependency-on-removed.json +125 -0
  9. package/dist/contract/conformance/invalid/v3-timeline-duplicate-dependency.json +125 -0
  10. package/dist/contract/conformance/invalid/v3-timeline-duplicate-identifier.json +120 -0
  11. package/dist/contract/conformance/invalid/v3-timeline-empty-task-endpoint.json +124 -0
  12. package/dist/contract/conformance/invalid/v3-timeline-impossible-date.json +101 -0
  13. package/dist/contract/conformance/invalid/v3-timeline-inverted-activity.json +120 -0
  14. package/dist/contract/conformance/invalid/v3-timeline-inverted-range.json +120 -0
  15. package/dist/contract/conformance/invalid/v3-timeline-milestone-outside-range.json +120 -0
  16. package/dist/contract/conformance/invalid/v3-timeline-period-outside-range.json +139 -0
  17. package/dist/contract/conformance/invalid/v3-timeline-presentation-property.json +121 -0
  18. package/dist/contract/conformance/invalid/v3-timeline-previous-outside-range.json +128 -0
  19. package/dist/contract/conformance/invalid/v3-timeline-previous-wrong-shape.json +128 -0
  20. package/dist/contract/conformance/invalid/v3-timeline-reference-outside-range.json +140 -0
  21. package/dist/contract/conformance/invalid/v3-timeline-self-dependency.json +124 -0
  22. package/dist/contract/conformance/invalid/v3-timeline-under-version-2.json +120 -0
  23. package/dist/contract/conformance/invalid/v3-timeline-unknown-dependency-type.json +121 -0
  24. package/dist/contract/conformance/invalid/v3-timeline-unresolved-dependency-endpoint.json +120 -0
  25. package/dist/contract/conformance/invalid/v3-timeline-unsupported-scale.json +120 -0
  26. package/dist/contract/conformance/invalid/v3-timeline-with-target.json +123 -0
  27. package/dist/contract/conformance/valid/v3-timeline-calendar.json +140 -0
  28. package/dist/contract/conformance/valid/v3-timeline-compared.json +142 -0
  29. package/dist/contract/conformance/valid/v3-timeline-empty-task-and-anonymous-separator.json +35 -0
  30. package/dist/contract/conformance/valid/v3-timeline-four-dependency-types.json +61 -0
  31. package/dist/contract/conformance/valid/v3-timeline-programme.json +44 -0
  32. package/dist/contract/conformance/valid/v3-timeline-quarter-scale.json +42 -0
  33. package/dist/contract/conformance/valid/v3-timeline-single-day-activity.json +27 -0
  34. package/dist/contract/conformance/valid/v3-timeline-unsatisfied-dependency.json +45 -0
  35. package/dist/contract/conformance/valid/v3-timeline-week-scale.json +35 -0
  36. package/dist/contract/conformance/version-1.lock.json +2 -2
  37. package/dist/contract/schemas/structured-exchange-3.json +1263 -0
  38. package/dist/contract/schemas/structured-exchange-profile-registry-2.json +94 -0
  39. package/dist/contract/structured-exchange-project-setup.md +36 -0
  40. package/dist/contract/validate-structured-exchange.mjs +1981 -174
  41. package/dist/pi-outpost-tools.mjs +4556 -1130
  42. package/dist/pi-outpost.mjs +5733 -1898
  43. package/dist/pi-outpost.sea.mjs +2 -2
  44. package/dist/sea-prep.blob +2 -2
  45. package/dist/skills/structured-exchange/SKILL.md +90 -378
  46. package/dist/skills/structured-exchange/references/enriched-contract.md +158 -0
  47. package/dist/skills/structured-exchange/references/figures.md +52 -0
  48. package/dist/skills/structured-exchange/references/graphs-and-tables.md +115 -0
  49. package/dist/skills/structured-exchange/references/proposals.md +86 -0
  50. package/dist/skills/structured-exchange/references/timelines.md +87 -0
  51. package/dist/skills/structured-exchange/structured-exchange-3.json +1263 -0
  52. package/dist/skills/structured-exchange/structured-exchange-profile-registry-2.json +94 -0
  53. package/dist/skills/structured-exchange-project/SKILL.md +22 -0
  54. package/dist/web/assets/{PdfViewer-DHIy06i5.js → PdfViewer-9kadnb9W.js} +2 -2
  55. package/dist/web/assets/{abnfDiagram-VCTEODGH-0IqI620v.js → abnfDiagram-YUKMZFIV-BUZ7jF1I.js} +1 -1
  56. package/dist/web/assets/architecture-WOLXFQ4H-CxBmyj2Z.js +1 -0
  57. package/dist/web/assets/architectureDiagram-47P4ROYG-BAvert-J.js +36 -0
  58. package/dist/web/assets/{blockDiagram-OSKFZWR5-sw0nzjYC.js → blockDiagram-E7TT5TSB-CXQT_J2x.js} +16 -5
  59. package/dist/web/assets/c4Diagram-CRA5TL53-Byqo5aDs.js +38 -0
  60. package/dist/web/assets/channel-D3nE3SyW.js +1 -0
  61. package/dist/web/assets/chunk-2BW5OAIV-D9dSVCv2.js +10 -0
  62. package/dist/web/assets/chunk-3YJQHVM4-D6IQcIQB.js +2 -0
  63. package/dist/web/assets/chunk-4EA7E6EY-BxZ_5HMn.js +1 -0
  64. package/dist/web/assets/{chunk-F27PBJKO-C6rqX2gT.js → chunk-7TKQ45FW-G9TsFldk.js} +1 -1
  65. package/dist/web/assets/{chunk-SVP7TREG-CYXVRfc0.js → chunk-AW2ZBBNX-nmg5rsd5.js} +3 -3
  66. package/dist/web/assets/{chunk-GVQU2GXP-BtSmWzHA.js → chunk-DBDB3WZW-BwVIGLtu.js} +1 -1
  67. package/dist/web/assets/chunk-DUW6YSOI-Dgx8z5s3.js +1 -0
  68. package/dist/web/assets/chunk-E2ZNV5FY-VD95O25Z.js +72 -0
  69. package/dist/web/assets/chunk-EU5HNXII-CSnybkPb.js +213 -0
  70. package/dist/web/assets/chunk-FVRAUYC3-TBqluQ8N.js +2 -0
  71. package/dist/web/assets/{chunk-PWAF6VOD-Dup_NAkl.js → chunk-HJ2JQQFS-BiLMpVsO.js} +1 -1
  72. package/dist/web/assets/chunk-HTAEGDNF-QDOAuhR5.js +1 -0
  73. package/dist/web/assets/chunk-J5ZVWO5B-oDCd-gWO.js +1 -0
  74. package/dist/web/assets/{chunk-POPQ4Y6H-BrnPOTT-.js → chunk-KQW6MTUR-_WxFaX97.js} +1 -1
  75. package/dist/web/assets/chunk-NGNAAXSQ-BW1P8EP7.js +136 -0
  76. package/dist/web/assets/chunk-NTY3LDVX-BI0Pj8F6.js +1 -0
  77. package/dist/web/assets/chunk-VPRB5NB3-BBDlNNll.js +129 -0
  78. package/dist/web/assets/chunk-XC4XBNZT-Ba1ra4Jd.js +62 -0
  79. package/dist/web/assets/classDiagram-v2-K4WV4PDN-CksBjG_q.js +217 -0
  80. package/dist/web/assets/{conversationExport-CfUybHMU.js → conversationExport-q-9NUHuj.js} +1 -1
  81. package/dist/web/assets/cynefin-EF2NZ3EQ-ucJDz_S5.js +1 -0
  82. package/dist/web/assets/{cynefinDiagram-5FMLGOSQ-BKvXEDID.js → cynefinDiagram-3GCD6N5R-qPxcNdaa.js} +1 -1
  83. package/dist/web/assets/dagre-W4DXFKR2-ChflYJGj.js +4 -0
  84. package/dist/web/assets/diagram-2UJZ2QOL-Bi9ngdu2.js +200 -0
  85. package/dist/web/assets/{diagram-VX7I27RA-D5POkb-9.js → diagram-OVF4WLC6-iSSbF5Cd.js} +10 -10
  86. package/dist/web/assets/{diagram-S7CK7UJ4-DTvEAe9r.js → diagram-PFPMY2P6-BeEOD8rR.js} +2 -2
  87. package/dist/web/assets/{diagram-Z3DM3KII-CC2Mxm4H.js → diagram-UMYRVEAY-BckO6iZI.js} +1 -1
  88. package/dist/web/assets/{diagram-UQ7AKVKN-CVGEkml-.js → diagram-YEKJPTXX-BzzDIAmO.js} +2 -2
  89. package/dist/web/assets/diagram-ZIFT7M5P-ByjWOPbN.js +3 -0
  90. package/dist/web/assets/{docxExport-ErgwApAZ.js → docxExport-BO7j3Xnv.js} +1 -1
  91. package/dist/web/assets/{ebnfDiagram-PWID7BFC-CbDy2vxX.js → ebnfDiagram-VR2GEFS7-DRp-A5JC.js} +1 -1
  92. package/dist/web/assets/elk-IJKZMXRS-QzeiQ3l1.js +27 -0
  93. package/dist/web/assets/{erDiagram-2YWLMYGG-DUdStx-7.js → erDiagram-O2IAPWRE-BewZvI56.js} +15 -15
  94. package/dist/web/assets/eventmodeling-K75KTNOO-CX7X0bsf.js +1 -0
  95. package/dist/web/assets/flowDiagram-OXPTDLAJ-CSIHFoeR.js +1 -0
  96. package/dist/web/assets/ganttDiagram-R7TSEDQI-BT8Lcdwc.js +292 -0
  97. package/dist/web/assets/gitGraph-VSP46ZUC-BxYbaxeg.js +1 -0
  98. package/dist/web/assets/gitGraphDiagram-XJZIOB7I-B0fqVCqP.js +106 -0
  99. package/dist/web/assets/index-DcqvxkHN.css +2 -0
  100. package/dist/web/assets/index-eTp_lQUc.js +350 -0
  101. package/dist/web/assets/info-OHQRW6UA-DV3PDKXA.js +1 -0
  102. package/dist/web/assets/infoDiagram-5W2HQ5XZ-DfHpZ9RG.js +2 -0
  103. package/dist/web/assets/{ishikawaDiagram-5VMMS53U-D-gYpOUM.js → ishikawaDiagram-K3B6WC7H-DuwLwL9k.js} +2 -2
  104. package/dist/web/assets/{journeyDiagram-EYS64GPL-B0WqOtZ4.js → journeyDiagram-COXZFDF6-CMOfweZO.js} +4 -4
  105. package/dist/web/assets/{kanban-definition-UXKFOSKX-DIrVFtP3.js → kanban-definition-P3RFRI5V-DjHhlDbk.js} +9 -9
  106. package/dist/web/assets/{line-CuEhAU65.js → line-CGIAMPkR.js} +1 -1
  107. package/dist/web/assets/loadReferencedImage-DZ5eApE4.js +2 -0
  108. package/dist/web/assets/{mermaid-parser.core-CzCh9EE1.js → mermaid-parser.core-C18KmsD9.js} +6 -6
  109. package/dist/web/assets/mermaid.core-C9srNL3b.js +44 -0
  110. package/dist/web/assets/{mindmap-definition-THT77NOG-CBH0Z9AJ.js → mindmap-definition-LZFPQGKD-C38HXkG2.js} +24 -24
  111. package/dist/web/assets/packet-JDAUHWVQ-Br-8ADK6.js +1 -0
  112. package/dist/web/assets/{pdf-6mG9havR.js → pdf-C3f6Vjz7.js} +1 -1
  113. package/dist/web/assets/{pegDiagram-XKGWAZYB-BNpTWHo8.js → pegDiagram-BGZESJAR-Be49dM_b.js} +1 -1
  114. package/dist/web/assets/pie-XZMESJXO-68ykK6i1.js +1 -0
  115. package/dist/web/assets/{pieDiagram-E7YTZNPT-CZ34Q1W-.js → pieDiagram-CAPJLFHJ-DVOWjXQ_.js} +2 -2
  116. package/dist/web/assets/{quadrantDiagram-AXDQQJYC-C5aFQsIe.js → quadrantDiagram-GDMTTRAM-8la_R53U.js} +3 -3
  117. package/dist/web/assets/radar-ABXABTNO-K00ZGu13.js +1 -0
  118. package/dist/web/assets/railroad-I3PHUGI6-W7QuDysT.js +1 -0
  119. package/dist/web/assets/railroad-abnf-LNEFI6M7-DR6CNkaK.js +1 -0
  120. package/dist/web/assets/railroad-ebnf-DWYD2UWJ-dAhaGv5L.js +1 -0
  121. package/dist/web/assets/railroad-peg-JR7BVNR7-DwoiiDdE.js +1 -0
  122. package/dist/web/assets/{railroadDiagram-O6MQD6OU-B0ctRtRT.js → railroadDiagram-SM67HX2B-BuSjCs02.js} +1 -1
  123. package/dist/web/assets/{requirementDiagram-IS5BZ75X-BuOtNPGm.js → requirementDiagram-X7JNWC4A-3uq8m_5E.js} +11 -11
  124. package/dist/web/assets/{sankeyDiagram-P5KCCOFB-CybICPpQ.js → sankeyDiagram-UM26HJRW-BB9_G8bN.js} +3 -3
  125. package/dist/web/assets/sequenceDiagram-ZO4K6R2Y-CGehVq9k.js +169 -0
  126. package/dist/web/assets/stateDiagram-v2-TBUQTH76-CwMywh5s.js +291 -0
  127. package/dist/web/assets/swimlanes-N4OXWK64-CqjihurI.js +1 -0
  128. package/dist/web/assets/swimlanesDiagram-K3J5GTZL-Blk5ohUI.js +8 -0
  129. package/dist/web/assets/timeline-definition-YOQAKGHF-BtKnuY5Y.js +120 -0
  130. package/dist/web/assets/treeView-D4JQ5SDB-Dy4jC4wa.js +1 -0
  131. package/dist/web/assets/treemap-SAJKECNS-CHtGJD8P.js +1 -0
  132. package/dist/web/assets/usecaseDiagram-VIAY4XPW-BjnstWbR.js +328 -0
  133. package/dist/web/assets/vennDiagram-BLWOH2XV-o_EtJWVA.js +34 -0
  134. package/dist/web/assets/wardley-7MLQ67FV-BTheL3FW.js +1 -0
  135. package/dist/web/assets/{wardleyDiagram-VM6X3IG4-CzB2tR_t.js → wardleyDiagram-YMQ3BMBF-Bp_sv2v4.js} +3 -3
  136. package/dist/web/assets/xychartDiagram-TAQBALBS-C0IpEfij.js +7 -0
  137. package/dist/web/index.html +2 -2
  138. package/package.json +3 -3
  139. package/dist/web/assets/architecture-7GRP2DOG-BqTZwqCY.js +0 -1
  140. package/dist/web/assets/architectureDiagram-5GKGNRK7-BEGSAGSn.js +0 -36
  141. package/dist/web/assets/c4Diagram-7LVT6UL2-C6wQYxBC.js +0 -38
  142. package/dist/web/assets/channel-CbMG5PZq.js +0 -1
  143. package/dist/web/assets/chunk-3NF5O7KM-Dni31-nE.js +0 -168
  144. package/dist/web/assets/chunk-4HAMMTFA-hiqoLVtf.js +0 -62
  145. package/dist/web/assets/chunk-75Z2AOVW-1k7HRGrm.js +0 -2
  146. package/dist/web/assets/chunk-DU6HZSFF-Dy05V--k.js +0 -127
  147. package/dist/web/assets/chunk-FOHPRMQF-DHwB1DNv.js +0 -161
  148. package/dist/web/assets/chunk-GMAD6QVW-Bi5Ne8OE.js +0 -72
  149. package/dist/web/assets/chunk-HLEWEB6X-yamDqy1M.js +0 -206
  150. package/dist/web/assets/chunk-L3NEJ4N5-CQSamtuJ.js +0 -1
  151. package/dist/web/assets/chunk-OSK3NFVY-S95igUko.js +0 -10
  152. package/dist/web/assets/chunk-P2QGCYS3-BPor-azX.js +0 -1
  153. package/dist/web/assets/chunk-ZLD2IHE6-D0uZMMWb.js +0 -231
  154. package/dist/web/assets/classDiagram-CYGNFDIV-2Yl201cv.js +0 -1
  155. package/dist/web/assets/classDiagram-v2-TLXNO2FR-2Yl201cv.js +0 -1
  156. package/dist/web/assets/cynefin-OW5HDTMX-ua6bZIWp.js +0 -1
  157. package/dist/web/assets/dagre-OS7QT2EB-BRxaZdm2.js +0 -4
  158. package/dist/web/assets/dagre-PrKaheQc.js +0 -1
  159. package/dist/web/assets/diagram-VSXAHHWV-Dkh-RvzE.js +0 -3
  160. package/dist/web/assets/eventmodeling-NTZA5JFV-Bw8wULv_.js +0 -1
  161. package/dist/web/assets/flowDiagram-T62WH6J4-Dp4v9IDN.js +0 -1
  162. package/dist/web/assets/ganttDiagram-EL5Y4UJY-6dI1H52q.js +0 -292
  163. package/dist/web/assets/gitGraph-4MIJSDKK-UXnB0IFr.js +0 -1
  164. package/dist/web/assets/gitGraphDiagram-WWUBYQGX-B_wXPpx0.js +0 -106
  165. package/dist/web/assets/index-9y9n2Dul.css +0 -2
  166. package/dist/web/assets/index-COu8CnNa.js +0 -350
  167. package/dist/web/assets/info-A6RAGUB7-C2WWyNzF.js +0 -1
  168. package/dist/web/assets/infoDiagram-FKFFQAWI-DY65_ndC.js +0 -2
  169. package/dist/web/assets/loadReferencedImage-DgHMXQNZ.js +0 -2
  170. package/dist/web/assets/mermaid.core-BmGW_v8T.js +0 -44
  171. package/dist/web/assets/packet-AYTQ26CC-BYG_KViO.js +0 -1
  172. package/dist/web/assets/pie-WAS4IAKB-wBoUHr8R.js +0 -1
  173. package/dist/web/assets/radar-RG4KPBEZ-D4K5XP7X.js +0 -1
  174. package/dist/web/assets/railroad-74A4TZTK-Haum25Us.js +0 -1
  175. package/dist/web/assets/railroad-abnf-HS5TGJTU-D-kbOsoZ.js +0 -1
  176. package/dist/web/assets/railroad-ebnf-LZEXJU2U-CWtixpZf.js +0 -1
  177. package/dist/web/assets/railroad-peg-WCYAUIDC-BeY7arxf.js +0 -1
  178. package/dist/web/assets/sequenceDiagram-WJ2MYXX4-Dvo8sl8e.js +0 -162
  179. package/dist/web/assets/stateDiagram-XQSTLZYL-BcM-hGJa.js +0 -1
  180. package/dist/web/assets/stateDiagram-v2-IH3M54BS-hYgwFLzv.js +0 -1
  181. package/dist/web/assets/swimlanes-V6O3JKXN-mOOjKnlm.js +0 -1
  182. package/dist/web/assets/swimlanesDiagram-JKAHXJPX-C_yinM3f.js +0 -8
  183. package/dist/web/assets/timeline-definition-24CTP7MA-DuwMztTy.js +0 -120
  184. package/dist/web/assets/treeView-Q6P3EWNA-BT4vRttT.js +0 -1
  185. package/dist/web/assets/treemap-WGGIJYW6-Df6GHCE2.js +0 -1
  186. package/dist/web/assets/vennDiagram-4TSXK5OY-BbcbGn7o.js +0 -34
  187. package/dist/web/assets/wardley-WFR3VGLG-L_G3ydHA.js +0 -1
  188. package/dist/web/assets/xychartDiagram-S5SC5T6Z-CKHwJboP.js +0 -7
@@ -0,0 +1,158 @@
1
+ # The enriched contract: `urn:structured-exchange:2`
2
+
3
+ <!-- only: pi-outpost -->
4
+ Part of the `structured-exchange` skill. What a project's profile refuses, and what to do about it, is in its `SKILL.md`.
5
+ <!-- end -->
6
+
7
+ Everything in `SKILL.md` is version 1 and still works exactly as written. Declare version 2
8
+ instead when you need any of what follows. Nothing is removed: change the identifier and
9
+ a version 1 document is a version 2 document, except that `target` becomes an object
10
+ (`"target": { "ref": "architecture-v4" }`), which is what lets it name a revision.
11
+
12
+ **Emit version 1 unless you need something below.** The reader cannot tell which you
13
+ used and neither contract is better; there is simply no reason to reach for the larger
14
+ vocabulary to say a smaller thing.
15
+
16
+ ## Attributes: the properties your domain owns
17
+
18
+ Any element, relationship or row may carry `attributes` — bounded, typed properties
19
+ whose names belong to your domain, not to this contract.
20
+
21
+ ```json
22
+ { "id": "battery", "label": "Battery", "kind": "source",
23
+ "attributes": { "voltage": 400, "chemistry": "LFP", "serviceable": true,
24
+ "suppliedBy": [{ "ref": "ORG-3" }] } }
25
+ ```
26
+
27
+ A value is a string, a finite number, a boolean, `null`, a reference (`{ "ref": "…" }`),
28
+ or one flat list of those. **Lists never nest and no other object shape is allowed.** A
29
+ quantity with a unit is two attributes or one string — `"mass_kg": 3.4`, not
30
+ `{ "value": 3.4, "unit": "kg" }`, which is refused.
31
+
32
+ Name the vocabulary those names come from with `profile` on the envelope:
33
+
34
+ ```json
35
+ { "schema": "urn:structured-exchange:2", "kind": "graph", "profile": "acme/electrical", "data": { … } }
36
+ ```
37
+
38
+ The profile is **a name and nothing more**. It is never fetched, resolved or executed,
39
+ and a reader who does not know it still sees every attribute, rendered generically. Do
40
+ not invent one to look official; use the identifier your domain actually uses, or omit
41
+ it.
42
+
43
+ ## Description, expectation, change: three different claims
44
+
45
+ Version 1 already separates *describing* a referenced thing from *changing* it. Version
46
+ 2 adds a third, and confusing them is the mistake that matters:
47
+
48
+ ```json
49
+ { "id": "r1", "ref": "REQ-1",
50
+ "label": "Stop within 40 m",
51
+ "expect": { "revision": "rev-9", "attributes": { "status": "approved" } },
52
+ "set": { "label": "Stop within 35 m", "attributes": { "status": "in review" },
53
+ "removeAttributes": ["waiver"] } }
54
+ ```
55
+
56
+ - **beside `ref`** — what it is called *now*. How the reader recognises it. Applied to
57
+ nothing.
58
+ - **`expect`** — what you believe is currently true, for the receiving authority to check
59
+ before it applies anything. You are not asserting it is true; you are saying what you
60
+ assumed. If you did not read the current state, do not write an `expect`.
61
+ - **`set`** — the only thing that changes anything.
62
+ - **`removeAttributes`** — takes properties away. **`null` does not delete.** Writing
63
+ `"waiver": null` sets the property to null; to unset it, name it here. Naming the same
64
+ attribute in both `set.attributes` and `removeAttributes` is refused rather than
65
+ resolved, because there is no precedence worth inventing.
66
+
67
+ Put the revision you prepared against on the target: `"target": { "ref": "REQ-DOC-1",
68
+ "revision": "rev-9" }`. A revision and an `expect` are only allowed in a proposal —
69
+ there is no authority to check them against otherwise.
70
+
71
+ ## Locations: where it is, never what it is
72
+
73
+ ```json
74
+ "locations": [{ "uri": "file:///src/brakes.ts", "revision": "abc123",
75
+ "range": { "startLine": 10, "endLine": 42 } }]
76
+ ```
77
+
78
+ A hint for a reader, zero-based. It takes no part in identity: `ref` says what something
79
+ **is**, a location says where a copy of it can be found today. Never encode a path into a
80
+ `ref` to save writing one — moving the file would then change the thing's identity.
81
+
82
+ Nothing is opened until a reader asks, and only through the application's existing rules
83
+ about what may be opened at all.
84
+
85
+ ## Artifacts: linked, digested, not attached
86
+
87
+ ```json
88
+ "artifacts": [{ "rel": "verifies", "uri": "https://ci.example/report.json",
89
+ "sha256": "sha256:<64 hex characters>", "mediaType": "application/json" }]
90
+ ```
91
+
92
+ The digest is mandatory, and it is the point: it binds an approval to specific bytes
93
+ even when the URI serves different ones later. If you cannot compute a digest, you do not
94
+ have an artifact link — use a location instead. Never inline the content; the envelope
95
+ carries references, and a payload pasted into it is a document nobody can read and a
96
+ ceiling you will hit.
97
+
98
+ ## Tables that carry a document
99
+
100
+ A row may declare an identity and a type of its own, which is what makes a requirements
101
+ table more than a grid:
102
+
103
+ ```json
104
+ { "id": "r1", "ref": "REQ-1", "kind": "requirement",
105
+ "cells": ["REQ-1", "Stop within 40 m", "approved"] }
106
+ ```
107
+
108
+ Headings organise it, and are rows of their own — not a data row with empty cells:
109
+
110
+ ```json
111
+ { "heading": "1. Braking", "depth": 1 }
112
+ ```
113
+
114
+ Traceability between rows is declared beside them, with each end stated explicitly:
115
+
116
+ ```json
117
+ "relations": [
118
+ { "from": { "id": "r1" }, "to": { "id": "r2" }, "kind": "derives" },
119
+ { "from": { "id": "r1" }, "to": { "ref": "TEST-9" }, "kind": "verifiedBy" }
120
+ ]
121
+ ```
122
+
123
+ `{ "id": … }` is a row of this document and must exist — a typo is refused, not quietly
124
+ drawn pointing at nothing. `{ "ref": … }` is something outside it and is accepted as
125
+ leaving the document, which is the normal case for the test that verifies a requirement.
126
+ Relation kinds are opaque, like every other kind: `derives`, `verifiedBy`, `satisfies` —
127
+ whatever your domain says.
128
+
129
+ **Do not state coverage you have not been told.** A requirement with no relation is a
130
+ requirement with no relation; the application reports what you declared and infers
131
+ nothing about what is missing.
132
+
133
+ All of it together, as one document you can copy:
134
+
135
+ ```json
136
+ {
137
+ "schema": "urn:structured-exchange:2",
138
+ "kind": "table",
139
+ "profile": "acme/requirements",
140
+ "data": {
141
+ "columns": ["id", "requirement", "status"],
142
+ "rows": [
143
+ { "heading": "1. Braking", "depth": 1 },
144
+ { "id": "r1", "ref": "REQ-1", "kind": "requirement",
145
+ "cells": ["REQ-1", "Stop within 40 m", "approved"],
146
+ "attributes": { "verification": "test" },
147
+ "locations": [{ "uri": "file:///specs/brakes.md", "range": { "startLine": 10, "endLine": 12 } }] },
148
+ { "heading": "1.1 Sensing", "depth": 2 },
149
+ { "id": "r2", "ref": "REQ-2", "kind": "requirement",
150
+ "cells": ["REQ-2", "Read wheel speed at 100 Hz", "approved"] }
151
+ ],
152
+ "relations": [
153
+ { "from": { "id": "r1" }, "to": { "id": "r2" }, "kind": "derives" },
154
+ { "from": { "id": "r1" }, "to": { "ref": "TEST-9" }, "kind": "verifiedBy" }
155
+ ]
156
+ }
157
+ }
158
+ ```
@@ -0,0 +1,52 @@
1
+ # Putting a diagram in a document you are writing
2
+
3
+ Part of the `structured-exchange` skill. A timeline's own figure options are in `references/timelines.md`.
4
+
5
+ `present_structure` shows a document in the conversation. When you are *writing* a
6
+ file — a report, a design note, a README — a diagram belongs in that file instead,
7
+ and `write_structure_figure` puts it there:
8
+
9
+ ```
10
+ write_structure_figure(
11
+ path: "models/vehicle.json",
12
+ output_path: "figures/power-train.svg",
13
+ hide_relationship_kinds: ["diagnostic"]
14
+ )
15
+ ```
16
+
17
+ It reads a structured-exchange document from the workspace, draws it, and writes one
18
+ `.svg`. Reference it from your Markdown as a relative path — `![Power
19
+ train](figures/power-train.svg)` — and the interface renders it in the preview.
20
+
21
+ Three things about it are worth knowing before you use it.
22
+
23
+ **The two hide lists are different vocabularies.** `hide_element_kinds` hides boxes by
24
+ their `kind`; `hide_relationship_kinds` hides arrows by theirs. The same name in both
25
+ means two unrelated things, and naming one where you meant the other hides nothing,
26
+ draws a perfectly valid figure of the whole document, and looks like it worked.
27
+
28
+ **Write one figure per view worth having.** A narrowed figure is the reason the tool
29
+ takes a narrowing at all: three figures each about one thing beat one figure of
30
+ everything, which is the diagram nobody reads. A figure that shows less than its
31
+ document says so, inside the picture, so a figure separated from its source is never
32
+ mistaken for the whole of it.
33
+
34
+ **A relationship whose endpoint you hid goes with it.** An arrow to a box that is not
35
+ drawn cannot be drawn. The result tells you how much of the document the figure shows,
36
+ so a narrowing that took more than you meant is visible in the answer rather than in
37
+ the file.
38
+
39
+ A table has no figure — it is data. To put one in a document you are writing,
40
+ `write_structure_table` writes it as Markdown:
41
+
42
+ ```
43
+ write_structure_table(
44
+ path: "requirements/braking.json",
45
+ output_path: "reports/braking-requirements.md"
46
+ )
47
+ ```
48
+
49
+ It reads a table from the workspace and writes a new `.md` file — each chapter a heading
50
+ followed by a Markdown table of its rows — which you can include in the document or hand on.
51
+ It never overwrites an existing file, and a table the project's profile or rules refuse is not
52
+ written. The reader can also export a table they are shown as a spreadsheet or as Markdown.
@@ -0,0 +1,115 @@
1
+ # Graphs and tables: roles, containers, viewpoints
2
+
3
+ Part of the `structured-exchange` skill. The envelope and validation are in its `SKILL.md`.
4
+
5
+ ## Roles on a table's rows
6
+
7
+ A table cannot be proposed, but it can *report* on a change it projects. Any row
8
+ may say what it plays, and the interface colours it the way it colours an added or
9
+ changed element in a graph:
10
+
11
+ ```jsonc
12
+ "data": {
13
+ "columns": ["id", "requirement", "status"],
14
+ "rows": [
15
+ { "role": "added", "cells": ["REQ-5", "Log every actuation.", "draft"] },
16
+ { "role": "changed", "cells": ["REQ-2", "Signal a fault within 200 ms.", "in review"] },
17
+ { "role": "removed", "cells": ["REQ-3", "Read battery voltage at 10 Hz.", "withdrawn"] },
18
+ { "cells": ["REQ-1", "Stop the vehicle within 40 m.", "approved"] } // context
19
+ ]
20
+ }
21
+ ```
22
+
23
+ `role` is one of `added`, `changed`, `context`, `removed`. A row that declares none
24
+ reads as context when any other row declares one. Both row forms are accepted, so
25
+ `["REQ-1", "…"]` and `{ "cells": ["REQ-1", "…"] }` are the same row, and a table
26
+ that declares no role anywhere is rendered exactly as before roles existed.
27
+
28
+ Declare the role — do not put it in a column and expect the colours. A `status`
29
+ column is your data and is rendered as data; nothing infers a role from it.
30
+
31
+ ## Grouping: containers
32
+
33
+ A graph or a sequence may declare **containers** — subsystems, layers, teams,
34
+ whatever the domain groups things into — and each element or participant may say
35
+ which one it belongs to.
36
+
37
+ ```jsonc
38
+ "data": {
39
+ "containers": [{ "id": "electrical", "label": "Electrical system" }],
40
+ "nodes": [{ "id": "battery", "label": "Battery", "container": "electrical" },
41
+ { "id": "driver", "label": "Driver" }], // in no container
42
+ "edges": [{ "from": "driver", "to": "battery", "kind": "operates" }]
43
+ }
44
+ ```
45
+
46
+ Four things to know:
47
+
48
+ - **Membership goes on the member**, never as a list of members on the container.
49
+ An element belongs to one container or to none.
50
+ - **Relationships ignore grouping entirely.** They connect elements, they cross
51
+ container boundaries freely, and an endpoint is never a container id. Naming a
52
+ container as `from` or `to` is refused.
53
+ - **Containers do not nest.** A member names a container, never a chain of them.
54
+ - **A container nobody joins is fine.** Declare the group first and fill it later
55
+ if that is what you mean; it is drawn as an empty box.
56
+
57
+ Naming a container the document does not declare is refused rather than quietly
58
+ ungrouped — an element shown outside a group it belongs to would misstate the
59
+ system you are describing.
60
+
61
+ In a sequence, the view puts a container's columns next to each other so its
62
+ header spans them. If you interleave two containers, the columns are reordered:
63
+ the first member of a container met brings the rest of that container with it,
64
+ and anything belonging to no container keeps its place. Declare participants in
65
+ the order you want them read.
66
+
67
+ ## Viewpoints: the readings a graph is made for
68
+
69
+ When a graph will be read in more than one way — power, then control, then what is
70
+ safety-relevant — declare those readings as `viewpoints` on the envelope, rather than
71
+ leaving the reader to rebuild each one from the key:
72
+
73
+ ```json
74
+ {
75
+ "schema": "urn:structured-exchange:2",
76
+ "kind": "graph",
77
+ "viewpoints": [
78
+ {
79
+ "id": "power",
80
+ "label": "Power distribution",
81
+ "concern": "Where energy is stored, converted and consumed",
82
+ "elementKinds": ["source", "load"],
83
+ "relationshipKinds": ["power"]
84
+ }
85
+ ],
86
+ "data": {
87
+ "nodes": [
88
+ { "id": "battery", "label": "Battery", "kind": "source" },
89
+ { "id": "motor", "label": "Motor", "kind": "load" },
90
+ { "id": "ecu", "label": "ECU", "kind": "controller" }
91
+ ],
92
+ "edges": [
93
+ { "from": "battery", "to": "motor", "kind": "power" },
94
+ { "from": "ecu", "to": "motor", "kind": "signal" }
95
+ ]
96
+ }
97
+ }
98
+ ```
99
+
100
+ - **A viewpoint says what it retains.** Name the element kinds, the relationship kinds,
101
+ or both — at least one list. A list you leave out keeps that whole vocabulary.
102
+ - **Only kinds the document has.** Every kind you retain must be the kind of some
103
+ element (or, for `relationshipKinds`, some relationship) in this document. A typo is
104
+ refused, not corrected, and the refusal says when the word exists in the other list.
105
+ - **Always give the concern.** It is printed inside every figure drawn for the
106
+ viewpoint — write it as the question that reading answers.
107
+ - **Graphs only**, and at most twenty per document.
108
+ - **Something with no kind survives every viewpoint.** If an element must drop out of a
109
+ reading, give it a kind.
110
+
111
+ <!-- only: pi-outpost -->
112
+ When you write a report with one chapter per reading, write one figure per viewpoint:
113
+ `write_structure_figure` with `viewpoint: "power"`. Do not rebuild the same selection
114
+ from hide lists — the viewpoint carries both the selection and the reason for it.
115
+ <!-- end -->
@@ -0,0 +1,86 @@
1
+ # Proposing a change to something that exists
2
+
3
+ Part of the `structured-exchange` skill. The envelope, the two identities and validation are in its `SKILL.md`.
4
+
5
+ > **The one rule that trips everyone up.** When you propose a change to something
6
+ > that already exists, the fields you write beside its `ref` say *what it is called
7
+ > now*. They are not applied. The new value goes in `set`.
8
+ >
9
+ > ```json
10
+ > { "id": "ledger", "ref": "EL-7", "label": "Ledger",
11
+ > "set": { "label": "General Ledger" } }
12
+ > ```
13
+ >
14
+ > Writing `"label": "General Ledger"` on its own does **not** rename anything — it
15
+ > claims that is already its name, and the proposal silently does nothing. If the
16
+ > tool answers `0 changed`, this is what happened.
17
+
18
+ Name the artifact in `target`. Then:
19
+
20
+ - An element you do not mention is left alone. Omission never removes anything.
21
+ - **On anything carrying a `ref`, the fields you declare describe what is already
22
+ there.** They are how the reader recognises it. They change nothing.
23
+ - **To change something, say so in `set`.** That is the only thing that is applied.
24
+ - To remove something, say so in `removals`, giving both the `ref` and whether it is
25
+ an `"element"` or a `"relationship"` — a reference alone does not say which.
26
+
27
+ > **Say what you are removing.** A removal may also carry `label`, `kind`, and for a
28
+ > relationship `from` and `to`. Add them. The reader's application holds your document
29
+ > and nothing else — it cannot look up what `REL-88` stood for, so without them the
30
+ > approval gate reads "relationship: REL-88" and asks someone to approve deleting
31
+ > something they cannot see. These fields describe and never identify: `ref` is still
32
+ > what names the thing.
33
+
34
+ ```json
35
+ {
36
+ "schema": "urn:structured-exchange:1",
37
+ "kind": "graph",
38
+ "target": "architecture-v4",
39
+ "removals": [
40
+ { "type": "relationship", "ref": "REL-88",
41
+ "kind": "calls", "from": "ledger", "to": "billing" }
42
+ ],
43
+ "data": {
44
+ "nodes": [
45
+ { "id": "billing", "ref": "EL-12", "label": "Billing" },
46
+ { "id": "ledger", "ref": "EL-7", "label": "Ledger",
47
+ "set": { "label": "General Ledger" } },
48
+ { "id": "audit", "label": "Audit" }
49
+ ],
50
+ "edges": [{ "from": "audit", "to": "billing", "kind": "calls" }]
51
+ }
52
+ }
53
+ ```
54
+
55
+ Read that proposal:
56
+
57
+ - **The removal** names `REL-88` and says what it is: the `calls` from Ledger to
58
+ Billing. The reader sees what goes, rather than an identifier.
59
+
60
+ - **`billing`** has a `ref` and a name, no `set` → **context**. It exists, it is shown
61
+ so you can see where the new thing attaches, and nothing happens to it.
62
+ - **`ledger`** has a `ref`, its current name, and a `set` → **a change**. The reader
63
+ sees `Ledger → General Ledger`, which is what makes it approvable.
64
+ - **`audit`** has no `ref` → **new**. With nothing to describe, its `label` is simply
65
+ its value.
66
+
67
+ **Include as much context as the reader needs.** That is what the default is for: an
68
+ element you include to make the picture legible costs nothing and changes nothing.
69
+ Leaving it out to be safe is the wrong instinct — a proposal nobody can situate is a
70
+ proposal nobody should approve.
71
+
72
+ ## Two rules that catch people out
73
+
74
+ **Never put a `set` on something with no `ref`.** There is nothing to change; its
75
+ fields are already its values. Refused.
76
+
77
+ **Never both `set` and remove the same `ref`.** That states two intentions at once and
78
+ is refused rather than resolved — decide which you meant.
79
+
80
+ **A relationship always declares `from` and `to`**, even when it carries a `ref`. Its
81
+ endpoints are its identity, not something you patch. To re-attach a relationship,
82
+ remove it and declare a new one.
83
+
84
+ **Moving something between containers is an ordinary change**: `"set": { "container":
85
+ "electrical" }` on an element that carries a `ref`, like any other field you change.
86
+ Containers themselves are not patched — they are declared afresh in every document.
@@ -0,0 +1,87 @@
1
+ # Timelines: a schedule as data
2
+
3
+ Part of the `structured-exchange` skill. The envelope, validation and size limits are in its `SKILL.md`.
4
+
5
+ A project schedule, a roadmap, a validation campaign: declare it as a version 3
6
+ `timeline` rather than as a Mermaid `gantt` block or a table of dates. The interface
7
+ draws a proportional calendar, bars, star milestones, dependency arrows and a **Today**
8
+ line taken from the reader's own date.
9
+
10
+ ```json
11
+ {
12
+ "schema": "urn:structured-exchange:3",
13
+ "kind": "timeline",
14
+ "data": {
15
+ "title": "Programme X",
16
+ "time": { "start": "2026-10-01", "end": "2027-12-31", "scale": "month" },
17
+ "rows": [
18
+ { "type": "separator", "label": "System A" },
19
+ { "type": "task", "id": "T1", "label": "System studies", "items": [
20
+ { "type": "activity", "id": "study", "start": "2026-11-01", "end": "2027-02-28", "label": "Preliminary study" },
21
+ { "type": "milestone", "id": "srr", "date": "2027-03-01", "kind": "SRR", "label": "System Requirements Review" },
22
+ { "type": "activity", "id": "design", "start": "2027-03-15", "end": "2027-07-31", "label": "Detailed design" },
23
+ { "type": "milestone", "id": "cdr", "date": "2027-08-01", "kind": "CDR" }
24
+ ] },
25
+ { "type": "separator" },
26
+ { "type": "task", "id": "T2", "label": "Development", "items": [
27
+ { "type": "activity", "id": "dev", "start": "2027-03-01", "end": "2027-09-30" }
28
+ ] }
29
+ ],
30
+ "dependencies": [
31
+ { "from": "study", "to": "srr" },
32
+ { "from": "srr", "to": "T2" },
33
+ { "from": "design", "to": "cdr", "type": "finish-to-finish" }
34
+ ]
35
+ }
36
+ }
37
+ ```
38
+
39
+ - **Rows** are drawn in order. A `task` has an `id`, a `label` and any number of
40
+ `items` — activities and milestones, overlapping or with gaps, in any order. A
41
+ `separator` divides groups of tasks, with a `label` or without one.
42
+ - **An activity** runs from `start` to `end` inclusive; **a milestone** is a `date`.
43
+ Dates are calendar days, `YYYY-MM-DD`, and every item must fall inside `time`:
44
+ one outside is refused, never clipped — widen `time` instead.
45
+ - **`label`** is what a reader sees beside the item; a milestone without one shows its
46
+ `kind`. **`kind`** is your own vocabulary (`SRR`, `PDR`, `CDR`); every kind gets its
47
+ own colour and a legend entry. Write no colour, position, shape or "today" — the
48
+ renderer derives them, and the schema refuses them.
49
+ - **A dependency** says `to` waits on `from`. Each names a task or an item by `id` (give
50
+ an item an `id` if anything depends on it); a task stands for the span of its items.
51
+ `type` is `finish-to-start` when omitted, or `start-to-start`, `finish-to-finish`,
52
+ `start-to-finish`. A dependency the dates break is **drawn and reported to you as
53
+ not satisfied**, not refused — tell the user, do not move dates to hide it. A cycle
54
+ is refused.
55
+ - A timeline is not a proposal: it has no `target`. To change one, present the whole
56
+ revised timeline again.
57
+ <!-- only: pi-outpost -->
58
+ `write_structure_table` refuses it.
59
+ <!-- end -->
60
+ - **Choose `time.scale` for the plan's length**: `week` for a few months (a test campaign),
61
+ `month` for a year or two, `quarter` beyond (a multi-year programme). It is only the scale
62
+ the plan opens at — the reader can switch to another or fit it to the screen — and it moves
63
+ no date.
64
+ - **Closures, holidays and key dates** belong in the plan: `periods` (`start`, `end`, optional
65
+ `label` and `kind`, e.g. `"fermeture"`) are drawn as bands across every row, and `references`
66
+ (`date`, `label`, optional `kind`, e.g. a contractual date) as named lines. They constrain
67
+ nothing. A period may run past the plan's range (drawn clipped); a reference must fall inside it.
68
+ <!-- only: pi-outpost -->
69
+ - **To show what changed between two versions of a plan**, keep each version as its own
70
+ timeline file and call `compare_timelines` with the previous and the current one — never
71
+ work out the shifts yourself. It pairs tasks and items by `id`, so give every item an `id`
72
+ in a plan that will be compared; it tells you how many it could not pair. The reader sees
73
+ previous dates dashed, shifts like `(+3w)`, new and dropped items marked, and can switch to
74
+ the new version alone. Give `output_path` to keep the comparison for a report, and draw it
75
+ with `write_structure_figure` (`comparison: "new"` draws the new version alone). A compared
76
+ timeline carries `comparedTo`, `previous` dates and `role: "added" | "removed"`; do not write
77
+ these by hand.
78
+ - **To put a timeline in a report**, write it with `write_structure_figure` and reference
79
+ the `.svg` from the Markdown. Give `width` (e.g. `900`) for a page — durations stay
80
+ proportional and rows grow to keep labels apart, and the header switches to months or
81
+ quarters when weeks would not fit; `scale` (`week`, `month`, `quarter`) to draw it at that
82
+ scale's natural size instead; `compact: true` for one row per section;
83
+ `hide_dependencies: true` to leave the arrows out. The figure's date line is labelled
84
+ with the day it is written (`reference_line: "none"` leaves it out), because the file
85
+ outlives that day. Graph options (`hide_element_kinds`, `viewpoint`…) are refused for a
86
+ timeline.
87
+ <!-- end -->