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.
- package/dist/contract/README.md +120 -1
- package/dist/contract/conformance/README.md +29 -5
- package/dist/contract/conformance/index.json +115 -0
- package/dist/contract/conformance/invalid/unknown-version.json +1 -1
- package/dist/contract/conformance/invalid/v3-timeline-comparison-without-reference.json +123 -0
- package/dist/contract/conformance/invalid/v3-timeline-contradictory-change.json +128 -0
- package/dist/contract/conformance/invalid/v3-timeline-dependency-cycle.json +124 -0
- package/dist/contract/conformance/invalid/v3-timeline-dependency-on-removed.json +125 -0
- package/dist/contract/conformance/invalid/v3-timeline-duplicate-dependency.json +125 -0
- package/dist/contract/conformance/invalid/v3-timeline-duplicate-identifier.json +120 -0
- package/dist/contract/conformance/invalid/v3-timeline-empty-task-endpoint.json +124 -0
- package/dist/contract/conformance/invalid/v3-timeline-impossible-date.json +101 -0
- package/dist/contract/conformance/invalid/v3-timeline-inverted-activity.json +120 -0
- package/dist/contract/conformance/invalid/v3-timeline-inverted-range.json +120 -0
- package/dist/contract/conformance/invalid/v3-timeline-milestone-outside-range.json +120 -0
- package/dist/contract/conformance/invalid/v3-timeline-period-outside-range.json +139 -0
- package/dist/contract/conformance/invalid/v3-timeline-presentation-property.json +121 -0
- package/dist/contract/conformance/invalid/v3-timeline-previous-outside-range.json +128 -0
- package/dist/contract/conformance/invalid/v3-timeline-previous-wrong-shape.json +128 -0
- package/dist/contract/conformance/invalid/v3-timeline-reference-outside-range.json +140 -0
- package/dist/contract/conformance/invalid/v3-timeline-self-dependency.json +124 -0
- package/dist/contract/conformance/invalid/v3-timeline-under-version-2.json +120 -0
- package/dist/contract/conformance/invalid/v3-timeline-unknown-dependency-type.json +121 -0
- package/dist/contract/conformance/invalid/v3-timeline-unresolved-dependency-endpoint.json +120 -0
- package/dist/contract/conformance/invalid/v3-timeline-unsupported-scale.json +120 -0
- package/dist/contract/conformance/invalid/v3-timeline-with-target.json +123 -0
- package/dist/contract/conformance/valid/v3-timeline-calendar.json +140 -0
- package/dist/contract/conformance/valid/v3-timeline-compared.json +142 -0
- package/dist/contract/conformance/valid/v3-timeline-empty-task-and-anonymous-separator.json +35 -0
- package/dist/contract/conformance/valid/v3-timeline-four-dependency-types.json +61 -0
- package/dist/contract/conformance/valid/v3-timeline-programme.json +44 -0
- package/dist/contract/conformance/valid/v3-timeline-quarter-scale.json +42 -0
- package/dist/contract/conformance/valid/v3-timeline-single-day-activity.json +27 -0
- package/dist/contract/conformance/valid/v3-timeline-unsatisfied-dependency.json +45 -0
- package/dist/contract/conformance/valid/v3-timeline-week-scale.json +35 -0
- package/dist/contract/conformance/version-1.lock.json +2 -2
- package/dist/contract/schemas/structured-exchange-3.json +1263 -0
- package/dist/contract/schemas/structured-exchange-profile-registry-2.json +94 -0
- package/dist/contract/structured-exchange-project-setup.md +36 -0
- package/dist/contract/validate-structured-exchange.mjs +1981 -174
- package/dist/pi-outpost-tools.mjs +4556 -1130
- package/dist/pi-outpost.mjs +5733 -1898
- package/dist/pi-outpost.sea.mjs +2 -2
- package/dist/sea-prep.blob +2 -2
- package/dist/skills/structured-exchange/SKILL.md +90 -378
- package/dist/skills/structured-exchange/references/enriched-contract.md +158 -0
- package/dist/skills/structured-exchange/references/figures.md +52 -0
- package/dist/skills/structured-exchange/references/graphs-and-tables.md +115 -0
- package/dist/skills/structured-exchange/references/proposals.md +86 -0
- package/dist/skills/structured-exchange/references/timelines.md +87 -0
- package/dist/skills/structured-exchange/structured-exchange-3.json +1263 -0
- package/dist/skills/structured-exchange/structured-exchange-profile-registry-2.json +94 -0
- package/dist/skills/structured-exchange-project/SKILL.md +22 -0
- package/dist/web/assets/{PdfViewer-DHIy06i5.js → PdfViewer-9kadnb9W.js} +2 -2
- package/dist/web/assets/{abnfDiagram-VCTEODGH-0IqI620v.js → abnfDiagram-YUKMZFIV-BUZ7jF1I.js} +1 -1
- package/dist/web/assets/architecture-WOLXFQ4H-CxBmyj2Z.js +1 -0
- package/dist/web/assets/architectureDiagram-47P4ROYG-BAvert-J.js +36 -0
- package/dist/web/assets/{blockDiagram-OSKFZWR5-sw0nzjYC.js → blockDiagram-E7TT5TSB-CXQT_J2x.js} +16 -5
- package/dist/web/assets/c4Diagram-CRA5TL53-Byqo5aDs.js +38 -0
- package/dist/web/assets/channel-D3nE3SyW.js +1 -0
- package/dist/web/assets/chunk-2BW5OAIV-D9dSVCv2.js +10 -0
- package/dist/web/assets/chunk-3YJQHVM4-D6IQcIQB.js +2 -0
- package/dist/web/assets/chunk-4EA7E6EY-BxZ_5HMn.js +1 -0
- package/dist/web/assets/{chunk-F27PBJKO-C6rqX2gT.js → chunk-7TKQ45FW-G9TsFldk.js} +1 -1
- package/dist/web/assets/{chunk-SVP7TREG-CYXVRfc0.js → chunk-AW2ZBBNX-nmg5rsd5.js} +3 -3
- package/dist/web/assets/{chunk-GVQU2GXP-BtSmWzHA.js → chunk-DBDB3WZW-BwVIGLtu.js} +1 -1
- package/dist/web/assets/chunk-DUW6YSOI-Dgx8z5s3.js +1 -0
- package/dist/web/assets/chunk-E2ZNV5FY-VD95O25Z.js +72 -0
- package/dist/web/assets/chunk-EU5HNXII-CSnybkPb.js +213 -0
- package/dist/web/assets/chunk-FVRAUYC3-TBqluQ8N.js +2 -0
- package/dist/web/assets/{chunk-PWAF6VOD-Dup_NAkl.js → chunk-HJ2JQQFS-BiLMpVsO.js} +1 -1
- package/dist/web/assets/chunk-HTAEGDNF-QDOAuhR5.js +1 -0
- package/dist/web/assets/chunk-J5ZVWO5B-oDCd-gWO.js +1 -0
- package/dist/web/assets/{chunk-POPQ4Y6H-BrnPOTT-.js → chunk-KQW6MTUR-_WxFaX97.js} +1 -1
- package/dist/web/assets/chunk-NGNAAXSQ-BW1P8EP7.js +136 -0
- package/dist/web/assets/chunk-NTY3LDVX-BI0Pj8F6.js +1 -0
- package/dist/web/assets/chunk-VPRB5NB3-BBDlNNll.js +129 -0
- package/dist/web/assets/chunk-XC4XBNZT-Ba1ra4Jd.js +62 -0
- package/dist/web/assets/classDiagram-v2-K4WV4PDN-CksBjG_q.js +217 -0
- package/dist/web/assets/{conversationExport-CfUybHMU.js → conversationExport-q-9NUHuj.js} +1 -1
- package/dist/web/assets/cynefin-EF2NZ3EQ-ucJDz_S5.js +1 -0
- package/dist/web/assets/{cynefinDiagram-5FMLGOSQ-BKvXEDID.js → cynefinDiagram-3GCD6N5R-qPxcNdaa.js} +1 -1
- package/dist/web/assets/dagre-W4DXFKR2-ChflYJGj.js +4 -0
- package/dist/web/assets/diagram-2UJZ2QOL-Bi9ngdu2.js +200 -0
- package/dist/web/assets/{diagram-VX7I27RA-D5POkb-9.js → diagram-OVF4WLC6-iSSbF5Cd.js} +10 -10
- package/dist/web/assets/{diagram-S7CK7UJ4-DTvEAe9r.js → diagram-PFPMY2P6-BeEOD8rR.js} +2 -2
- package/dist/web/assets/{diagram-Z3DM3KII-CC2Mxm4H.js → diagram-UMYRVEAY-BckO6iZI.js} +1 -1
- package/dist/web/assets/{diagram-UQ7AKVKN-CVGEkml-.js → diagram-YEKJPTXX-BzzDIAmO.js} +2 -2
- package/dist/web/assets/diagram-ZIFT7M5P-ByjWOPbN.js +3 -0
- package/dist/web/assets/{docxExport-ErgwApAZ.js → docxExport-BO7j3Xnv.js} +1 -1
- package/dist/web/assets/{ebnfDiagram-PWID7BFC-CbDy2vxX.js → ebnfDiagram-VR2GEFS7-DRp-A5JC.js} +1 -1
- package/dist/web/assets/elk-IJKZMXRS-QzeiQ3l1.js +27 -0
- package/dist/web/assets/{erDiagram-2YWLMYGG-DUdStx-7.js → erDiagram-O2IAPWRE-BewZvI56.js} +15 -15
- package/dist/web/assets/eventmodeling-K75KTNOO-CX7X0bsf.js +1 -0
- package/dist/web/assets/flowDiagram-OXPTDLAJ-CSIHFoeR.js +1 -0
- package/dist/web/assets/ganttDiagram-R7TSEDQI-BT8Lcdwc.js +292 -0
- package/dist/web/assets/gitGraph-VSP46ZUC-BxYbaxeg.js +1 -0
- package/dist/web/assets/gitGraphDiagram-XJZIOB7I-B0fqVCqP.js +106 -0
- package/dist/web/assets/index-DcqvxkHN.css +2 -0
- package/dist/web/assets/index-eTp_lQUc.js +350 -0
- package/dist/web/assets/info-OHQRW6UA-DV3PDKXA.js +1 -0
- package/dist/web/assets/infoDiagram-5W2HQ5XZ-DfHpZ9RG.js +2 -0
- package/dist/web/assets/{ishikawaDiagram-5VMMS53U-D-gYpOUM.js → ishikawaDiagram-K3B6WC7H-DuwLwL9k.js} +2 -2
- package/dist/web/assets/{journeyDiagram-EYS64GPL-B0WqOtZ4.js → journeyDiagram-COXZFDF6-CMOfweZO.js} +4 -4
- package/dist/web/assets/{kanban-definition-UXKFOSKX-DIrVFtP3.js → kanban-definition-P3RFRI5V-DjHhlDbk.js} +9 -9
- package/dist/web/assets/{line-CuEhAU65.js → line-CGIAMPkR.js} +1 -1
- package/dist/web/assets/loadReferencedImage-DZ5eApE4.js +2 -0
- package/dist/web/assets/{mermaid-parser.core-CzCh9EE1.js → mermaid-parser.core-C18KmsD9.js} +6 -6
- package/dist/web/assets/mermaid.core-C9srNL3b.js +44 -0
- package/dist/web/assets/{mindmap-definition-THT77NOG-CBH0Z9AJ.js → mindmap-definition-LZFPQGKD-C38HXkG2.js} +24 -24
- package/dist/web/assets/packet-JDAUHWVQ-Br-8ADK6.js +1 -0
- package/dist/web/assets/{pdf-6mG9havR.js → pdf-C3f6Vjz7.js} +1 -1
- package/dist/web/assets/{pegDiagram-XKGWAZYB-BNpTWHo8.js → pegDiagram-BGZESJAR-Be49dM_b.js} +1 -1
- package/dist/web/assets/pie-XZMESJXO-68ykK6i1.js +1 -0
- package/dist/web/assets/{pieDiagram-E7YTZNPT-CZ34Q1W-.js → pieDiagram-CAPJLFHJ-DVOWjXQ_.js} +2 -2
- package/dist/web/assets/{quadrantDiagram-AXDQQJYC-C5aFQsIe.js → quadrantDiagram-GDMTTRAM-8la_R53U.js} +3 -3
- package/dist/web/assets/radar-ABXABTNO-K00ZGu13.js +1 -0
- package/dist/web/assets/railroad-I3PHUGI6-W7QuDysT.js +1 -0
- package/dist/web/assets/railroad-abnf-LNEFI6M7-DR6CNkaK.js +1 -0
- package/dist/web/assets/railroad-ebnf-DWYD2UWJ-dAhaGv5L.js +1 -0
- package/dist/web/assets/railroad-peg-JR7BVNR7-DwoiiDdE.js +1 -0
- package/dist/web/assets/{railroadDiagram-O6MQD6OU-B0ctRtRT.js → railroadDiagram-SM67HX2B-BuSjCs02.js} +1 -1
- package/dist/web/assets/{requirementDiagram-IS5BZ75X-BuOtNPGm.js → requirementDiagram-X7JNWC4A-3uq8m_5E.js} +11 -11
- package/dist/web/assets/{sankeyDiagram-P5KCCOFB-CybICPpQ.js → sankeyDiagram-UM26HJRW-BB9_G8bN.js} +3 -3
- package/dist/web/assets/sequenceDiagram-ZO4K6R2Y-CGehVq9k.js +169 -0
- package/dist/web/assets/stateDiagram-v2-TBUQTH76-CwMywh5s.js +291 -0
- package/dist/web/assets/swimlanes-N4OXWK64-CqjihurI.js +1 -0
- package/dist/web/assets/swimlanesDiagram-K3J5GTZL-Blk5ohUI.js +8 -0
- package/dist/web/assets/timeline-definition-YOQAKGHF-BtKnuY5Y.js +120 -0
- package/dist/web/assets/treeView-D4JQ5SDB-Dy4jC4wa.js +1 -0
- package/dist/web/assets/treemap-SAJKECNS-CHtGJD8P.js +1 -0
- package/dist/web/assets/usecaseDiagram-VIAY4XPW-BjnstWbR.js +328 -0
- package/dist/web/assets/vennDiagram-BLWOH2XV-o_EtJWVA.js +34 -0
- package/dist/web/assets/wardley-7MLQ67FV-BTheL3FW.js +1 -0
- package/dist/web/assets/{wardleyDiagram-VM6X3IG4-CzB2tR_t.js → wardleyDiagram-YMQ3BMBF-Bp_sv2v4.js} +3 -3
- package/dist/web/assets/xychartDiagram-TAQBALBS-C0IpEfij.js +7 -0
- package/dist/web/index.html +2 -2
- package/package.json +3 -3
- package/dist/web/assets/architecture-7GRP2DOG-BqTZwqCY.js +0 -1
- package/dist/web/assets/architectureDiagram-5GKGNRK7-BEGSAGSn.js +0 -36
- package/dist/web/assets/c4Diagram-7LVT6UL2-C6wQYxBC.js +0 -38
- package/dist/web/assets/channel-CbMG5PZq.js +0 -1
- package/dist/web/assets/chunk-3NF5O7KM-Dni31-nE.js +0 -168
- package/dist/web/assets/chunk-4HAMMTFA-hiqoLVtf.js +0 -62
- package/dist/web/assets/chunk-75Z2AOVW-1k7HRGrm.js +0 -2
- package/dist/web/assets/chunk-DU6HZSFF-Dy05V--k.js +0 -127
- package/dist/web/assets/chunk-FOHPRMQF-DHwB1DNv.js +0 -161
- package/dist/web/assets/chunk-GMAD6QVW-Bi5Ne8OE.js +0 -72
- package/dist/web/assets/chunk-HLEWEB6X-yamDqy1M.js +0 -206
- package/dist/web/assets/chunk-L3NEJ4N5-CQSamtuJ.js +0 -1
- package/dist/web/assets/chunk-OSK3NFVY-S95igUko.js +0 -10
- package/dist/web/assets/chunk-P2QGCYS3-BPor-azX.js +0 -1
- package/dist/web/assets/chunk-ZLD2IHE6-D0uZMMWb.js +0 -231
- package/dist/web/assets/classDiagram-CYGNFDIV-2Yl201cv.js +0 -1
- package/dist/web/assets/classDiagram-v2-TLXNO2FR-2Yl201cv.js +0 -1
- package/dist/web/assets/cynefin-OW5HDTMX-ua6bZIWp.js +0 -1
- package/dist/web/assets/dagre-OS7QT2EB-BRxaZdm2.js +0 -4
- package/dist/web/assets/dagre-PrKaheQc.js +0 -1
- package/dist/web/assets/diagram-VSXAHHWV-Dkh-RvzE.js +0 -3
- package/dist/web/assets/eventmodeling-NTZA5JFV-Bw8wULv_.js +0 -1
- package/dist/web/assets/flowDiagram-T62WH6J4-Dp4v9IDN.js +0 -1
- package/dist/web/assets/ganttDiagram-EL5Y4UJY-6dI1H52q.js +0 -292
- package/dist/web/assets/gitGraph-4MIJSDKK-UXnB0IFr.js +0 -1
- package/dist/web/assets/gitGraphDiagram-WWUBYQGX-B_wXPpx0.js +0 -106
- package/dist/web/assets/index-9y9n2Dul.css +0 -2
- package/dist/web/assets/index-COu8CnNa.js +0 -350
- package/dist/web/assets/info-A6RAGUB7-C2WWyNzF.js +0 -1
- package/dist/web/assets/infoDiagram-FKFFQAWI-DY65_ndC.js +0 -2
- package/dist/web/assets/loadReferencedImage-DgHMXQNZ.js +0 -2
- package/dist/web/assets/mermaid.core-BmGW_v8T.js +0 -44
- package/dist/web/assets/packet-AYTQ26CC-BYG_KViO.js +0 -1
- package/dist/web/assets/pie-WAS4IAKB-wBoUHr8R.js +0 -1
- package/dist/web/assets/radar-RG4KPBEZ-D4K5XP7X.js +0 -1
- package/dist/web/assets/railroad-74A4TZTK-Haum25Us.js +0 -1
- package/dist/web/assets/railroad-abnf-HS5TGJTU-D-kbOsoZ.js +0 -1
- package/dist/web/assets/railroad-ebnf-LZEXJU2U-CWtixpZf.js +0 -1
- package/dist/web/assets/railroad-peg-WCYAUIDC-BeY7arxf.js +0 -1
- package/dist/web/assets/sequenceDiagram-WJ2MYXX4-Dvo8sl8e.js +0 -162
- package/dist/web/assets/stateDiagram-XQSTLZYL-BcM-hGJa.js +0 -1
- package/dist/web/assets/stateDiagram-v2-IH3M54BS-hYgwFLzv.js +0 -1
- package/dist/web/assets/swimlanes-V6O3JKXN-mOOjKnlm.js +0 -1
- package/dist/web/assets/swimlanesDiagram-JKAHXJPX-C_yinM3f.js +0 -8
- package/dist/web/assets/timeline-definition-24CTP7MA-DuwMztTy.js +0 -120
- package/dist/web/assets/treeView-Q6P3EWNA-BT4vRttT.js +0 -1
- package/dist/web/assets/treemap-WGGIJYW6-Df6GHCE2.js +0 -1
- package/dist/web/assets/vennDiagram-4TSXK5OY-BbcbGn7o.js +0 -34
- package/dist/web/assets/wardley-WFR3VGLG-L_G3ydHA.js +0 -1
- package/dist/web/assets/xychartDiagram-S5SC5T6Z-CKHwJboP.js +0 -7
|
@@ -13,7 +13,10 @@ import path2 from "node:path";
|
|
|
13
13
|
var STRUCTURED_EXCHANGE_SCHEMA_V1 = "urn:structured-exchange:1";
|
|
14
14
|
var PROPOSABLE_KINDS = ["graph", "sequence"];
|
|
15
15
|
function proposableKinds(schema2) {
|
|
16
|
-
return schema2
|
|
16
|
+
return isEnrichedSchema(schema2) ? ["graph", "sequence", "table"] : PROPOSABLE_KINDS;
|
|
17
|
+
}
|
|
18
|
+
function isEnrichedSchema(schema2) {
|
|
19
|
+
return schema2 === STRUCTURED_EXCHANGE_SCHEMA_V2 || schema2 === STRUCTURED_EXCHANGE_SCHEMA_V3;
|
|
17
20
|
}
|
|
18
21
|
function readTableRow(row) {
|
|
19
22
|
if (Array.isArray(row)) return { cells: row };
|
|
@@ -95,9 +98,11 @@ var STRUCTURED_EXCHANGE_CEILINGS_2 = {
|
|
|
95
98
|
viewpointConcern: 500
|
|
96
99
|
};
|
|
97
100
|
var STRUCTURED_EXCHANGE_BYTES_CEILING_2 = 8e6;
|
|
101
|
+
var STRUCTURED_EXCHANGE_SCHEMA_V3 = "urn:structured-exchange:3";
|
|
98
102
|
var STRUCTURED_EXCHANGE_SUPPORTED_SCHEMAS = [
|
|
99
103
|
STRUCTURED_EXCHANGE_SCHEMA_V1,
|
|
100
|
-
STRUCTURED_EXCHANGE_SCHEMA_V2
|
|
104
|
+
STRUCTURED_EXCHANGE_SCHEMA_V2,
|
|
105
|
+
STRUCTURED_EXCHANGE_SCHEMA_V3
|
|
101
106
|
];
|
|
102
107
|
function supportedSchemaOf(declared) {
|
|
103
108
|
return STRUCTURED_EXCHANGE_SUPPORTED_SCHEMAS.find((supported2) => supported2 === declared);
|
|
@@ -110,7 +115,7 @@ var STRUCTURED_EXCHANGE_BYTES_CEILING_ANY = Math.max(
|
|
|
110
115
|
STRUCTURED_EXCHANGE_BYTES_CEILING_2
|
|
111
116
|
);
|
|
112
117
|
function bytesCeilingFor(declared) {
|
|
113
|
-
return declared
|
|
118
|
+
return isEnrichedSchema(declared) ? STRUCTURED_EXCHANGE_BYTES_CEILING_2 : STRUCTURED_EXCHANGE_BYTES_CEILING;
|
|
114
119
|
}
|
|
115
120
|
var utf8Bytes = (value) => new TextEncoder().encode(value).length;
|
|
116
121
|
function ceilingFor(bound) {
|
|
@@ -174,11 +179,339 @@ function measureAccepted(envelope, serialized) {
|
|
|
174
179
|
return { kind: envelope.kind, bytes: utf8Bytes(serialized), counts };
|
|
175
180
|
}
|
|
176
181
|
|
|
182
|
+
// shared/src/structuredExchangeTimeline.ts
|
|
183
|
+
var MS_PER_DAY = 864e5;
|
|
184
|
+
var CALENDAR_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
185
|
+
function dayNumber(date) {
|
|
186
|
+
const match = CALENDAR_DATE.exec(date);
|
|
187
|
+
if (match === null) return void 0;
|
|
188
|
+
const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
189
|
+
const instant = new Date(Date.UTC(year, month - 1, day));
|
|
190
|
+
instant.setUTCFullYear(year, month - 1, day);
|
|
191
|
+
if (instant.getUTCFullYear() !== year || instant.getUTCMonth() !== month - 1 || instant.getUTCDate() !== day) {
|
|
192
|
+
return void 0;
|
|
193
|
+
}
|
|
194
|
+
return Math.round(instant.getTime() / MS_PER_DAY);
|
|
195
|
+
}
|
|
196
|
+
function itemDays(item) {
|
|
197
|
+
const start = dayNumber(item.type === "activity" ? item.start : item.date);
|
|
198
|
+
const end = dayNumber(item.type === "activity" ? item.end : item.date);
|
|
199
|
+
return start === void 0 || end === void 0 ? void 0 : { start, end };
|
|
200
|
+
}
|
|
201
|
+
function timelineEndpoints(data) {
|
|
202
|
+
const endpoints = /* @__PURE__ */ new Map();
|
|
203
|
+
data.rows.forEach((row, rowIndex) => {
|
|
204
|
+
if (row.type !== "task") return;
|
|
205
|
+
if (!endpoints.has(row.id)) endpoints.set(row.id, { id: row.id, type: "task", row: rowIndex, days: taskDays(row) });
|
|
206
|
+
row.items.forEach((item, itemIndex) => {
|
|
207
|
+
if (item.id === void 0 || endpoints.has(item.id)) return;
|
|
208
|
+
endpoints.set(item.id, { id: item.id, type: item.type, row: rowIndex, item: itemIndex, days: itemDays(item) });
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
return endpoints;
|
|
212
|
+
}
|
|
213
|
+
function taskDays(task) {
|
|
214
|
+
let span;
|
|
215
|
+
for (const item of task.items) {
|
|
216
|
+
const days = itemDays(item);
|
|
217
|
+
if (days === void 0) continue;
|
|
218
|
+
span = span === void 0 ? { ...days } : { start: Math.min(span.start, days.start), end: Math.max(span.end, days.end) };
|
|
219
|
+
}
|
|
220
|
+
return span;
|
|
221
|
+
}
|
|
222
|
+
function dependencyType(dependency) {
|
|
223
|
+
return dependency.type ?? "finish-to-start";
|
|
224
|
+
}
|
|
225
|
+
var TIMELINE_TODAY_BAND = 18;
|
|
226
|
+
var TIMELINE_YEAR_BAND = 20;
|
|
227
|
+
var TIMELINE_MONTH_BAND = 20;
|
|
228
|
+
var TIMELINE_HEADER_HEIGHT = TIMELINE_TODAY_BAND + TIMELINE_YEAR_BAND + TIMELINE_MONTH_BAND;
|
|
229
|
+
|
|
230
|
+
// shared/src/structuredExchangeTimelineValidation.ts
|
|
231
|
+
function timelineIssues(data) {
|
|
232
|
+
const issues = [];
|
|
233
|
+
const day = (value, at) => {
|
|
234
|
+
const found = dayNumber(value);
|
|
235
|
+
if (found === void 0) {
|
|
236
|
+
issues.push({ rule: "invalid-date", path: at, message: `"${value}" is not a day of the calendar` });
|
|
237
|
+
}
|
|
238
|
+
return found;
|
|
239
|
+
};
|
|
240
|
+
const rangeStart = day(data.time.start, "/data/time/start");
|
|
241
|
+
const rangeEnd = day(data.time.end, "/data/time/end");
|
|
242
|
+
const range = rangeStart !== void 0 && rangeEnd !== void 0 && rangeStart <= rangeEnd ? { start: rangeStart, end: rangeEnd } : void 0;
|
|
243
|
+
if (rangeStart !== void 0 && rangeEnd !== void 0 && rangeStart > rangeEnd) {
|
|
244
|
+
issues.push({
|
|
245
|
+
rule: "inverted-range",
|
|
246
|
+
path: "/data/time",
|
|
247
|
+
message: `the timeline starts on ${data.time.start}, after it ends on ${data.time.end}`
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
const declaredRange = `${data.time.start} to ${data.time.end}`;
|
|
251
|
+
const seen = /* @__PURE__ */ new Map();
|
|
252
|
+
const identify = (id, at) => {
|
|
253
|
+
if (id === void 0) return;
|
|
254
|
+
const first = seen.get(id);
|
|
255
|
+
if (first === void 0) seen.set(id, at);
|
|
256
|
+
else {
|
|
257
|
+
issues.push({
|
|
258
|
+
rule: "duplicate-identifier",
|
|
259
|
+
path: `${at}/id`,
|
|
260
|
+
message: `identifier "${id}" is already declared at ${first}`
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
const compared = data.comparedTo !== void 0;
|
|
265
|
+
if (data.comparedTo?.date !== void 0) day(data.comparedTo.date, "/data/comparedTo/date");
|
|
266
|
+
const withoutReference = (at) => issues.push({
|
|
267
|
+
rule: "comparison-without-reference",
|
|
268
|
+
path: at,
|
|
269
|
+
message: "previous dates and change roles describe a comparison; declare `comparedTo` naming the plan they compare with"
|
|
270
|
+
});
|
|
271
|
+
const kinds = /* @__PURE__ */ new Set();
|
|
272
|
+
data.rows.forEach((row, rowIndex) => {
|
|
273
|
+
if (row.type !== "task") return;
|
|
274
|
+
const rowAt = `/data/rows/${rowIndex}`;
|
|
275
|
+
identify(row.id, rowAt);
|
|
276
|
+
if (row.role !== void 0 && !compared) withoutReference(`${rowAt}/role`);
|
|
277
|
+
row.items.forEach((item, itemIndex) => {
|
|
278
|
+
const at = `${rowAt}/items/${itemIndex}`;
|
|
279
|
+
identify(item.id, at);
|
|
280
|
+
if (item.kind !== void 0) kinds.add(item.kind);
|
|
281
|
+
if (item.role !== void 0 && !compared) withoutReference(`${at}/role`);
|
|
282
|
+
if (item.previous !== void 0) {
|
|
283
|
+
if (!compared) withoutReference(`${at}/previous`);
|
|
284
|
+
if (item.role !== void 0 || row.role !== void 0) {
|
|
285
|
+
issues.push({
|
|
286
|
+
rule: "contradictory-change",
|
|
287
|
+
path: `${at}/previous`,
|
|
288
|
+
message: `an item that is ${item.role ?? `in a task that is ${row.role}`} has no previous dates; it is new or dropped, not moved`
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
const previous = item.previous;
|
|
292
|
+
const before = item.type === "activity" ? { first: day(previous.start, `${at}/previous/start`), last: day(previous.end, `${at}/previous/end`) } : (() => {
|
|
293
|
+
const only = day(previous.date, `${at}/previous/date`);
|
|
294
|
+
return { first: only, last: only };
|
|
295
|
+
})();
|
|
296
|
+
if (before.first !== void 0 && before.last !== void 0) {
|
|
297
|
+
if (before.first > before.last) {
|
|
298
|
+
issues.push({ rule: "inverted-range", path: `${at}/previous`, message: `the previous dates start on ${previous.start}, after they end on ${previous.end}` });
|
|
299
|
+
} else if (range !== void 0 && (before.first < range.start || before.last > range.end)) {
|
|
300
|
+
issues.push({
|
|
301
|
+
rule: "item-outside-range",
|
|
302
|
+
path: `${at}/previous`,
|
|
303
|
+
message: `the previous dates fall outside the timeline's range ${declaredRange}; the range covers both plans, so widen \`time\``
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (item.role !== void 0 && row.role !== void 0 && item.role !== row.role) {
|
|
309
|
+
issues.push({
|
|
310
|
+
rule: "contradictory-change",
|
|
311
|
+
path: `${at}/role`,
|
|
312
|
+
message: `an item ${item.role} in a task that is ${row.role}`
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
let first;
|
|
316
|
+
let last;
|
|
317
|
+
if (item.type === "activity") {
|
|
318
|
+
first = day(item.start, `${at}/start`);
|
|
319
|
+
last = day(item.end, `${at}/end`);
|
|
320
|
+
if (first !== void 0 && last !== void 0 && first > last) {
|
|
321
|
+
issues.push({
|
|
322
|
+
rule: "inverted-range",
|
|
323
|
+
path: at,
|
|
324
|
+
message: `the activity starts on ${item.start}, after it ends on ${item.end}`
|
|
325
|
+
});
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
} else {
|
|
329
|
+
first = last = day(item.date, `${at}/date`);
|
|
330
|
+
}
|
|
331
|
+
if (range === void 0 || first === void 0 || last === void 0) return;
|
|
332
|
+
if (first < range.start || last > range.end) {
|
|
333
|
+
issues.push({
|
|
334
|
+
rule: "item-outside-range",
|
|
335
|
+
path: at,
|
|
336
|
+
message: item.type === "activity" ? `the activity runs ${item.start} to ${item.end}, outside the timeline's range ${declaredRange}; widen \`time\` or move the activity` : `the milestone falls on ${item.date}, outside the timeline's range ${declaredRange}; widen \`time\` or move the milestone`
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
(data.periods ?? []).forEach((period, index3) => {
|
|
342
|
+
const at = `/data/periods/${index3}`;
|
|
343
|
+
if (period.kind !== void 0) kinds.add(period.kind);
|
|
344
|
+
const first = day(period.start, `${at}/start`);
|
|
345
|
+
const last = day(period.end, `${at}/end`);
|
|
346
|
+
if (first === void 0 || last === void 0) return;
|
|
347
|
+
if (first > last) {
|
|
348
|
+
issues.push({ rule: "inverted-range", path: at, message: `the period starts on ${period.start}, after it ends on ${period.end}` });
|
|
349
|
+
} else if (range !== void 0 && (last < range.start || first > range.end)) {
|
|
350
|
+
issues.push({
|
|
351
|
+
rule: "period-outside-range",
|
|
352
|
+
path: at,
|
|
353
|
+
message: `the period ${period.start} to ${period.end} lies wholly outside the timeline's range ${declaredRange}, so nothing of it could be drawn`
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
(data.references ?? []).forEach((reference, index3) => {
|
|
358
|
+
const at = `/data/references/${index3}`;
|
|
359
|
+
if (reference.kind !== void 0) kinds.add(reference.kind);
|
|
360
|
+
const only = day(reference.date, `${at}/date`);
|
|
361
|
+
if (only !== void 0 && range !== void 0 && (only < range.start || only > range.end)) {
|
|
362
|
+
issues.push({
|
|
363
|
+
rule: "item-outside-range",
|
|
364
|
+
path: at,
|
|
365
|
+
message: `the reference date ${reference.date} is outside the timeline's range ${declaredRange}; widen \`time\` or move it`
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
if (kinds.size > STRUCTURED_EXCHANGE_CEILINGS.kindsPerVocabulary) {
|
|
370
|
+
issues.push({
|
|
371
|
+
rule: "too-many-kinds",
|
|
372
|
+
path: "/data/rows",
|
|
373
|
+
message: `${kinds.size} distinct item types, and no more than ${STRUCTURED_EXCHANGE_CEILINGS.kindsPerVocabulary} can be told apart in a rendering`,
|
|
374
|
+
observed: kinds.size,
|
|
375
|
+
limit: STRUCTURED_EXCHANGE_CEILINGS.kindsPerVocabulary
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
issues.push(...dependencyIssues(data, timelineEndpoints(data)));
|
|
379
|
+
issues.push(...removedDependencyIssues(data));
|
|
380
|
+
return issues;
|
|
381
|
+
}
|
|
382
|
+
function removedDependencyIssues(data) {
|
|
383
|
+
const removed = /* @__PURE__ */ new Set();
|
|
384
|
+
for (const row of data.rows) {
|
|
385
|
+
if (row.type !== "task") continue;
|
|
386
|
+
if (row.role === "removed") removed.add(row.id);
|
|
387
|
+
for (const item of row.items) {
|
|
388
|
+
if (item.id !== void 0 && (item.role === "removed" || row.role === "removed")) removed.add(item.id);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
const issues = [];
|
|
392
|
+
(data.dependencies ?? []).forEach((dependency, index3) => {
|
|
393
|
+
for (const side of ["from", "to"]) {
|
|
394
|
+
if (removed.has(dependency[side])) {
|
|
395
|
+
issues.push({
|
|
396
|
+
rule: "dependency-on-removed",
|
|
397
|
+
path: `/data/dependencies/${index3}/${side}`,
|
|
398
|
+
message: `"${dependency[side]}" was dropped from the plan, so nothing can depend on it any more; remove the dependency`
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
return issues;
|
|
404
|
+
}
|
|
405
|
+
function dependencyIssues(data, endpoints) {
|
|
406
|
+
const issues = [];
|
|
407
|
+
const dependencies = data.dependencies ?? [];
|
|
408
|
+
const usable = [];
|
|
409
|
+
const declared = /* @__PURE__ */ new Map();
|
|
410
|
+
dependencies.forEach((dependency, index3) => {
|
|
411
|
+
const at = `/data/dependencies/${index3}`;
|
|
412
|
+
let resolved = true;
|
|
413
|
+
for (const side of ["from", "to"]) {
|
|
414
|
+
const named = dependency[side];
|
|
415
|
+
const endpoint = endpoints.get(named);
|
|
416
|
+
if (endpoint === void 0) {
|
|
417
|
+
resolved = false;
|
|
418
|
+
issues.push({
|
|
419
|
+
rule: "unresolved-endpoint",
|
|
420
|
+
path: `${at}/${side}`,
|
|
421
|
+
message: `"${named}" is not the identifier of any task or item this timeline declares`
|
|
422
|
+
});
|
|
423
|
+
} else if (endpoint.type === "task" && endpoint.days === void 0) {
|
|
424
|
+
resolved = false;
|
|
425
|
+
const task = data.rows[endpoint.row];
|
|
426
|
+
if (task.type === "task" && task.items.length > 0) continue;
|
|
427
|
+
issues.push({
|
|
428
|
+
rule: "empty-task-endpoint",
|
|
429
|
+
path: `${at}/${side}`,
|
|
430
|
+
message: `task "${named}" holds no item, so it has no start or finish for a dependency to link`
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
if (!resolved) return;
|
|
435
|
+
const from = endpoints.get(dependency.from);
|
|
436
|
+
const to = endpoints.get(dependency.to);
|
|
437
|
+
const contains = (outer, inner) => outer.type === "task" && inner.type !== "task" && inner.row === outer.row;
|
|
438
|
+
if (from.id === to.id || contains(from, to) || contains(to, from)) {
|
|
439
|
+
issues.push({
|
|
440
|
+
rule: "self-dependency",
|
|
441
|
+
path: at,
|
|
442
|
+
message: from.id === to.id ? `"${from.id}" cannot depend on itself` : `a task and one of its own items cannot depend on each other: the task's span is made of its items`
|
|
443
|
+
});
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const key = JSON.stringify([dependency.from, dependency.to, dependencyType(dependency)]);
|
|
447
|
+
const first = declared.get(key);
|
|
448
|
+
if (first !== void 0) {
|
|
449
|
+
issues.push({
|
|
450
|
+
rule: "duplicate-dependency",
|
|
451
|
+
path: at,
|
|
452
|
+
message: `the same dependency is already declared at /data/dependencies/${first}`
|
|
453
|
+
});
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
declared.set(key, index3);
|
|
457
|
+
usable.push({ from: dependency.from, to: dependency.to, index: index3 });
|
|
458
|
+
});
|
|
459
|
+
const cycle = findCycle(usable);
|
|
460
|
+
if (cycle !== void 0) {
|
|
461
|
+
issues.push({
|
|
462
|
+
rule: "dependency-cycle",
|
|
463
|
+
path: `/data/dependencies/${cycle.index}`,
|
|
464
|
+
message: `dependencies form a cycle, which no dates can honour: ${cycle.ids.join(" \u2192 ")}`
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
return issues;
|
|
468
|
+
}
|
|
469
|
+
function findCycle(edges) {
|
|
470
|
+
const outgoing = /* @__PURE__ */ new Map();
|
|
471
|
+
for (const edge of edges) {
|
|
472
|
+
const list = outgoing.get(edge.from) ?? [];
|
|
473
|
+
list.push({ to: edge.to, index: edge.index });
|
|
474
|
+
outgoing.set(edge.from, list);
|
|
475
|
+
}
|
|
476
|
+
const state2 = /* @__PURE__ */ new Map();
|
|
477
|
+
const path3 = [];
|
|
478
|
+
for (const root of outgoing.keys()) {
|
|
479
|
+
if (state2.has(root)) continue;
|
|
480
|
+
const stack = [{ id: root, next: 0 }];
|
|
481
|
+
state2.set(root, "open");
|
|
482
|
+
path3.push({ id: root, index: -1 });
|
|
483
|
+
while (stack.length > 0) {
|
|
484
|
+
const frame = stack[stack.length - 1];
|
|
485
|
+
const edgesOut = outgoing.get(frame.id) ?? [];
|
|
486
|
+
if (frame.next >= edgesOut.length) {
|
|
487
|
+
state2.set(frame.id, "done");
|
|
488
|
+
stack.pop();
|
|
489
|
+
path3.pop();
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
const edge = edgesOut[frame.next++];
|
|
493
|
+
const seen = state2.get(edge.to);
|
|
494
|
+
if (seen === "open") {
|
|
495
|
+
const start = path3.findIndex((step) => step.id === edge.to);
|
|
496
|
+
const ids = [...path3.slice(start).map((step) => step.id), edge.to];
|
|
497
|
+
return { ids, index: edge.index };
|
|
498
|
+
}
|
|
499
|
+
if (seen === void 0) {
|
|
500
|
+
state2.set(edge.to, "open");
|
|
501
|
+
stack.push({ id: edge.to, next: 0 });
|
|
502
|
+
path3.push({ id: edge.to, index: edge.index });
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return void 0;
|
|
507
|
+
}
|
|
508
|
+
|
|
177
509
|
// shared/src/structuredExchangeValidation.ts
|
|
178
510
|
function dataMatchesKind(envelope) {
|
|
179
511
|
const data = envelope.data;
|
|
180
512
|
if (envelope.kind === "graph") return Array.isArray(data.nodes) && Array.isArray(data.edges);
|
|
181
513
|
if (envelope.kind === "sequence") return Array.isArray(data.participants) && Array.isArray(data.messages);
|
|
514
|
+
if (envelope.kind === "timeline") return typeof data.time === "object" && data.time !== null && Array.isArray(data.rows);
|
|
182
515
|
return Array.isArray(data.columns) && Array.isArray(data.rows);
|
|
183
516
|
}
|
|
184
517
|
function elementsOf(envelope) {
|
|
@@ -203,6 +536,7 @@ function relationshipsPointer(envelope) {
|
|
|
203
536
|
return envelope.kind === "graph" ? "/data/edges" : "/data/messages";
|
|
204
537
|
}
|
|
205
538
|
function enrichedItemsOf(envelope) {
|
|
539
|
+
if (envelope.kind === "timeline") return [];
|
|
206
540
|
const data = envelope.data;
|
|
207
541
|
const items = [];
|
|
208
542
|
for (const collection of ["nodes", "edges", "participants", "messages", "rows", "relations"]) {
|
|
@@ -254,6 +588,12 @@ function rowRelationsOf(envelope) {
|
|
|
254
588
|
const relations = envelope.data.relations;
|
|
255
589
|
return Array.isArray(relations) ? relations : [];
|
|
256
590
|
}
|
|
591
|
+
function notProposable(kind, consequence) {
|
|
592
|
+
if (kind === "timeline") {
|
|
593
|
+
return `a timeline is maintained by presenting the revised timeline again, not proposed as a change, ${consequence}`;
|
|
594
|
+
}
|
|
595
|
+
return `a ${kind} is a projection and cannot be proposed, ${consequence}`;
|
|
596
|
+
}
|
|
257
597
|
function validateStructuredExchangeSemantics(envelope) {
|
|
258
598
|
const issues = [];
|
|
259
599
|
if (!dataMatchesKind(envelope)) {
|
|
@@ -269,7 +609,7 @@ function validateStructuredExchangeSemantics(envelope) {
|
|
|
269
609
|
issues.push({
|
|
270
610
|
rule: "kind-not-proposable",
|
|
271
611
|
path: "/target",
|
|
272
|
-
message:
|
|
612
|
+
message: notProposable(envelope.kind, "so it carries no target")
|
|
273
613
|
});
|
|
274
614
|
}
|
|
275
615
|
if (envelope.removals !== void 0) {
|
|
@@ -277,7 +617,7 @@ function validateStructuredExchangeSemantics(envelope) {
|
|
|
277
617
|
issues.push({
|
|
278
618
|
rule: "kind-not-proposable",
|
|
279
619
|
path: "/removals",
|
|
280
|
-
message:
|
|
620
|
+
message: notProposable(envelope.kind, "so it declares no removals")
|
|
281
621
|
});
|
|
282
622
|
} else if (envelope.target === void 0) {
|
|
283
623
|
issues.push({
|
|
@@ -338,15 +678,15 @@ function validateStructuredExchangeSemantics(envelope) {
|
|
|
338
678
|
}
|
|
339
679
|
});
|
|
340
680
|
const claimed = /* @__PURE__ */ new Map();
|
|
341
|
-
const claim = (type, ref,
|
|
681
|
+
const claim = (type, ref, at) => {
|
|
342
682
|
if (ref === void 0) return;
|
|
343
683
|
const key = `${type}:${ref}`;
|
|
344
684
|
const first = claimed.get(key);
|
|
345
|
-
if (first === void 0) claimed.set(key,
|
|
685
|
+
if (first === void 0) claimed.set(key, at);
|
|
346
686
|
else {
|
|
347
687
|
issues.push({
|
|
348
688
|
rule: "duplicate-reference",
|
|
349
|
-
path:
|
|
689
|
+
path: at,
|
|
350
690
|
message: `${type} "${ref}" is already addressed at ${first}; a proposal states one intention per thing`
|
|
351
691
|
});
|
|
352
692
|
}
|
|
@@ -376,7 +716,7 @@ function validateStructuredExchangeSemantics(envelope) {
|
|
|
376
716
|
issues.push({
|
|
377
717
|
rule: "kind-not-proposable",
|
|
378
718
|
path: `${candidate.at}/set`,
|
|
379
|
-
message:
|
|
719
|
+
message: notProposable(envelope.kind, "so nothing in it declares a change")
|
|
380
720
|
});
|
|
381
721
|
} else if (envelope.target === void 0) {
|
|
382
722
|
issues.push({
|
|
@@ -399,11 +739,11 @@ function validateStructuredExchangeSemantics(envelope) {
|
|
|
399
739
|
countKinds(relationshipsOf(envelope))
|
|
400
740
|
]
|
|
401
741
|
];
|
|
402
|
-
for (const [noun,
|
|
742
|
+
for (const [noun, at, kinds] of vocabularies) {
|
|
403
743
|
if (kinds.size > STRUCTURED_EXCHANGE_CEILINGS.kindsPerVocabulary) {
|
|
404
744
|
issues.push({
|
|
405
745
|
rule: "too-many-kinds",
|
|
406
|
-
path:
|
|
746
|
+
path: at,
|
|
407
747
|
message: `${kinds.size} distinct ${noun} types, and no more than ${STRUCTURED_EXCHANGE_CEILINGS.kindsPerVocabulary} can be told apart in a rendering`,
|
|
408
748
|
observed: kinds.size,
|
|
409
749
|
limit: STRUCTURED_EXCHANGE_CEILINGS.kindsPerVocabulary
|
|
@@ -425,21 +765,21 @@ function validateStructuredExchangeSemantics(envelope) {
|
|
|
425
765
|
);
|
|
426
766
|
const seenViewpoints = /* @__PURE__ */ new Map();
|
|
427
767
|
viewpoints.forEach((viewpoint, index3) => {
|
|
428
|
-
const
|
|
768
|
+
const at = `/viewpoints/${index3}`;
|
|
429
769
|
const { id, elementKinds: retainedElements, relationshipKinds: retainedRelationships } = viewpoint;
|
|
430
770
|
const first = seenViewpoints.get(id);
|
|
431
771
|
if (first === void 0) seenViewpoints.set(id, index3);
|
|
432
772
|
else {
|
|
433
773
|
issues.push({
|
|
434
774
|
rule: "duplicate-viewpoint-identifier",
|
|
435
|
-
path: `${
|
|
775
|
+
path: `${at}/id`,
|
|
436
776
|
message: `viewpoint "${id}" is already declared at /viewpoints/${first}`
|
|
437
777
|
});
|
|
438
778
|
}
|
|
439
779
|
if (retainedElements === void 0 && retainedRelationships === void 0) {
|
|
440
780
|
issues.push({
|
|
441
781
|
rule: "empty-viewpoint",
|
|
442
|
-
path:
|
|
782
|
+
path: at,
|
|
443
783
|
message: `viewpoint "${id}" retains no kind, so it would show nothing it was not already showing; name elementKinds, relationshipKinds, or both`
|
|
444
784
|
});
|
|
445
785
|
}
|
|
@@ -452,7 +792,7 @@ function validateStructuredExchangeSemantics(envelope) {
|
|
|
452
792
|
if (present.has(kind)) return;
|
|
453
793
|
issues.push({
|
|
454
794
|
rule: "unresolved-viewpoint-kind",
|
|
455
|
-
path: `${
|
|
795
|
+
path: `${at}/${list}/${position}`,
|
|
456
796
|
message: `viewpoint "${id}" retains ${noun} kind "${kind}", and no ${noun} of this document has it` + (other.has(kind) ? ` (it is a ${otherNoun} kind here, which is a different vocabulary)` : "")
|
|
457
797
|
});
|
|
458
798
|
});
|
|
@@ -476,6 +816,7 @@ function validateStructuredExchangeSemantics(envelope) {
|
|
|
476
816
|
}
|
|
477
817
|
});
|
|
478
818
|
}
|
|
819
|
+
if (envelope.kind === "timeline") issues.push(...timelineIssues(envelope.data));
|
|
479
820
|
for (const item of enrichedItemsOf(envelope)) {
|
|
480
821
|
if (item.expect !== void 0) {
|
|
481
822
|
if (envelope.target === void 0) {
|
|
@@ -9728,127 +10069,1452 @@ var structured_exchange_2_default = {
|
|
|
9728
10069
|
}
|
|
9729
10070
|
};
|
|
9730
10071
|
|
|
9731
|
-
// shared/
|
|
9732
|
-
var
|
|
9733
|
-
|
|
9734
|
-
|
|
9735
|
-
|
|
9736
|
-
|
|
9737
|
-
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9743
|
-
|
|
9744
|
-
|
|
9745
|
-
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
|
|
9749
|
-
|
|
9750
|
-
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
}
|
|
9777
|
-
function observedFor(keyword, value) {
|
|
9778
|
-
if (typeof value === "string" && (keyword === "maxLength" || keyword === "minLength")) return value.length;
|
|
9779
|
-
if (Array.isArray(value) && (keyword === "maxItems" || keyword === "minItems")) return value.length;
|
|
9780
|
-
return void 0;
|
|
9781
|
-
}
|
|
9782
|
-
function at(document, pointer) {
|
|
9783
|
-
if (pointer === "") return document;
|
|
9784
|
-
let current = document;
|
|
9785
|
-
for (const rawSegment of pointer.slice(1).split("/")) {
|
|
9786
|
-
if (current === null || typeof current !== "object") return void 0;
|
|
9787
|
-
const segment4 = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
9788
|
-
current = current[segment4];
|
|
9789
|
-
}
|
|
9790
|
-
return current;
|
|
9791
|
-
}
|
|
9792
|
-
var checkStructuredExchangeSchema = (document) => {
|
|
9793
|
-
const declared = declaredSchemaOf(document);
|
|
9794
|
-
const version = supportedSchemaOf(declared);
|
|
9795
|
-
if (version === void 0 && declared !== void 0) {
|
|
9796
|
-
return [
|
|
9797
|
-
{
|
|
9798
|
-
rule: "unsupported-version",
|
|
9799
|
-
path: "/schema",
|
|
9800
|
-
message: `this build validates ${STRUCTURED_EXCHANGE_SUPPORTED_SCHEMAS.join(" and ")}`
|
|
10072
|
+
// shared/schemas/structured-exchange-3.json
|
|
10073
|
+
var structured_exchange_3_default = {
|
|
10074
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
10075
|
+
$id: "urn:structured-exchange:3",
|
|
10076
|
+
title: "Structured exchange envelope v3",
|
|
10077
|
+
description: "Version 2 plus one kind, the timeline. Every version 2 construct keeps its definition, so a version 2 document means the same thing once its identifier is changed to this one.",
|
|
10078
|
+
type: "object",
|
|
10079
|
+
additionalProperties: false,
|
|
10080
|
+
required: [
|
|
10081
|
+
"schema",
|
|
10082
|
+
"kind",
|
|
10083
|
+
"data"
|
|
10084
|
+
],
|
|
10085
|
+
$defs: {
|
|
10086
|
+
ref: {
|
|
10087
|
+
type: "string",
|
|
10088
|
+
minLength: 1,
|
|
10089
|
+
maxLength: 200
|
|
10090
|
+
},
|
|
10091
|
+
localId: {
|
|
10092
|
+
type: "string",
|
|
10093
|
+
minLength: 1,
|
|
10094
|
+
maxLength: 200
|
|
10095
|
+
},
|
|
10096
|
+
label: {
|
|
10097
|
+
type: "string",
|
|
10098
|
+
maxLength: 500
|
|
10099
|
+
},
|
|
10100
|
+
kind: {
|
|
10101
|
+
description: "The producing tool's type or stereotype for this thing \u2014 'block', 'sensor', 'requirement', 'power'. Free text, because the vocabulary belongs to the domain and not to this contract; a profile names which domain owns it.",
|
|
10102
|
+
type: "string",
|
|
10103
|
+
minLength: 1,
|
|
10104
|
+
maxLength: 100
|
|
10105
|
+
},
|
|
10106
|
+
reference: {
|
|
10107
|
+
description: "Something owned elsewhere, named by the identifier its authority knows it by. Opaque: never parsed, resolved or fetched.",
|
|
10108
|
+
type: "object",
|
|
10109
|
+
additionalProperties: false,
|
|
10110
|
+
required: [
|
|
10111
|
+
"ref"
|
|
10112
|
+
],
|
|
10113
|
+
properties: {
|
|
10114
|
+
ref: {
|
|
10115
|
+
$ref: "#/$defs/ref"
|
|
10116
|
+
}
|
|
9801
10117
|
}
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
10118
|
+
},
|
|
10119
|
+
attributeScalar: {
|
|
10120
|
+
type: [
|
|
10121
|
+
"string",
|
|
10122
|
+
"number",
|
|
10123
|
+
"boolean",
|
|
10124
|
+
"null"
|
|
10125
|
+
],
|
|
10126
|
+
maxLength: 1e3
|
|
10127
|
+
},
|
|
10128
|
+
attributeValue: {
|
|
10129
|
+
description: "A scalar, an opaque reference, or one flat list of those. Lists never nest and no other object shape is allowed: recursive values would weaken size analysis, generic rendering and deterministic comparison.",
|
|
10130
|
+
oneOf: [
|
|
10131
|
+
{
|
|
10132
|
+
$ref: "#/$defs/attributeScalar"
|
|
10133
|
+
},
|
|
10134
|
+
{
|
|
10135
|
+
$ref: "#/$defs/reference"
|
|
10136
|
+
},
|
|
10137
|
+
{
|
|
10138
|
+
type: "array",
|
|
10139
|
+
maxItems: 50,
|
|
10140
|
+
items: {
|
|
10141
|
+
oneOf: [
|
|
10142
|
+
{
|
|
10143
|
+
$ref: "#/$defs/attributeScalar"
|
|
10144
|
+
},
|
|
10145
|
+
{
|
|
10146
|
+
$ref: "#/$defs/reference"
|
|
10147
|
+
}
|
|
10148
|
+
]
|
|
10149
|
+
}
|
|
10150
|
+
}
|
|
10151
|
+
]
|
|
10152
|
+
},
|
|
10153
|
+
attributes: {
|
|
10154
|
+
description: "Domain-owned properties of this item. Names belong to the profile's vocabulary; this contract bounds them and reads none of them.",
|
|
10155
|
+
type: "object",
|
|
10156
|
+
maxProperties: 50,
|
|
10157
|
+
propertyNames: {
|
|
10158
|
+
minLength: 1,
|
|
10159
|
+
maxLength: 200
|
|
10160
|
+
},
|
|
10161
|
+
additionalProperties: {
|
|
10162
|
+
$ref: "#/$defs/attributeValue"
|
|
10163
|
+
}
|
|
10164
|
+
},
|
|
10165
|
+
removeAttributes: {
|
|
10166
|
+
description: "Attribute names this proposal takes away. Deletion is explicit because null is an ordinary value: a producer that means 'unset' says so here.",
|
|
10167
|
+
type: "array",
|
|
10168
|
+
maxItems: 50,
|
|
10169
|
+
items: {
|
|
10170
|
+
$ref: "#/$defs/localId"
|
|
10171
|
+
}
|
|
10172
|
+
},
|
|
10173
|
+
revision: {
|
|
10174
|
+
description: "The revision an authority knows its state by. Opaque: compared by the authority, never interpreted here.",
|
|
10175
|
+
type: "string",
|
|
10176
|
+
minLength: 1,
|
|
10177
|
+
maxLength: 200
|
|
10178
|
+
},
|
|
10179
|
+
position: {
|
|
10180
|
+
type: "integer",
|
|
10181
|
+
minimum: 0,
|
|
10182
|
+
maximum: 1e6
|
|
10183
|
+
},
|
|
10184
|
+
location: {
|
|
10185
|
+
description: "Where this item can be found, as a hint for a reader. Never an identity: locations take no part in endpoint resolution, duplicate detection, or what a proposal addresses, and moving the thing does not change what it is.",
|
|
10186
|
+
type: "object",
|
|
10187
|
+
additionalProperties: false,
|
|
10188
|
+
required: [
|
|
10189
|
+
"uri"
|
|
10190
|
+
],
|
|
10191
|
+
properties: {
|
|
10192
|
+
uri: {
|
|
10193
|
+
type: "string",
|
|
10194
|
+
minLength: 1,
|
|
10195
|
+
maxLength: 2e3
|
|
10196
|
+
},
|
|
10197
|
+
revision: {
|
|
10198
|
+
$ref: "#/$defs/revision"
|
|
10199
|
+
},
|
|
10200
|
+
range: {
|
|
10201
|
+
type: "object",
|
|
10202
|
+
additionalProperties: false,
|
|
10203
|
+
required: [
|
|
10204
|
+
"startLine",
|
|
10205
|
+
"endLine"
|
|
10206
|
+
],
|
|
10207
|
+
description: "A zero-based range inside the resource. Ordering is checked after the schema, which cannot conveniently compare two positions.",
|
|
10208
|
+
properties: {
|
|
10209
|
+
startLine: {
|
|
10210
|
+
$ref: "#/$defs/position"
|
|
10211
|
+
},
|
|
10212
|
+
startCharacter: {
|
|
10213
|
+
$ref: "#/$defs/position"
|
|
10214
|
+
},
|
|
10215
|
+
endLine: {
|
|
10216
|
+
$ref: "#/$defs/position"
|
|
10217
|
+
},
|
|
10218
|
+
endCharacter: {
|
|
10219
|
+
$ref: "#/$defs/position"
|
|
10220
|
+
}
|
|
10221
|
+
}
|
|
10222
|
+
}
|
|
10223
|
+
}
|
|
10224
|
+
},
|
|
10225
|
+
locations: {
|
|
10226
|
+
type: "array",
|
|
10227
|
+
maxItems: 10,
|
|
10228
|
+
items: {
|
|
10229
|
+
$ref: "#/$defs/location"
|
|
10230
|
+
}
|
|
10231
|
+
},
|
|
10232
|
+
artifact: {
|
|
10233
|
+
description: "A related artifact \u2014 an implementation, a report, a piece of evidence \u2014 named rather than carried. The digest is mandatory so an approval refers to stable bytes even when the URI is not: nothing here is retrieved by validation or by rendering.",
|
|
10234
|
+
type: "object",
|
|
10235
|
+
additionalProperties: false,
|
|
10236
|
+
required: [
|
|
10237
|
+
"rel",
|
|
10238
|
+
"uri",
|
|
10239
|
+
"sha256"
|
|
10240
|
+
],
|
|
10241
|
+
properties: {
|
|
10242
|
+
rel: {
|
|
10243
|
+
type: "string",
|
|
10244
|
+
minLength: 1,
|
|
10245
|
+
maxLength: 100
|
|
10246
|
+
},
|
|
10247
|
+
uri: {
|
|
10248
|
+
type: "string",
|
|
10249
|
+
minLength: 1,
|
|
10250
|
+
maxLength: 2e3
|
|
10251
|
+
},
|
|
10252
|
+
sha256: {
|
|
10253
|
+
type: "string",
|
|
10254
|
+
pattern: "^sha256:[0-9a-f]{64}$"
|
|
10255
|
+
},
|
|
10256
|
+
mediaType: {
|
|
10257
|
+
type: "string",
|
|
10258
|
+
minLength: 1,
|
|
10259
|
+
maxLength: 100
|
|
10260
|
+
},
|
|
10261
|
+
label: {
|
|
10262
|
+
$ref: "#/$defs/label"
|
|
10263
|
+
}
|
|
10264
|
+
}
|
|
10265
|
+
},
|
|
10266
|
+
artifacts: {
|
|
10267
|
+
type: "array",
|
|
10268
|
+
maxItems: 20,
|
|
10269
|
+
items: {
|
|
10270
|
+
$ref: "#/$defs/artifact"
|
|
10271
|
+
}
|
|
10272
|
+
},
|
|
10273
|
+
expect: {
|
|
10274
|
+
description: "What the producer believes is true of this item right now. A declaration for the receiving authority to check immediately before applying, never a claim this application has established.",
|
|
10275
|
+
type: "object",
|
|
10276
|
+
additionalProperties: false,
|
|
10277
|
+
minProperties: 1,
|
|
10278
|
+
properties: {
|
|
10279
|
+
label: {
|
|
10280
|
+
$ref: "#/$defs/label"
|
|
10281
|
+
},
|
|
10282
|
+
kind: {
|
|
10283
|
+
$ref: "#/$defs/kind"
|
|
10284
|
+
},
|
|
10285
|
+
container: {
|
|
10286
|
+
$ref: "#/$defs/localId"
|
|
10287
|
+
},
|
|
10288
|
+
revision: {
|
|
10289
|
+
$ref: "#/$defs/revision"
|
|
10290
|
+
},
|
|
10291
|
+
attributes: {
|
|
10292
|
+
$ref: "#/$defs/attributes"
|
|
10293
|
+
}
|
|
10294
|
+
}
|
|
10295
|
+
},
|
|
10296
|
+
elementChange: {
|
|
10297
|
+
type: "object",
|
|
10298
|
+
additionalProperties: false,
|
|
10299
|
+
minProperties: 1,
|
|
10300
|
+
properties: {
|
|
10301
|
+
label: {
|
|
10302
|
+
$ref: "#/$defs/label"
|
|
10303
|
+
},
|
|
10304
|
+
kind: {
|
|
10305
|
+
$ref: "#/$defs/kind"
|
|
10306
|
+
},
|
|
10307
|
+
container: {
|
|
10308
|
+
$ref: "#/$defs/localId"
|
|
10309
|
+
},
|
|
10310
|
+
attributes: {
|
|
10311
|
+
$ref: "#/$defs/attributes"
|
|
10312
|
+
},
|
|
10313
|
+
removeAttributes: {
|
|
10314
|
+
$ref: "#/$defs/removeAttributes"
|
|
10315
|
+
}
|
|
10316
|
+
}
|
|
10317
|
+
},
|
|
10318
|
+
edgeChange: {
|
|
10319
|
+
type: "object",
|
|
10320
|
+
additionalProperties: false,
|
|
10321
|
+
minProperties: 1,
|
|
10322
|
+
properties: {
|
|
10323
|
+
kind: {
|
|
10324
|
+
$ref: "#/$defs/kind"
|
|
10325
|
+
},
|
|
10326
|
+
label: {
|
|
10327
|
+
$ref: "#/$defs/label"
|
|
10328
|
+
},
|
|
10329
|
+
attributes: {
|
|
10330
|
+
$ref: "#/$defs/attributes"
|
|
10331
|
+
},
|
|
10332
|
+
removeAttributes: {
|
|
10333
|
+
$ref: "#/$defs/removeAttributes"
|
|
10334
|
+
}
|
|
10335
|
+
}
|
|
10336
|
+
},
|
|
10337
|
+
messageChange: {
|
|
10338
|
+
type: "object",
|
|
10339
|
+
additionalProperties: false,
|
|
10340
|
+
minProperties: 1,
|
|
10341
|
+
properties: {
|
|
10342
|
+
label: {
|
|
10343
|
+
$ref: "#/$defs/label"
|
|
10344
|
+
},
|
|
10345
|
+
attributes: {
|
|
10346
|
+
$ref: "#/$defs/attributes"
|
|
10347
|
+
},
|
|
10348
|
+
removeAttributes: {
|
|
10349
|
+
$ref: "#/$defs/removeAttributes"
|
|
10350
|
+
}
|
|
10351
|
+
}
|
|
10352
|
+
},
|
|
10353
|
+
rowChange: {
|
|
10354
|
+
type: "object",
|
|
10355
|
+
additionalProperties: false,
|
|
10356
|
+
minProperties: 1,
|
|
10357
|
+
properties: {
|
|
10358
|
+
label: {
|
|
10359
|
+
$ref: "#/$defs/label"
|
|
10360
|
+
},
|
|
10361
|
+
kind: {
|
|
10362
|
+
$ref: "#/$defs/kind"
|
|
10363
|
+
},
|
|
10364
|
+
cells: {
|
|
10365
|
+
$ref: "#/$defs/cells"
|
|
10366
|
+
},
|
|
10367
|
+
attributes: {
|
|
10368
|
+
$ref: "#/$defs/attributes"
|
|
10369
|
+
},
|
|
10370
|
+
removeAttributes: {
|
|
10371
|
+
$ref: "#/$defs/removeAttributes"
|
|
10372
|
+
}
|
|
10373
|
+
}
|
|
10374
|
+
},
|
|
10375
|
+
container: {
|
|
10376
|
+
description: "A named group of elements or participants. Grouping only: relationships connect elements and cross container boundaries freely, and a container carries no relationship of its own.",
|
|
10377
|
+
type: "object",
|
|
10378
|
+
additionalProperties: false,
|
|
10379
|
+
required: [
|
|
10380
|
+
"id",
|
|
10381
|
+
"label"
|
|
10382
|
+
],
|
|
10383
|
+
properties: {
|
|
10384
|
+
id: {
|
|
10385
|
+
$ref: "#/$defs/localId"
|
|
10386
|
+
},
|
|
10387
|
+
label: {
|
|
10388
|
+
$ref: "#/$defs/label"
|
|
10389
|
+
},
|
|
10390
|
+
kind: {
|
|
10391
|
+
$ref: "#/$defs/kind"
|
|
10392
|
+
}
|
|
10393
|
+
}
|
|
10394
|
+
},
|
|
10395
|
+
element: {
|
|
10396
|
+
type: "object",
|
|
10397
|
+
additionalProperties: false,
|
|
10398
|
+
required: [
|
|
10399
|
+
"id"
|
|
10400
|
+
],
|
|
10401
|
+
properties: {
|
|
10402
|
+
id: {
|
|
10403
|
+
$ref: "#/$defs/localId"
|
|
10404
|
+
},
|
|
10405
|
+
ref: {
|
|
10406
|
+
$ref: "#/$defs/ref"
|
|
10407
|
+
},
|
|
10408
|
+
label: {
|
|
10409
|
+
$ref: "#/$defs/label"
|
|
10410
|
+
},
|
|
10411
|
+
kind: {
|
|
10412
|
+
$ref: "#/$defs/kind"
|
|
10413
|
+
},
|
|
10414
|
+
set: {
|
|
10415
|
+
$ref: "#/$defs/elementChange"
|
|
10416
|
+
},
|
|
10417
|
+
container: {
|
|
10418
|
+
$ref: "#/$defs/localId"
|
|
10419
|
+
},
|
|
10420
|
+
attributes: {
|
|
10421
|
+
$ref: "#/$defs/attributes"
|
|
10422
|
+
},
|
|
10423
|
+
expect: {
|
|
10424
|
+
$ref: "#/$defs/expect"
|
|
10425
|
+
},
|
|
10426
|
+
locations: {
|
|
10427
|
+
$ref: "#/$defs/locations"
|
|
10428
|
+
},
|
|
10429
|
+
artifacts: {
|
|
10430
|
+
$ref: "#/$defs/artifacts"
|
|
10431
|
+
}
|
|
10432
|
+
},
|
|
10433
|
+
if: {
|
|
10434
|
+
not: {
|
|
10435
|
+
required: [
|
|
10436
|
+
"ref"
|
|
10437
|
+
]
|
|
10438
|
+
}
|
|
10439
|
+
},
|
|
10440
|
+
then: {
|
|
10441
|
+
required: [
|
|
10442
|
+
"label"
|
|
10443
|
+
]
|
|
10444
|
+
}
|
|
10445
|
+
},
|
|
10446
|
+
edge: {
|
|
10447
|
+
type: "object",
|
|
10448
|
+
additionalProperties: false,
|
|
10449
|
+
required: [
|
|
10450
|
+
"from",
|
|
10451
|
+
"to"
|
|
10452
|
+
],
|
|
10453
|
+
properties: {
|
|
10454
|
+
from: {
|
|
10455
|
+
$ref: "#/$defs/localId"
|
|
10456
|
+
},
|
|
10457
|
+
to: {
|
|
10458
|
+
$ref: "#/$defs/localId"
|
|
10459
|
+
},
|
|
10460
|
+
kind: {
|
|
10461
|
+
$ref: "#/$defs/kind"
|
|
10462
|
+
},
|
|
10463
|
+
ref: {
|
|
10464
|
+
$ref: "#/$defs/ref"
|
|
10465
|
+
},
|
|
10466
|
+
label: {
|
|
10467
|
+
$ref: "#/$defs/label"
|
|
10468
|
+
},
|
|
10469
|
+
set: {
|
|
10470
|
+
$ref: "#/$defs/edgeChange"
|
|
10471
|
+
},
|
|
10472
|
+
attributes: {
|
|
10473
|
+
$ref: "#/$defs/attributes"
|
|
10474
|
+
},
|
|
10475
|
+
expect: {
|
|
10476
|
+
$ref: "#/$defs/expect"
|
|
10477
|
+
},
|
|
10478
|
+
locations: {
|
|
10479
|
+
$ref: "#/$defs/locations"
|
|
10480
|
+
},
|
|
10481
|
+
artifacts: {
|
|
10482
|
+
$ref: "#/$defs/artifacts"
|
|
10483
|
+
}
|
|
10484
|
+
},
|
|
10485
|
+
if: {
|
|
10486
|
+
not: {
|
|
10487
|
+
required: [
|
|
10488
|
+
"ref"
|
|
10489
|
+
]
|
|
10490
|
+
}
|
|
10491
|
+
},
|
|
10492
|
+
then: {
|
|
10493
|
+
required: [
|
|
10494
|
+
"kind"
|
|
10495
|
+
]
|
|
10496
|
+
}
|
|
10497
|
+
},
|
|
10498
|
+
message: {
|
|
10499
|
+
type: "object",
|
|
10500
|
+
additionalProperties: false,
|
|
10501
|
+
required: [
|
|
10502
|
+
"from",
|
|
10503
|
+
"to"
|
|
10504
|
+
],
|
|
10505
|
+
properties: {
|
|
10506
|
+
from: {
|
|
10507
|
+
$ref: "#/$defs/localId"
|
|
10508
|
+
},
|
|
10509
|
+
to: {
|
|
10510
|
+
$ref: "#/$defs/localId"
|
|
10511
|
+
},
|
|
10512
|
+
ref: {
|
|
10513
|
+
$ref: "#/$defs/ref"
|
|
10514
|
+
},
|
|
10515
|
+
label: {
|
|
10516
|
+
$ref: "#/$defs/label"
|
|
10517
|
+
},
|
|
10518
|
+
set: {
|
|
10519
|
+
$ref: "#/$defs/messageChange"
|
|
10520
|
+
},
|
|
10521
|
+
attributes: {
|
|
10522
|
+
$ref: "#/$defs/attributes"
|
|
10523
|
+
},
|
|
10524
|
+
expect: {
|
|
10525
|
+
$ref: "#/$defs/expect"
|
|
10526
|
+
},
|
|
10527
|
+
locations: {
|
|
10528
|
+
$ref: "#/$defs/locations"
|
|
10529
|
+
},
|
|
10530
|
+
artifacts: {
|
|
10531
|
+
$ref: "#/$defs/artifacts"
|
|
10532
|
+
}
|
|
10533
|
+
},
|
|
10534
|
+
if: {
|
|
10535
|
+
not: {
|
|
10536
|
+
required: [
|
|
10537
|
+
"ref"
|
|
10538
|
+
]
|
|
10539
|
+
}
|
|
10540
|
+
},
|
|
10541
|
+
then: {
|
|
10542
|
+
required: [
|
|
10543
|
+
"label"
|
|
10544
|
+
]
|
|
10545
|
+
}
|
|
10546
|
+
},
|
|
10547
|
+
removal: {
|
|
10548
|
+
description: "Something to take out of the target, named by the reference the authority knows it by. The other fields describe it and never identify it: they exist so a reader can see what they are approving the removal of.",
|
|
10549
|
+
type: "object",
|
|
10550
|
+
additionalProperties: false,
|
|
10551
|
+
required: [
|
|
10552
|
+
"type",
|
|
10553
|
+
"ref"
|
|
10554
|
+
],
|
|
10555
|
+
properties: {
|
|
10556
|
+
type: {
|
|
10557
|
+
enum: [
|
|
10558
|
+
"element",
|
|
10559
|
+
"relationship",
|
|
10560
|
+
"row"
|
|
10561
|
+
]
|
|
10562
|
+
},
|
|
10563
|
+
ref: {
|
|
10564
|
+
$ref: "#/$defs/ref"
|
|
10565
|
+
},
|
|
10566
|
+
label: {
|
|
10567
|
+
$ref: "#/$defs/label"
|
|
10568
|
+
},
|
|
10569
|
+
kind: {
|
|
10570
|
+
$ref: "#/$defs/kind"
|
|
10571
|
+
},
|
|
10572
|
+
from: {
|
|
10573
|
+
$ref: "#/$defs/localId"
|
|
10574
|
+
},
|
|
10575
|
+
to: {
|
|
10576
|
+
$ref: "#/$defs/localId"
|
|
10577
|
+
}
|
|
10578
|
+
}
|
|
10579
|
+
},
|
|
10580
|
+
cells: {
|
|
10581
|
+
type: "array",
|
|
10582
|
+
items: {
|
|
10583
|
+
type: [
|
|
10584
|
+
"string",
|
|
10585
|
+
"number",
|
|
10586
|
+
"boolean",
|
|
10587
|
+
"null"
|
|
10588
|
+
],
|
|
10589
|
+
maxLength: 1e3
|
|
10590
|
+
},
|
|
10591
|
+
maxItems: 50
|
|
10592
|
+
},
|
|
10593
|
+
role: {
|
|
10594
|
+
enum: [
|
|
10595
|
+
"added",
|
|
10596
|
+
"changed",
|
|
10597
|
+
"context",
|
|
10598
|
+
"removed"
|
|
10599
|
+
]
|
|
10600
|
+
},
|
|
10601
|
+
dataRow: {
|
|
10602
|
+
description: "A row of the table. It may carry an identity of its own \u2014 a document-local id, the reference its authority knows it by, and the kind of thing it is \u2014 which is what lets a relation point at it and a patch address it.",
|
|
10603
|
+
type: "object",
|
|
10604
|
+
additionalProperties: false,
|
|
10605
|
+
required: [
|
|
10606
|
+
"cells"
|
|
10607
|
+
],
|
|
10608
|
+
properties: {
|
|
10609
|
+
cells: {
|
|
10610
|
+
$ref: "#/$defs/cells"
|
|
10611
|
+
},
|
|
10612
|
+
role: {
|
|
10613
|
+
$ref: "#/$defs/role"
|
|
10614
|
+
},
|
|
10615
|
+
id: {
|
|
10616
|
+
$ref: "#/$defs/localId"
|
|
10617
|
+
},
|
|
10618
|
+
ref: {
|
|
10619
|
+
$ref: "#/$defs/ref"
|
|
10620
|
+
},
|
|
10621
|
+
kind: {
|
|
10622
|
+
$ref: "#/$defs/kind"
|
|
10623
|
+
},
|
|
10624
|
+
label: {
|
|
10625
|
+
$ref: "#/$defs/label"
|
|
10626
|
+
},
|
|
10627
|
+
set: {
|
|
10628
|
+
$ref: "#/$defs/rowChange"
|
|
10629
|
+
},
|
|
10630
|
+
attributes: {
|
|
10631
|
+
$ref: "#/$defs/attributes"
|
|
10632
|
+
},
|
|
10633
|
+
expect: {
|
|
10634
|
+
$ref: "#/$defs/expect"
|
|
10635
|
+
},
|
|
10636
|
+
locations: {
|
|
10637
|
+
$ref: "#/$defs/locations"
|
|
10638
|
+
},
|
|
10639
|
+
artifacts: {
|
|
10640
|
+
$ref: "#/$defs/artifacts"
|
|
10641
|
+
}
|
|
10642
|
+
}
|
|
10643
|
+
},
|
|
10644
|
+
structuralRow: {
|
|
10645
|
+
description: "A heading that organises the table \u2014 a chapter, a section \u2014 rather than a row of data. It spans the table and is not aligned to its columns; it is never inferred from a data row whose cells are empty.",
|
|
10646
|
+
type: "object",
|
|
10647
|
+
additionalProperties: false,
|
|
10648
|
+
required: [
|
|
10649
|
+
"heading"
|
|
10650
|
+
],
|
|
10651
|
+
properties: {
|
|
10652
|
+
heading: {
|
|
10653
|
+
type: "string",
|
|
10654
|
+
minLength: 1,
|
|
10655
|
+
maxLength: 500
|
|
10656
|
+
},
|
|
10657
|
+
depth: {
|
|
10658
|
+
type: "integer",
|
|
10659
|
+
minimum: 1,
|
|
10660
|
+
maximum: 6
|
|
10661
|
+
},
|
|
10662
|
+
role: {
|
|
10663
|
+
$ref: "#/$defs/role"
|
|
10664
|
+
},
|
|
10665
|
+
id: {
|
|
10666
|
+
$ref: "#/$defs/localId"
|
|
10667
|
+
},
|
|
10668
|
+
ref: {
|
|
10669
|
+
$ref: "#/$defs/ref"
|
|
10670
|
+
}
|
|
10671
|
+
}
|
|
10672
|
+
},
|
|
10673
|
+
endpoint: {
|
|
10674
|
+
description: "One end of a relation: a row of this document by its local id, or something outside it by the reference its authority knows. Stated explicitly so an unresolvable local endpoint is an error rather than silently reread as external.",
|
|
10675
|
+
type: "object",
|
|
10676
|
+
additionalProperties: false,
|
|
10677
|
+
minProperties: 1,
|
|
10678
|
+
maxProperties: 1,
|
|
10679
|
+
oneOf: [
|
|
10680
|
+
{
|
|
10681
|
+
required: [
|
|
10682
|
+
"id"
|
|
10683
|
+
]
|
|
10684
|
+
},
|
|
10685
|
+
{
|
|
10686
|
+
required: [
|
|
10687
|
+
"ref"
|
|
10688
|
+
]
|
|
10689
|
+
}
|
|
10690
|
+
],
|
|
10691
|
+
properties: {
|
|
10692
|
+
id: {
|
|
10693
|
+
$ref: "#/$defs/localId"
|
|
10694
|
+
},
|
|
10695
|
+
ref: {
|
|
10696
|
+
$ref: "#/$defs/ref"
|
|
10697
|
+
}
|
|
10698
|
+
}
|
|
10699
|
+
},
|
|
10700
|
+
relation: {
|
|
10701
|
+
description: "A relation between rows \u2014 traceability. Carries an opaque kind from the profile's vocabulary, exactly as a relationship between graph elements does; unlike one, an end may leave the document, because the test that verifies a requirement usually lives elsewhere.",
|
|
10702
|
+
type: "object",
|
|
10703
|
+
additionalProperties: false,
|
|
10704
|
+
required: [
|
|
10705
|
+
"from",
|
|
10706
|
+
"to",
|
|
10707
|
+
"kind"
|
|
10708
|
+
],
|
|
10709
|
+
properties: {
|
|
10710
|
+
from: {
|
|
10711
|
+
$ref: "#/$defs/endpoint"
|
|
10712
|
+
},
|
|
10713
|
+
to: {
|
|
10714
|
+
$ref: "#/$defs/endpoint"
|
|
10715
|
+
},
|
|
10716
|
+
kind: {
|
|
10717
|
+
$ref: "#/$defs/kind"
|
|
10718
|
+
},
|
|
10719
|
+
ref: {
|
|
10720
|
+
$ref: "#/$defs/ref"
|
|
10721
|
+
},
|
|
10722
|
+
label: {
|
|
10723
|
+
$ref: "#/$defs/label"
|
|
10724
|
+
},
|
|
10725
|
+
attributes: {
|
|
10726
|
+
$ref: "#/$defs/attributes"
|
|
10727
|
+
}
|
|
10728
|
+
}
|
|
10729
|
+
},
|
|
10730
|
+
viewpoint: {
|
|
10731
|
+
description: "A named reading of a graph: the concern it frames, and the element and relationship kinds that address it. An inclusion \u2014 showing it shows what it retains and hides the rest, so a kind added to the model later is not shown unannounced. A vocabulary it names no kinds for is left whole. The term is ISO/IEC/IEEE 42010's.",
|
|
10732
|
+
type: "object",
|
|
10733
|
+
additionalProperties: false,
|
|
10734
|
+
required: [
|
|
10735
|
+
"id",
|
|
10736
|
+
"label",
|
|
10737
|
+
"concern"
|
|
10738
|
+
],
|
|
10739
|
+
properties: {
|
|
10740
|
+
id: {
|
|
10741
|
+
$ref: "#/$defs/localId"
|
|
10742
|
+
},
|
|
10743
|
+
label: {
|
|
10744
|
+
description: "What a reader selects it by.",
|
|
10745
|
+
type: "string",
|
|
10746
|
+
minLength: 1,
|
|
10747
|
+
maxLength: 500
|
|
10748
|
+
},
|
|
10749
|
+
concern: {
|
|
10750
|
+
description: "What this reading is for \u2014 stated inside every figure drawn for it, so a figure taken out of its report still says what it is a reading of.",
|
|
10751
|
+
type: "string",
|
|
10752
|
+
minLength: 1,
|
|
10753
|
+
maxLength: 500
|
|
10754
|
+
},
|
|
10755
|
+
elementKinds: {
|
|
10756
|
+
description: "Element kinds this viewpoint retains. Absent leaves the element vocabulary whole.",
|
|
10757
|
+
type: "array",
|
|
10758
|
+
minItems: 1,
|
|
10759
|
+
maxItems: 64,
|
|
10760
|
+
uniqueItems: true,
|
|
10761
|
+
items: {
|
|
10762
|
+
$ref: "#/$defs/kind"
|
|
10763
|
+
}
|
|
10764
|
+
},
|
|
10765
|
+
relationshipKinds: {
|
|
10766
|
+
description: "Relationship kinds this viewpoint retains. Absent leaves the relationship vocabulary whole.",
|
|
10767
|
+
type: "array",
|
|
10768
|
+
minItems: 1,
|
|
10769
|
+
maxItems: 64,
|
|
10770
|
+
uniqueItems: true,
|
|
10771
|
+
items: {
|
|
10772
|
+
$ref: "#/$defs/kind"
|
|
10773
|
+
}
|
|
10774
|
+
}
|
|
10775
|
+
}
|
|
10776
|
+
},
|
|
10777
|
+
calendarDate: {
|
|
10778
|
+
description: "A calendar date, YYYY-MM-DD. A day, not an instant: no time and no zone, so a position derived from it is the same for every reader.",
|
|
10779
|
+
type: "string",
|
|
10780
|
+
pattern: "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$"
|
|
10781
|
+
},
|
|
10782
|
+
timelineActivity: {
|
|
10783
|
+
description: "A duration on a task, drawn as a bar from the start of its start day to the end of its end day.",
|
|
10784
|
+
type: "object",
|
|
10785
|
+
additionalProperties: false,
|
|
10786
|
+
required: [
|
|
10787
|
+
"type",
|
|
10788
|
+
"start",
|
|
10789
|
+
"end"
|
|
10790
|
+
],
|
|
10791
|
+
properties: {
|
|
10792
|
+
type: {
|
|
10793
|
+
const: "activity"
|
|
10794
|
+
},
|
|
10795
|
+
start: {
|
|
10796
|
+
$ref: "#/$defs/calendarDate"
|
|
10797
|
+
},
|
|
10798
|
+
end: {
|
|
10799
|
+
$ref: "#/$defs/calendarDate"
|
|
10800
|
+
},
|
|
10801
|
+
id: {
|
|
10802
|
+
$ref: "#/$defs/localId"
|
|
10803
|
+
},
|
|
10804
|
+
label: {
|
|
10805
|
+
$ref: "#/$defs/label"
|
|
10806
|
+
},
|
|
10807
|
+
kind: {
|
|
10808
|
+
$ref: "#/$defs/kind"
|
|
10809
|
+
},
|
|
10810
|
+
previous: {
|
|
10811
|
+
description: "Where the activity stood in the plan named by comparedTo.",
|
|
10812
|
+
type: "object",
|
|
10813
|
+
additionalProperties: false,
|
|
10814
|
+
required: [
|
|
10815
|
+
"start",
|
|
10816
|
+
"end"
|
|
10817
|
+
],
|
|
10818
|
+
properties: {
|
|
10819
|
+
start: {
|
|
10820
|
+
$ref: "#/$defs/calendarDate"
|
|
10821
|
+
},
|
|
10822
|
+
end: {
|
|
10823
|
+
$ref: "#/$defs/calendarDate"
|
|
10824
|
+
}
|
|
10825
|
+
}
|
|
10826
|
+
},
|
|
10827
|
+
role: {
|
|
10828
|
+
$ref: "#/$defs/timelineChangeRole"
|
|
10829
|
+
}
|
|
10830
|
+
}
|
|
10831
|
+
},
|
|
10832
|
+
timelineMilestone: {
|
|
10833
|
+
description: "A point in time on a task, drawn as a star.",
|
|
10834
|
+
type: "object",
|
|
10835
|
+
additionalProperties: false,
|
|
10836
|
+
required: [
|
|
10837
|
+
"type",
|
|
10838
|
+
"date"
|
|
10839
|
+
],
|
|
10840
|
+
properties: {
|
|
10841
|
+
type: {
|
|
10842
|
+
const: "milestone"
|
|
10843
|
+
},
|
|
10844
|
+
date: {
|
|
10845
|
+
$ref: "#/$defs/calendarDate"
|
|
10846
|
+
},
|
|
10847
|
+
id: {
|
|
10848
|
+
$ref: "#/$defs/localId"
|
|
10849
|
+
},
|
|
10850
|
+
label: {
|
|
10851
|
+
$ref: "#/$defs/label"
|
|
10852
|
+
},
|
|
10853
|
+
kind: {
|
|
10854
|
+
$ref: "#/$defs/kind"
|
|
10855
|
+
},
|
|
10856
|
+
previous: {
|
|
10857
|
+
description: "Where the milestone stood in the plan named by comparedTo.",
|
|
10858
|
+
type: "object",
|
|
10859
|
+
additionalProperties: false,
|
|
10860
|
+
required: [
|
|
10861
|
+
"date"
|
|
10862
|
+
],
|
|
10863
|
+
properties: {
|
|
10864
|
+
date: {
|
|
10865
|
+
$ref: "#/$defs/calendarDate"
|
|
10866
|
+
}
|
|
10867
|
+
}
|
|
10868
|
+
},
|
|
10869
|
+
role: {
|
|
10870
|
+
$ref: "#/$defs/timelineChangeRole"
|
|
10871
|
+
}
|
|
10872
|
+
}
|
|
10873
|
+
},
|
|
10874
|
+
timelineTask: {
|
|
10875
|
+
description: "A semantic row: a named task holding any number of activities and milestones, in any order.",
|
|
10876
|
+
type: "object",
|
|
10877
|
+
additionalProperties: false,
|
|
10878
|
+
required: [
|
|
10879
|
+
"type",
|
|
10880
|
+
"id",
|
|
10881
|
+
"label",
|
|
10882
|
+
"items"
|
|
10883
|
+
],
|
|
10884
|
+
properties: {
|
|
10885
|
+
type: {
|
|
10886
|
+
const: "task"
|
|
10887
|
+
},
|
|
10888
|
+
id: {
|
|
10889
|
+
$ref: "#/$defs/localId"
|
|
10890
|
+
},
|
|
10891
|
+
label: {
|
|
10892
|
+
$ref: "#/$defs/label"
|
|
10893
|
+
},
|
|
10894
|
+
items: {
|
|
10895
|
+
type: "array",
|
|
10896
|
+
maxItems: 100,
|
|
10897
|
+
items: {
|
|
10898
|
+
$ref: "#/$defs/timelineItem"
|
|
10899
|
+
}
|
|
10900
|
+
},
|
|
10901
|
+
role: {
|
|
10902
|
+
$ref: "#/$defs/timelineChangeRole"
|
|
10903
|
+
}
|
|
10904
|
+
}
|
|
10905
|
+
},
|
|
10906
|
+
timelineSeparator: {
|
|
10907
|
+
description: "A horizontal divider between groups of tasks, with an optional title. Carries no dates and takes no part in the time axis.",
|
|
10908
|
+
type: "object",
|
|
10909
|
+
additionalProperties: false,
|
|
10910
|
+
required: [
|
|
10911
|
+
"type"
|
|
10912
|
+
],
|
|
10913
|
+
properties: {
|
|
10914
|
+
type: {
|
|
10915
|
+
const: "separator"
|
|
10916
|
+
},
|
|
10917
|
+
label: {
|
|
10918
|
+
$ref: "#/$defs/label"
|
|
10919
|
+
}
|
|
10920
|
+
}
|
|
10921
|
+
},
|
|
10922
|
+
timelineDependency: {
|
|
10923
|
+
description: "A Gantt dependency: the successor `to` waits on the predecessor `from`. Endpoints name a task or an item by id; a task stands for the span of its items. Without a type it is finish-to-start.",
|
|
10924
|
+
type: "object",
|
|
10925
|
+
additionalProperties: false,
|
|
10926
|
+
required: [
|
|
10927
|
+
"from",
|
|
10928
|
+
"to"
|
|
10929
|
+
],
|
|
10930
|
+
properties: {
|
|
10931
|
+
from: {
|
|
10932
|
+
$ref: "#/$defs/localId"
|
|
10933
|
+
},
|
|
10934
|
+
to: {
|
|
10935
|
+
$ref: "#/$defs/localId"
|
|
10936
|
+
},
|
|
10937
|
+
type: {
|
|
10938
|
+
enum: [
|
|
10939
|
+
"finish-to-start",
|
|
10940
|
+
"start-to-start",
|
|
10941
|
+
"finish-to-finish",
|
|
10942
|
+
"start-to-finish"
|
|
10943
|
+
]
|
|
10944
|
+
}
|
|
10945
|
+
}
|
|
10946
|
+
},
|
|
10947
|
+
timelineItem: {
|
|
10948
|
+
description: "An activity or a milestone, selected by its type so a refusal speaks about the one it is.",
|
|
10949
|
+
type: "object",
|
|
10950
|
+
required: [
|
|
10951
|
+
"type"
|
|
10952
|
+
],
|
|
10953
|
+
properties: {
|
|
10954
|
+
type: {
|
|
10955
|
+
enum: [
|
|
10956
|
+
"activity",
|
|
10957
|
+
"milestone"
|
|
10958
|
+
]
|
|
10959
|
+
}
|
|
10960
|
+
},
|
|
10961
|
+
allOf: [
|
|
10962
|
+
{
|
|
10963
|
+
if: {
|
|
10964
|
+
properties: {
|
|
10965
|
+
type: {
|
|
10966
|
+
const: "activity"
|
|
10967
|
+
}
|
|
10968
|
+
}
|
|
10969
|
+
},
|
|
10970
|
+
then: {
|
|
10971
|
+
$ref: "#/$defs/timelineActivity"
|
|
10972
|
+
}
|
|
10973
|
+
},
|
|
10974
|
+
{
|
|
10975
|
+
if: {
|
|
10976
|
+
properties: {
|
|
10977
|
+
type: {
|
|
10978
|
+
const: "milestone"
|
|
10979
|
+
}
|
|
10980
|
+
}
|
|
10981
|
+
},
|
|
10982
|
+
then: {
|
|
10983
|
+
$ref: "#/$defs/timelineMilestone"
|
|
10984
|
+
}
|
|
10985
|
+
}
|
|
10986
|
+
]
|
|
10987
|
+
},
|
|
10988
|
+
timelineRow: {
|
|
10989
|
+
description: "A task or a separator, selected by its type so a refusal speaks about the one it is.",
|
|
10990
|
+
type: "object",
|
|
10991
|
+
required: [
|
|
10992
|
+
"type"
|
|
10993
|
+
],
|
|
10994
|
+
properties: {
|
|
10995
|
+
type: {
|
|
10996
|
+
enum: [
|
|
10997
|
+
"task",
|
|
10998
|
+
"separator"
|
|
10999
|
+
]
|
|
11000
|
+
}
|
|
11001
|
+
},
|
|
11002
|
+
allOf: [
|
|
11003
|
+
{
|
|
11004
|
+
if: {
|
|
11005
|
+
properties: {
|
|
11006
|
+
type: {
|
|
11007
|
+
const: "task"
|
|
11008
|
+
}
|
|
11009
|
+
}
|
|
11010
|
+
},
|
|
11011
|
+
then: {
|
|
11012
|
+
$ref: "#/$defs/timelineTask"
|
|
11013
|
+
}
|
|
11014
|
+
},
|
|
11015
|
+
{
|
|
11016
|
+
if: {
|
|
11017
|
+
properties: {
|
|
11018
|
+
type: {
|
|
11019
|
+
const: "separator"
|
|
11020
|
+
}
|
|
11021
|
+
}
|
|
11022
|
+
},
|
|
11023
|
+
then: {
|
|
11024
|
+
$ref: "#/$defs/timelineSeparator"
|
|
11025
|
+
}
|
|
11026
|
+
}
|
|
11027
|
+
]
|
|
11028
|
+
},
|
|
11029
|
+
timelineChangeRole: {
|
|
11030
|
+
description: "In a compared timeline: new since the previous plan, or dropped from it and kept so it can be shown.",
|
|
11031
|
+
enum: [
|
|
11032
|
+
"added",
|
|
11033
|
+
"removed"
|
|
11034
|
+
]
|
|
11035
|
+
},
|
|
11036
|
+
timelinePeriod: {
|
|
11037
|
+
description: "A span of the calendar the plan runs in \u2014 a closure, holidays. Drawn as a band across every row; constrains nothing.",
|
|
11038
|
+
type: "object",
|
|
11039
|
+
additionalProperties: false,
|
|
11040
|
+
required: [
|
|
11041
|
+
"start",
|
|
11042
|
+
"end"
|
|
11043
|
+
],
|
|
11044
|
+
properties: {
|
|
11045
|
+
start: {
|
|
11046
|
+
$ref: "#/$defs/calendarDate"
|
|
11047
|
+
},
|
|
11048
|
+
end: {
|
|
11049
|
+
$ref: "#/$defs/calendarDate"
|
|
11050
|
+
},
|
|
11051
|
+
label: {
|
|
11052
|
+
$ref: "#/$defs/label"
|
|
11053
|
+
},
|
|
11054
|
+
kind: {
|
|
11055
|
+
$ref: "#/$defs/kind"
|
|
11056
|
+
}
|
|
11057
|
+
}
|
|
11058
|
+
},
|
|
11059
|
+
timelineReference: {
|
|
11060
|
+
description: "A named day the plan is judged against \u2014 a contractual date, a delivery. Drawn as a line across every row.",
|
|
11061
|
+
type: "object",
|
|
11062
|
+
additionalProperties: false,
|
|
11063
|
+
required: [
|
|
11064
|
+
"date",
|
|
11065
|
+
"label"
|
|
11066
|
+
],
|
|
11067
|
+
properties: {
|
|
11068
|
+
date: {
|
|
11069
|
+
$ref: "#/$defs/calendarDate"
|
|
11070
|
+
},
|
|
11071
|
+
label: {
|
|
11072
|
+
type: "string",
|
|
11073
|
+
minLength: 1,
|
|
11074
|
+
maxLength: 500
|
|
11075
|
+
},
|
|
11076
|
+
kind: {
|
|
11077
|
+
$ref: "#/$defs/kind"
|
|
11078
|
+
}
|
|
11079
|
+
}
|
|
11080
|
+
}
|
|
11081
|
+
},
|
|
11082
|
+
properties: {
|
|
11083
|
+
schema: {
|
|
11084
|
+
const: "urn:structured-exchange:3"
|
|
11085
|
+
},
|
|
11086
|
+
kind: {
|
|
11087
|
+
enum: [
|
|
11088
|
+
"graph",
|
|
11089
|
+
"sequence",
|
|
11090
|
+
"table",
|
|
11091
|
+
"timeline"
|
|
11092
|
+
]
|
|
11093
|
+
},
|
|
11094
|
+
profile: {
|
|
11095
|
+
description: "The vocabulary that owns the kinds and attribute names in this document. Opaque: never fetched, executed, or required to be known \u2014 an unknown profile is presented generically, not refused.",
|
|
11096
|
+
type: "string",
|
|
11097
|
+
minLength: 1,
|
|
11098
|
+
maxLength: 200
|
|
11099
|
+
},
|
|
11100
|
+
target: {
|
|
11101
|
+
description: "The artifact this document proposes a change to, and the revision it was prepared against. Its presence is what makes the document a proposal.",
|
|
11102
|
+
type: "object",
|
|
11103
|
+
additionalProperties: false,
|
|
11104
|
+
required: [
|
|
11105
|
+
"ref"
|
|
11106
|
+
],
|
|
11107
|
+
properties: {
|
|
11108
|
+
ref: {
|
|
11109
|
+
$ref: "#/$defs/ref"
|
|
11110
|
+
},
|
|
11111
|
+
revision: {
|
|
11112
|
+
$ref: "#/$defs/revision"
|
|
11113
|
+
}
|
|
11114
|
+
}
|
|
11115
|
+
},
|
|
11116
|
+
removals: {
|
|
11117
|
+
type: "array",
|
|
11118
|
+
maxItems: 500,
|
|
11119
|
+
items: {
|
|
11120
|
+
$ref: "#/$defs/removal"
|
|
11121
|
+
}
|
|
11122
|
+
},
|
|
11123
|
+
artifacts: {
|
|
11124
|
+
type: "array",
|
|
11125
|
+
maxItems: 50,
|
|
11126
|
+
items: {
|
|
11127
|
+
$ref: "#/$defs/artifact"
|
|
11128
|
+
}
|
|
11129
|
+
},
|
|
11130
|
+
viewpoints: {
|
|
11131
|
+
description: "Named readings of this document. Only a graph may declare them. Presentation only: selecting one never alters the document.",
|
|
11132
|
+
type: "array",
|
|
11133
|
+
maxItems: 20,
|
|
11134
|
+
items: {
|
|
11135
|
+
$ref: "#/$defs/viewpoint"
|
|
11136
|
+
}
|
|
11137
|
+
},
|
|
11138
|
+
data: {
|
|
11139
|
+
oneOf: [
|
|
11140
|
+
{
|
|
11141
|
+
type: "object",
|
|
11142
|
+
additionalProperties: false,
|
|
11143
|
+
required: [
|
|
11144
|
+
"nodes",
|
|
11145
|
+
"edges"
|
|
11146
|
+
],
|
|
11147
|
+
properties: {
|
|
11148
|
+
nodes: {
|
|
11149
|
+
type: "array",
|
|
11150
|
+
minItems: 1,
|
|
11151
|
+
maxItems: 500,
|
|
11152
|
+
items: {
|
|
11153
|
+
$ref: "#/$defs/element"
|
|
11154
|
+
}
|
|
11155
|
+
},
|
|
11156
|
+
edges: {
|
|
11157
|
+
type: "array",
|
|
11158
|
+
maxItems: 2e3,
|
|
11159
|
+
items: {
|
|
11160
|
+
$ref: "#/$defs/edge"
|
|
11161
|
+
}
|
|
11162
|
+
},
|
|
11163
|
+
containers: {
|
|
11164
|
+
type: "array",
|
|
11165
|
+
maxItems: 50,
|
|
11166
|
+
items: {
|
|
11167
|
+
$ref: "#/$defs/container"
|
|
11168
|
+
}
|
|
11169
|
+
}
|
|
11170
|
+
}
|
|
11171
|
+
},
|
|
11172
|
+
{
|
|
11173
|
+
type: "object",
|
|
11174
|
+
additionalProperties: false,
|
|
11175
|
+
required: [
|
|
11176
|
+
"participants",
|
|
11177
|
+
"messages"
|
|
11178
|
+
],
|
|
11179
|
+
properties: {
|
|
11180
|
+
participants: {
|
|
11181
|
+
type: "array",
|
|
11182
|
+
minItems: 1,
|
|
11183
|
+
maxItems: 100,
|
|
11184
|
+
items: {
|
|
11185
|
+
$ref: "#/$defs/element"
|
|
11186
|
+
}
|
|
11187
|
+
},
|
|
11188
|
+
messages: {
|
|
11189
|
+
type: "array",
|
|
11190
|
+
maxItems: 1e3,
|
|
11191
|
+
items: {
|
|
11192
|
+
$ref: "#/$defs/message"
|
|
11193
|
+
}
|
|
11194
|
+
},
|
|
11195
|
+
containers: {
|
|
11196
|
+
type: "array",
|
|
11197
|
+
maxItems: 50,
|
|
11198
|
+
items: {
|
|
11199
|
+
$ref: "#/$defs/container"
|
|
11200
|
+
}
|
|
11201
|
+
}
|
|
11202
|
+
}
|
|
11203
|
+
},
|
|
11204
|
+
{
|
|
11205
|
+
type: "object",
|
|
11206
|
+
additionalProperties: false,
|
|
11207
|
+
required: [
|
|
11208
|
+
"columns",
|
|
11209
|
+
"rows"
|
|
11210
|
+
],
|
|
11211
|
+
properties: {
|
|
11212
|
+
columns: {
|
|
11213
|
+
type: "array",
|
|
11214
|
+
minItems: 1,
|
|
11215
|
+
maxItems: 50,
|
|
11216
|
+
items: {
|
|
11217
|
+
type: "string",
|
|
11218
|
+
minLength: 1,
|
|
11219
|
+
maxLength: 200
|
|
11220
|
+
}
|
|
11221
|
+
},
|
|
11222
|
+
rows: {
|
|
11223
|
+
type: "array",
|
|
11224
|
+
maxItems: 5e3,
|
|
11225
|
+
items: {
|
|
11226
|
+
oneOf: [
|
|
11227
|
+
{
|
|
11228
|
+
$ref: "#/$defs/cells"
|
|
11229
|
+
},
|
|
11230
|
+
{
|
|
11231
|
+
$ref: "#/$defs/dataRow"
|
|
11232
|
+
},
|
|
11233
|
+
{
|
|
11234
|
+
$ref: "#/$defs/structuralRow"
|
|
11235
|
+
}
|
|
11236
|
+
]
|
|
11237
|
+
}
|
|
11238
|
+
},
|
|
11239
|
+
relations: {
|
|
11240
|
+
type: "array",
|
|
11241
|
+
maxItems: 2e3,
|
|
11242
|
+
items: {
|
|
11243
|
+
$ref: "#/$defs/relation"
|
|
11244
|
+
}
|
|
11245
|
+
}
|
|
11246
|
+
}
|
|
11247
|
+
},
|
|
11248
|
+
{
|
|
11249
|
+
description: "A planning timeline: a calendar range and an ordered list of rows. Never coordinates, colours or a current date \u2014 the renderer derives those.",
|
|
11250
|
+
type: "object",
|
|
11251
|
+
additionalProperties: false,
|
|
11252
|
+
required: [
|
|
11253
|
+
"time",
|
|
11254
|
+
"rows"
|
|
11255
|
+
],
|
|
11256
|
+
properties: {
|
|
11257
|
+
title: {
|
|
11258
|
+
$ref: "#/$defs/label"
|
|
11259
|
+
},
|
|
11260
|
+
time: {
|
|
11261
|
+
type: "object",
|
|
11262
|
+
additionalProperties: false,
|
|
11263
|
+
required: [
|
|
11264
|
+
"start",
|
|
11265
|
+
"end",
|
|
11266
|
+
"scale"
|
|
11267
|
+
],
|
|
11268
|
+
properties: {
|
|
11269
|
+
start: {
|
|
11270
|
+
$ref: "#/$defs/calendarDate"
|
|
11271
|
+
},
|
|
11272
|
+
end: {
|
|
11273
|
+
$ref: "#/$defs/calendarDate"
|
|
11274
|
+
},
|
|
11275
|
+
scale: {
|
|
11276
|
+
enum: [
|
|
11277
|
+
"week",
|
|
11278
|
+
"month",
|
|
11279
|
+
"quarter"
|
|
11280
|
+
]
|
|
11281
|
+
}
|
|
11282
|
+
}
|
|
11283
|
+
},
|
|
11284
|
+
rows: {
|
|
11285
|
+
type: "array",
|
|
11286
|
+
maxItems: 500,
|
|
11287
|
+
items: {
|
|
11288
|
+
$ref: "#/$defs/timelineRow"
|
|
11289
|
+
}
|
|
11290
|
+
},
|
|
11291
|
+
dependencies: {
|
|
11292
|
+
type: "array",
|
|
11293
|
+
maxItems: 2e3,
|
|
11294
|
+
items: {
|
|
11295
|
+
$ref: "#/$defs/timelineDependency"
|
|
11296
|
+
}
|
|
11297
|
+
},
|
|
11298
|
+
comparedTo: {
|
|
11299
|
+
description: "The plan this timeline is compared with. Its presence makes the timeline a comparison: items may then carry previous dates and roles.",
|
|
11300
|
+
type: "object",
|
|
11301
|
+
additionalProperties: false,
|
|
11302
|
+
required: [
|
|
11303
|
+
"label"
|
|
11304
|
+
],
|
|
11305
|
+
properties: {
|
|
11306
|
+
label: {
|
|
11307
|
+
type: "string",
|
|
11308
|
+
minLength: 1,
|
|
11309
|
+
maxLength: 500
|
|
11310
|
+
},
|
|
11311
|
+
date: {
|
|
11312
|
+
$ref: "#/$defs/calendarDate"
|
|
11313
|
+
}
|
|
11314
|
+
}
|
|
11315
|
+
},
|
|
11316
|
+
periods: {
|
|
11317
|
+
type: "array",
|
|
11318
|
+
maxItems: 100,
|
|
11319
|
+
items: {
|
|
11320
|
+
$ref: "#/$defs/timelinePeriod"
|
|
11321
|
+
}
|
|
11322
|
+
},
|
|
11323
|
+
references: {
|
|
11324
|
+
type: "array",
|
|
11325
|
+
maxItems: 50,
|
|
11326
|
+
items: {
|
|
11327
|
+
$ref: "#/$defs/timelineReference"
|
|
11328
|
+
}
|
|
11329
|
+
}
|
|
11330
|
+
}
|
|
11331
|
+
}
|
|
11332
|
+
]
|
|
11333
|
+
}
|
|
11334
|
+
}
|
|
11335
|
+
};
|
|
11336
|
+
|
|
11337
|
+
// shared/src/structuredExchangeDocument.ts
|
|
11338
|
+
var STRUCTURED_EXCHANGE_SCHEMA_PREFIX = "urn:structured-exchange:";
|
|
11339
|
+
function declaredSchemaOf(document) {
|
|
11340
|
+
if (typeof document !== "object" || document === null || Array.isArray(document)) return void 0;
|
|
11341
|
+
const schema2 = document.schema;
|
|
11342
|
+
if (typeof schema2 !== "string" || !schema2.startsWith(STRUCTURED_EXCHANGE_SCHEMA_PREFIX)) return void 0;
|
|
11343
|
+
return schema2;
|
|
11344
|
+
}
|
|
11345
|
+
|
|
11346
|
+
// shared/src/structuredExchangeSchemaNode.ts
|
|
11347
|
+
function unwrapSchemaModule(module) {
|
|
11348
|
+
const raw = module;
|
|
11349
|
+
const looksLikeSchema = "$id" in raw || "type" in raw;
|
|
11350
|
+
const root = looksLikeSchema ? raw : raw.default;
|
|
11351
|
+
if (root.default !== root) return root;
|
|
11352
|
+
const { default: _interop, ...rest } = root;
|
|
11353
|
+
return rest;
|
|
11354
|
+
}
|
|
11355
|
+
var schemas = {
|
|
11356
|
+
"urn:structured-exchange:1": unwrapSchemaModule(structured_exchange_1_default),
|
|
11357
|
+
"urn:structured-exchange:2": unwrapSchemaModule(structured_exchange_2_default),
|
|
11358
|
+
"urn:structured-exchange:3": unwrapSchemaModule(structured_exchange_3_default)
|
|
11359
|
+
};
|
|
11360
|
+
var schema = schemas[STRUCTURED_EXCHANGE_SCHEMA_V1];
|
|
11361
|
+
var compiled = /* @__PURE__ */ new Map();
|
|
11362
|
+
function schemaFor(version, kind) {
|
|
11363
|
+
const published = schemas[version];
|
|
11364
|
+
const variants = published.properties.data?.oneOf ?? [];
|
|
11365
|
+
const required = {
|
|
11366
|
+
graph: "nodes",
|
|
11367
|
+
sequence: "participants",
|
|
11368
|
+
table: "columns",
|
|
11369
|
+
timeline: "time"
|
|
11370
|
+
};
|
|
11371
|
+
const marker = typeof kind === "string" ? required[kind] : void 0;
|
|
11372
|
+
const variant = marker === void 0 ? void 0 : variants.find((candidate) => candidate.properties?.[marker] !== void 0);
|
|
11373
|
+
if (variant === void 0) return published;
|
|
11374
|
+
return {
|
|
11375
|
+
...published,
|
|
11376
|
+
properties: { ...published.properties, data: variant }
|
|
11377
|
+
};
|
|
11378
|
+
}
|
|
11379
|
+
var NARROWABLE_KINDS = ["graph", "sequence", "table", "timeline"];
|
|
11380
|
+
function validator(version, kind) {
|
|
11381
|
+
const narrowable = typeof kind === "string" && NARROWABLE_KINDS.includes(kind);
|
|
11382
|
+
const key = `${version}:${narrowable ? kind : "*"}`;
|
|
11383
|
+
const existing = compiled.get(key);
|
|
11384
|
+
if (existing !== void 0) return existing;
|
|
11385
|
+
const built = Compile(schemaFor(version, narrowable ? kind : void 0));
|
|
11386
|
+
compiled.set(key, built);
|
|
11387
|
+
return built;
|
|
11388
|
+
}
|
|
11389
|
+
var TIMELINE_BRANCHES = {
|
|
11390
|
+
task: "timelineTask",
|
|
11391
|
+
separator: "timelineSeparator",
|
|
11392
|
+
activity: "timelineActivity",
|
|
11393
|
+
milestone: "timelineMilestone"
|
|
11394
|
+
};
|
|
11395
|
+
var branchValidators = /* @__PURE__ */ new Map();
|
|
11396
|
+
function branchValidator(definition) {
|
|
11397
|
+
const existing = branchValidators.get(definition);
|
|
11398
|
+
if (existing !== void 0) return existing;
|
|
11399
|
+
const defs = schemas[STRUCTURED_EXCHANGE_SCHEMA_V3].$defs;
|
|
11400
|
+
const built = Compile({ $defs: defs, $ref: `#/$defs/${definition}` });
|
|
11401
|
+
branchValidators.set(definition, built);
|
|
11402
|
+
return built;
|
|
11403
|
+
}
|
|
11404
|
+
function expandTimelineBranches(document, errors) {
|
|
11405
|
+
return errors.flatMap((error) => {
|
|
11406
|
+
if (error.keyword === "additionalProperties") return namedExtras(error);
|
|
11407
|
+
if (error.keyword === "enum") return [withAllowedValues(error)];
|
|
11408
|
+
if (error.keyword !== "if") return [error];
|
|
11409
|
+
const at = error.instancePath ?? "";
|
|
11410
|
+
const value = atPointer(document, at);
|
|
11411
|
+
const definition = typeof value?.type === "string" ? TIMELINE_BRANCHES[value.type] : void 0;
|
|
11412
|
+
if (definition === void 0) return [error];
|
|
11413
|
+
const inner = [...branchValidator(definition).Errors(value)].map((found) => ({
|
|
11414
|
+
...found,
|
|
11415
|
+
instancePath: `${at}${found.instancePath ?? ""}`
|
|
11416
|
+
}));
|
|
11417
|
+
return inner.length === 0 ? [error] : expandTimelineBranches(document, inner);
|
|
11418
|
+
});
|
|
11419
|
+
}
|
|
11420
|
+
function withAllowedValues(error) {
|
|
11421
|
+
const allowed = error.params?.allowedValues;
|
|
11422
|
+
if (!Array.isArray(allowed)) return error;
|
|
11423
|
+
return { ...error, message: `must be one of ${allowed.map((value) => JSON.stringify(value)).join(", ")}` };
|
|
11424
|
+
}
|
|
11425
|
+
var PRESENTATION_NAMES = /* @__PURE__ */ new Set(["x", "y", "color", "colour", "fill", "stroke", "shape", "width", "height", "position", "style", "dash"]);
|
|
11426
|
+
function namedExtras(error) {
|
|
11427
|
+
const names2 = error.params?.additionalProperties;
|
|
11428
|
+
if (!Array.isArray(names2) || names2.length === 0) return [error];
|
|
11429
|
+
return names2.map(
|
|
11430
|
+
(name) => ({
|
|
11431
|
+
...error,
|
|
11432
|
+
instancePath: `${error.instancePath ?? ""}/${String(name).replace(/~/g, "~0").replace(/\//g, "~1")}`,
|
|
11433
|
+
message: PRESENTATION_NAMES.has(String(name).toLowerCase()) ? `"${String(name)}" is not defined here; a timeline carries what the plan means, and the renderer derives positions, colours and shapes` : `"${String(name)}" is not defined here`
|
|
11434
|
+
})
|
|
11435
|
+
);
|
|
11436
|
+
}
|
|
11437
|
+
function observedFor(keyword, value) {
|
|
11438
|
+
if (typeof value === "string" && (keyword === "maxLength" || keyword === "minLength")) return value.length;
|
|
11439
|
+
if (Array.isArray(value) && (keyword === "maxItems" || keyword === "minItems")) return value.length;
|
|
11440
|
+
return void 0;
|
|
11441
|
+
}
|
|
11442
|
+
function atPointer(document, pointer) {
|
|
11443
|
+
if (pointer === "") return document;
|
|
11444
|
+
let current = document;
|
|
11445
|
+
for (const rawSegment of pointer.slice(1).split("/")) {
|
|
11446
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
11447
|
+
const segment4 = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
11448
|
+
current = current[segment4];
|
|
11449
|
+
}
|
|
11450
|
+
return current;
|
|
11451
|
+
}
|
|
11452
|
+
var checkStructuredExchangeSchema = (document) => {
|
|
11453
|
+
const declared = declaredSchemaOf(document);
|
|
11454
|
+
const version = supportedSchemaOf(declared);
|
|
11455
|
+
if (version === void 0 && declared !== void 0) {
|
|
11456
|
+
return [
|
|
11457
|
+
{
|
|
11458
|
+
rule: "unsupported-version",
|
|
11459
|
+
path: "/schema",
|
|
11460
|
+
message: `this build validates ${STRUCTURED_EXCHANGE_SUPPORTED_SCHEMAS.join(" and ")}`
|
|
11461
|
+
}
|
|
11462
|
+
];
|
|
11463
|
+
}
|
|
11464
|
+
const issues = [];
|
|
11465
|
+
const contract = version ?? STRUCTURED_EXCHANGE_SCHEMA_V1;
|
|
11466
|
+
const published = [...validator(contract, void 0).Errors(document)];
|
|
11467
|
+
if (published.length === 0) return issues;
|
|
11468
|
+
const kind = document?.kind;
|
|
11469
|
+
if (contract === STRUCTURED_EXCHANGE_SCHEMA_V3 && typeof kind === "string" && ["graph", "sequence", "table"].includes(kind)) {
|
|
11470
|
+
const asVersionTwo = checkStructuredExchangeSchema({
|
|
11471
|
+
...document,
|
|
11472
|
+
schema: STRUCTURED_EXCHANGE_SCHEMA_V2
|
|
11473
|
+
});
|
|
11474
|
+
if (asVersionTwo.length > 0) return asVersionTwo;
|
|
11475
|
+
}
|
|
11476
|
+
const narrowed = [...validator(contract, kind).Errors(document)];
|
|
11477
|
+
const seen = new Set(narrowed.map((error) => `${error.keyword}@${error.instancePath}`));
|
|
11478
|
+
const timeline = contract === STRUCTURED_EXCHANGE_SCHEMA_V3 && kind === "timeline";
|
|
11479
|
+
const combined = timeline ? expandTimelineBranches(document, narrowed) : [...narrowed, ...published.filter((error) => !seen.has(`${error.keyword}@${error.instancePath}`))];
|
|
11480
|
+
for (const error of combined) {
|
|
11481
|
+
const keyword = String(error.keyword ?? "schema");
|
|
11482
|
+
const limit = error.params?.limit;
|
|
11483
|
+
issues.push({
|
|
11484
|
+
rule: `schema/${keyword}`,
|
|
11485
|
+
path: error.instancePath ?? "",
|
|
11486
|
+
message: error.message ?? "does not conform to the published schema",
|
|
11487
|
+
...limit !== void 0 ? { limit, level: "ceiling" } : {},
|
|
11488
|
+
...(() => {
|
|
11489
|
+
const observed = observedFor(keyword, atPointer(document, error.instancePath ?? ""));
|
|
11490
|
+
return observed === void 0 ? {} : { observed };
|
|
11491
|
+
})()
|
|
11492
|
+
});
|
|
11493
|
+
}
|
|
11494
|
+
return issues.sort((left, right) => right.path.split("/").length - left.path.split("/").length);
|
|
11495
|
+
};
|
|
11496
|
+
|
|
11497
|
+
// shared/src/structuredExchangeProfile.ts
|
|
11498
|
+
var STRUCTURED_EXCHANGE_PROFILE_REGISTRY_SCHEMA_V2 = "urn:structured-exchange-profile-registry:2";
|
|
11499
|
+
var STRUCTURED_EXCHANGE_PROFILE_REGISTRY_PATH = ".pi-outpost/structured-exchange.json";
|
|
11500
|
+
var STRUCTURED_EXCHANGE_CONFORMITY_REPORT_PROFILE = "urn:structured-exchange-conformity-report:1";
|
|
11501
|
+
var STRUCTURED_EXCHANGE_RULES_REGISTER_PROFILE = "urn:structured-exchange-rules-register:1";
|
|
11502
|
+
var STRUCTURED_EXCHANGE_RULE_PATTERNS_PROFILE = "urn:structured-exchange-rule-patterns:1";
|
|
11503
|
+
var RESERVED_PROFILE_IDENTIFIERS = /* @__PURE__ */ new Set([
|
|
11504
|
+
STRUCTURED_EXCHANGE_CONFORMITY_REPORT_PROFILE,
|
|
11505
|
+
STRUCTURED_EXCHANGE_RULES_REGISTER_PROFILE,
|
|
11506
|
+
STRUCTURED_EXCHANGE_RULE_PATTERNS_PROFILE
|
|
11507
|
+
]);
|
|
11508
|
+
var STRUCTURED_EXCHANGE_PROFILE_CEILINGS = {
|
|
11509
|
+
/** A profile's identifier, bounded like the `profile` a document names it by. */
|
|
11510
|
+
id: 200,
|
|
11511
|
+
label: 500,
|
|
11512
|
+
description: 2e3,
|
|
11513
|
+
/** Kinds per vocabulary, as a document's `kindsPerVocabulary`. */
|
|
11514
|
+
kindsPerVocabulary: 64,
|
|
11515
|
+
/** Attributes one kind declares, as a document's `attributesPerItem`. */
|
|
11516
|
+
attributesPerKind: 50,
|
|
11517
|
+
attributeName: 200,
|
|
9852
11518
|
/**
|
|
9853
11519
|
* Values one enumeration lists. Generous: a requirements tool's enumerations
|
|
9854
11520
|
* include long ones — components, suppliers — and a profile that cannot hold its
|
|
@@ -10190,9 +11856,106 @@ var structured_exchange_profile_registry_1_default = {
|
|
|
10190
11856
|
}
|
|
10191
11857
|
};
|
|
10192
11858
|
|
|
11859
|
+
// shared/schemas/structured-exchange-profile-registry-2.json
|
|
11860
|
+
var structured_exchange_profile_registry_2_default = {
|
|
11861
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
11862
|
+
$id: "urn:structured-exchange-profile-registry:2",
|
|
11863
|
+
title: "Structured exchange profile registry v2",
|
|
11864
|
+
description: "Version 1 plus the project's appearance: colours for the kinds its documents use, applied wherever a kind is coloured and never written into a document. Profiles become optional, so a project may declare only its colours. Kept at .pi-outpost/structured-exchange.json in the project.",
|
|
11865
|
+
type: "object",
|
|
11866
|
+
additionalProperties: false,
|
|
11867
|
+
required: [
|
|
11868
|
+
"schema"
|
|
11869
|
+
],
|
|
11870
|
+
properties: {
|
|
11871
|
+
schema: {
|
|
11872
|
+
description: "Which registry format this is.",
|
|
11873
|
+
const: "urn:structured-exchange-profile-registry:2"
|
|
11874
|
+
},
|
|
11875
|
+
profiles: {
|
|
11876
|
+
description: "Profile files, by path relative to the project directory. Each must stay inside the project. May be empty or absent: a registry without profiles constrains no document.",
|
|
11877
|
+
type: "array",
|
|
11878
|
+
minItems: 0,
|
|
11879
|
+
maxItems: 20,
|
|
11880
|
+
items: {
|
|
11881
|
+
type: "string",
|
|
11882
|
+
minLength: 1,
|
|
11883
|
+
maxLength: 500
|
|
11884
|
+
}
|
|
11885
|
+
},
|
|
11886
|
+
rules: {
|
|
11887
|
+
description: "Rules files, by path relative to the project directory. Each names the registered profile it applies to, and is checked against that profile's vocabulary whenever it is read.",
|
|
11888
|
+
type: "array",
|
|
11889
|
+
maxItems: 20,
|
|
11890
|
+
items: {
|
|
11891
|
+
type: "string",
|
|
11892
|
+
minLength: 1,
|
|
11893
|
+
maxLength: 500
|
|
11894
|
+
}
|
|
11895
|
+
},
|
|
11896
|
+
default: {
|
|
11897
|
+
description: "The identifier of a registered profile that documents naming no profile are held to. Declaring one also refuses documents that name an unregistered profile, and version 1 documents.",
|
|
11898
|
+
type: "string",
|
|
11899
|
+
minLength: 1,
|
|
11900
|
+
maxLength: 200
|
|
11901
|
+
},
|
|
11902
|
+
appearance: {
|
|
11903
|
+
description: "The project's colours for kinds, by vocabulary. A name in one map does not colour the other vocabulary; a kind not named keeps its automatic colour.",
|
|
11904
|
+
type: "object",
|
|
11905
|
+
additionalProperties: false,
|
|
11906
|
+
properties: {
|
|
11907
|
+
kinds: {
|
|
11908
|
+
type: "object",
|
|
11909
|
+
maxProperties: 64,
|
|
11910
|
+
propertyNames: {
|
|
11911
|
+
type: "string",
|
|
11912
|
+
minLength: 1,
|
|
11913
|
+
maxLength: 100
|
|
11914
|
+
},
|
|
11915
|
+
additionalProperties: {
|
|
11916
|
+
$ref: "#/$defs/kindAppearance"
|
|
11917
|
+
},
|
|
11918
|
+
description: "Kinds of elements, participants, table rows and timeline items."
|
|
11919
|
+
},
|
|
11920
|
+
relationshipKinds: {
|
|
11921
|
+
type: "object",
|
|
11922
|
+
maxProperties: 64,
|
|
11923
|
+
propertyNames: {
|
|
11924
|
+
type: "string",
|
|
11925
|
+
minLength: 1,
|
|
11926
|
+
maxLength: 100
|
|
11927
|
+
},
|
|
11928
|
+
additionalProperties: {
|
|
11929
|
+
$ref: "#/$defs/kindAppearance"
|
|
11930
|
+
},
|
|
11931
|
+
description: "Kinds of relationships and table relations."
|
|
11932
|
+
}
|
|
11933
|
+
}
|
|
11934
|
+
}
|
|
11935
|
+
},
|
|
11936
|
+
$defs: {
|
|
11937
|
+
kindAppearance: {
|
|
11938
|
+
description: "How one kind is drawn. Colour only; the renderer derives lighter fills from it.",
|
|
11939
|
+
type: "object",
|
|
11940
|
+
additionalProperties: false,
|
|
11941
|
+
required: [
|
|
11942
|
+
"color"
|
|
11943
|
+
],
|
|
11944
|
+
properties: {
|
|
11945
|
+
color: {
|
|
11946
|
+
description: "A six-digit hexadecimal colour, #rrggbb.",
|
|
11947
|
+
type: "string",
|
|
11948
|
+
pattern: "^#[0-9a-fA-F]{6}$"
|
|
11949
|
+
}
|
|
11950
|
+
}
|
|
11951
|
+
}
|
|
11952
|
+
}
|
|
11953
|
+
};
|
|
11954
|
+
|
|
10193
11955
|
// shared/src/structuredExchangeProfileValidation.ts
|
|
10194
11956
|
var profileCheck;
|
|
10195
11957
|
var registryCheck;
|
|
11958
|
+
var registryCheckV2;
|
|
10196
11959
|
function segment(name) {
|
|
10197
11960
|
return name.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
10198
11961
|
}
|
|
@@ -10225,27 +11988,27 @@ function profileRuleIssues(profile) {
|
|
|
10225
11988
|
for (const list of ["elementKinds", "relationshipKinds"]) {
|
|
10226
11989
|
const seenKinds = /* @__PURE__ */ new Map();
|
|
10227
11990
|
(profile[list] ?? []).forEach((declaration, k) => {
|
|
10228
|
-
const
|
|
11991
|
+
const at = `/${list}/${k}`;
|
|
10229
11992
|
declared[list].add(declaration.kind);
|
|
10230
11993
|
const firstKind = seenKinds.get(declaration.kind);
|
|
10231
11994
|
if (firstKind === void 0) seenKinds.set(declaration.kind, k);
|
|
10232
11995
|
else {
|
|
10233
11996
|
issues.push({
|
|
10234
11997
|
rule: "profile-format/duplicate-kind",
|
|
10235
|
-
path: `${
|
|
11998
|
+
path: `${at}/kind`,
|
|
10236
11999
|
message: `kind "${declaration.kind}" is already declared at /${list}/${firstKind}; declare each kind once, with all its attributes`
|
|
10237
12000
|
});
|
|
10238
12001
|
}
|
|
10239
12002
|
const seenAttributes = /* @__PURE__ */ new Map();
|
|
10240
12003
|
(declaration.attributes ?? []).forEach((attribute, a) => {
|
|
10241
|
-
const attributeAt = `${
|
|
12004
|
+
const attributeAt = `${at}/attributes/${a}`;
|
|
10242
12005
|
const firstAttribute = seenAttributes.get(attribute.name);
|
|
10243
12006
|
if (firstAttribute === void 0) seenAttributes.set(attribute.name, a);
|
|
10244
12007
|
else {
|
|
10245
12008
|
issues.push({
|
|
10246
12009
|
rule: "profile-format/duplicate-attribute",
|
|
10247
12010
|
path: `${attributeAt}/name`,
|
|
10248
|
-
message: `kind "${declaration.kind}" already declares attribute "${attribute.name}" at ${
|
|
12011
|
+
message: `kind "${declaration.kind}" already declares attribute "${attribute.name}" at ${at}/attributes/${firstAttribute}`
|
|
10249
12012
|
});
|
|
10250
12013
|
}
|
|
10251
12014
|
if (attribute.type === "enumeration") {
|
|
@@ -10290,12 +12053,12 @@ function profileRuleIssues(profile) {
|
|
|
10290
12053
|
for (const end of ["from", "to"]) {
|
|
10291
12054
|
const seen = /* @__PURE__ */ new Map();
|
|
10292
12055
|
declaration[end]?.forEach((kind, position) => {
|
|
10293
|
-
const
|
|
12056
|
+
const at = `/relationshipKinds/${k}/${end}/${position}`;
|
|
10294
12057
|
const first = seen.get(kind);
|
|
10295
12058
|
if (first !== void 0) {
|
|
10296
12059
|
issues.push({
|
|
10297
12060
|
rule: "profile-format/repeated-end-kind",
|
|
10298
|
-
path:
|
|
12061
|
+
path: at,
|
|
10299
12062
|
message: `relationship kind "${declaration.kind}" already names "${kind}" at /relationshipKinds/${k}/${end}/${first}`
|
|
10300
12063
|
});
|
|
10301
12064
|
return;
|
|
@@ -10304,7 +12067,7 @@ function profileRuleIssues(profile) {
|
|
|
10304
12067
|
if (declared.elementKinds.has(kind)) return;
|
|
10305
12068
|
issues.push({
|
|
10306
12069
|
rule: "profile-format/unresolved-end-kind",
|
|
10307
|
-
path:
|
|
12070
|
+
path: at,
|
|
10308
12071
|
message: `relationship kind "${declaration.kind}" allows element kind "${kind}" at its ${end === "from" ? "source" : "target"}, which this profile does not declare; it declares ${declaredElementKinds}` + (declared.relationshipKinds.has(kind) ? ` ("${kind}" is a relationship kind here, and a relationship joins elements)` : "")
|
|
10309
12072
|
});
|
|
10310
12073
|
});
|
|
@@ -10312,20 +12075,20 @@ function profileRuleIssues(profile) {
|
|
|
10312
12075
|
});
|
|
10313
12076
|
const seenViewpoints = /* @__PURE__ */ new Map();
|
|
10314
12077
|
(profile.viewpoints ?? []).forEach((viewpoint, index3) => {
|
|
10315
|
-
const
|
|
12078
|
+
const at = `/viewpoints/${index3}`;
|
|
10316
12079
|
const first = seenViewpoints.get(viewpoint.id);
|
|
10317
12080
|
if (first === void 0) seenViewpoints.set(viewpoint.id, index3);
|
|
10318
12081
|
else {
|
|
10319
12082
|
issues.push({
|
|
10320
12083
|
rule: "profile-format/duplicate-viewpoint-identifier",
|
|
10321
|
-
path: `${
|
|
12084
|
+
path: `${at}/id`,
|
|
10322
12085
|
message: `viewpoint "${viewpoint.id}" is already declared at /viewpoints/${first}`
|
|
10323
12086
|
});
|
|
10324
12087
|
}
|
|
10325
12088
|
if (viewpoint.elementKinds === void 0 && viewpoint.relationshipKinds === void 0) {
|
|
10326
12089
|
issues.push({
|
|
10327
12090
|
rule: "profile-format/empty-viewpoint",
|
|
10328
|
-
path:
|
|
12091
|
+
path: at,
|
|
10329
12092
|
message: `viewpoint "${viewpoint.id}" retains no kind; name elementKinds, relationshipKinds, or both`
|
|
10330
12093
|
});
|
|
10331
12094
|
}
|
|
@@ -10338,7 +12101,7 @@ function profileRuleIssues(profile) {
|
|
|
10338
12101
|
if (declared[list].has(kind)) return;
|
|
10339
12102
|
issues.push({
|
|
10340
12103
|
rule: "profile-format/unresolved-viewpoint-kind",
|
|
10341
|
-
path: `${
|
|
12104
|
+
path: `${at}/${list}/${position}`,
|
|
10342
12105
|
message: `viewpoint "${viewpoint.id}" retains ${noun} kind "${kind}", which this profile does not declare` + (declared[otherList].has(kind) ? ` (it is a ${otherNoun} kind here, which is a different vocabulary)` : "")
|
|
10343
12106
|
});
|
|
10344
12107
|
});
|
|
@@ -10356,19 +12119,62 @@ function validateProfile(value) {
|
|
|
10356
12119
|
return rules.length > 0 ? { valid: false, issues: rules } : { valid: true, profile, issues: [] };
|
|
10357
12120
|
}
|
|
10358
12121
|
function validateRegistry(value) {
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
if (
|
|
12122
|
+
const declared = value?.schema;
|
|
12123
|
+
let check;
|
|
12124
|
+
if (declared === STRUCTURED_EXCHANGE_PROFILE_REGISTRY_SCHEMA_V2) {
|
|
12125
|
+
registryCheckV2 ??= Compile(unwrapSchemaModule(structured_exchange_profile_registry_2_default));
|
|
12126
|
+
check = registryCheckV2;
|
|
12127
|
+
} else {
|
|
12128
|
+
registryCheck ??= Compile(unwrapSchemaModule(structured_exchange_profile_registry_1_default));
|
|
12129
|
+
check = registryCheck;
|
|
12130
|
+
}
|
|
12131
|
+
const schema2 = schemaIssues(check, value, "registry");
|
|
12132
|
+
if (schema2.length > 0) return { valid: false, issues: preciseAppearanceIssues(value, schema2) };
|
|
10362
12133
|
const registry = value;
|
|
10363
12134
|
const issues = [];
|
|
10364
12135
|
const seenPaths = /* @__PURE__ */ new Map();
|
|
10365
|
-
registry.profiles.forEach((listed, index3) => {
|
|
12136
|
+
(registry.profiles ?? []).forEach((listed, index3) => {
|
|
10366
12137
|
const first = seenPaths.get(listed);
|
|
10367
12138
|
if (first === void 0) seenPaths.set(listed, index3);
|
|
10368
12139
|
else issues.push({ rule: "registry/repeated-profile-path", path: `/profiles/${index3}`, message: `"${listed}" is already listed at /profiles/${first}` });
|
|
10369
12140
|
});
|
|
10370
12141
|
return issues.length > 0 ? { valid: false, issues } : { valid: true, registry, issues: [] };
|
|
10371
12142
|
}
|
|
12143
|
+
function preciseAppearanceIssues(value, issues) {
|
|
12144
|
+
const appearance = value?.appearance;
|
|
12145
|
+
if (appearance === null || typeof appearance !== "object") return issues;
|
|
12146
|
+
const precise = [];
|
|
12147
|
+
const explained = /* @__PURE__ */ new Set();
|
|
12148
|
+
for (const vocabulary of ["kinds", "relationshipKinds"]) {
|
|
12149
|
+
const map = appearance[vocabulary];
|
|
12150
|
+
if (map === null || typeof map !== "object" || Array.isArray(map)) continue;
|
|
12151
|
+
const at = `/appearance/${vocabulary}`;
|
|
12152
|
+
for (const [kind, entry] of Object.entries(map)) {
|
|
12153
|
+
const where = `${at}/${segment(kind)}`;
|
|
12154
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) {
|
|
12155
|
+
precise.push({ rule: "registry/schema/type", path: where, message: `the appearance of "${kind}" must be an object declaring a color` });
|
|
12156
|
+
explained.add(at);
|
|
12157
|
+
continue;
|
|
12158
|
+
}
|
|
12159
|
+
const { color, ...rest } = entry;
|
|
12160
|
+
if (typeof color !== "string" || !/^#[0-9a-fA-F]{6}$/.test(color)) {
|
|
12161
|
+
precise.push({
|
|
12162
|
+
rule: "registry/appearance/color",
|
|
12163
|
+
path: `${where}/color`,
|
|
12164
|
+
message: `the colour of "${kind}" must be six hexadecimal digits after "#", such as "#dc2626"; got ${JSON.stringify(color)}`
|
|
12165
|
+
});
|
|
12166
|
+
explained.add(at);
|
|
12167
|
+
}
|
|
12168
|
+
for (const name of Object.keys(rest)) {
|
|
12169
|
+
precise.push({ rule: "registry/schema/additionalProperties", path: `${where}/${segment(name)}`, message: `"${name}" is not part of a kind's appearance; only "color" is` });
|
|
12170
|
+
explained.add(at);
|
|
12171
|
+
}
|
|
12172
|
+
}
|
|
12173
|
+
}
|
|
12174
|
+
if (precise.length === 0) return issues;
|
|
12175
|
+
const within = (issue) => [...explained].some((map) => issue.path === map || issue.path.startsWith(`${map}/`));
|
|
12176
|
+
return [...issues.filter((issue) => !within(issue)), ...precise];
|
|
12177
|
+
}
|
|
10372
12178
|
function registryConsistencyIssues(registry, loaded) {
|
|
10373
12179
|
const issues = [];
|
|
10374
12180
|
const firstById = /* @__PURE__ */ new Map();
|
|
@@ -10384,7 +12190,7 @@ function registryConsistencyIssues(registry, loaded) {
|
|
|
10384
12190
|
}
|
|
10385
12191
|
});
|
|
10386
12192
|
if (registry.default !== void 0 && !firstById.has(registry.default)) {
|
|
10387
|
-
const registered = [...firstById.keys()].map((id) => `"${id}"`).join(", ");
|
|
12193
|
+
const registered = firstById.size === 0 ? "none" : [...firstById.keys()].map((id) => `"${id}"`).join(", ");
|
|
10388
12194
|
issues.push({
|
|
10389
12195
|
rule: "registry/unregistered-default",
|
|
10390
12196
|
path: "/default",
|
|
@@ -10592,7 +12398,7 @@ function selectProfile(envelope, context) {
|
|
|
10592
12398
|
} else {
|
|
10593
12399
|
selected = fallback;
|
|
10594
12400
|
}
|
|
10595
|
-
if (selected === void 0 || kind === "sequence") return { outcome: "unconstrained" };
|
|
12401
|
+
if (selected === void 0 || kind === "sequence" || kind === "timeline") return { outcome: "unconstrained" };
|
|
10596
12402
|
return { outcome: "held", profile: selected };
|
|
10597
12403
|
}
|
|
10598
12404
|
function checkAgainstProfile(envelope, profile, options = {}) {
|
|
@@ -10663,18 +12469,18 @@ function checkAgainstProfile(envelope, profile, options = {}) {
|
|
|
10663
12469
|
if (Array.isArray(value)) value.forEach((item, index3) => checkScalar(attribute, kind, item, `${path3}/${index3}`));
|
|
10664
12470
|
else checkScalar(attribute, kind, value, path3);
|
|
10665
12471
|
}
|
|
10666
|
-
function checkItem(item,
|
|
12472
|
+
function checkItem(item, at, vocabulary, noun) {
|
|
10667
12473
|
const kinds = vocabularies[vocabulary];
|
|
10668
12474
|
const other = vocabularies[vocabulary === "element" ? "relationship" : "element"];
|
|
10669
12475
|
const set = item.set ?? void 0;
|
|
10670
12476
|
const setKind = typeof set?.kind === "string" ? set.kind : void 0;
|
|
10671
12477
|
const ownKind = typeof item.kind === "string" ? item.kind : void 0;
|
|
10672
12478
|
const kind = setKind ?? ownKind;
|
|
10673
|
-
const kindAt = setKind !== void 0 ? `${
|
|
12479
|
+
const kindAt = setKind !== void 0 ? `${at}/set/kind` : `${at}/kind`;
|
|
10674
12480
|
if (kind === void 0) {
|
|
10675
12481
|
issues.push({
|
|
10676
12482
|
rule: "profile/missing-kind",
|
|
10677
|
-
path:
|
|
12483
|
+
path: at,
|
|
10678
12484
|
message: `this ${noun} carries no kind; profile "${profile.id}" holds every ${noun} to one of its ${vocabulary} kinds: ${quoted([...kinds.keys()])}` + (item.ref !== void 0 ? ". A changed item states its kind too, so its attributes can be checked" : "")
|
|
10679
12485
|
});
|
|
10680
12486
|
return;
|
|
@@ -10705,8 +12511,8 @@ function checkAgainstProfile(envelope, profile, options = {}) {
|
|
|
10705
12511
|
checkValue(attribute, kind, value, path3);
|
|
10706
12512
|
}
|
|
10707
12513
|
};
|
|
10708
|
-
checkAttributes(item.attributes, `${
|
|
10709
|
-
checkAttributes(set?.attributes, `${
|
|
12514
|
+
checkAttributes(item.attributes, `${at}/attributes`);
|
|
12515
|
+
checkAttributes(set?.attributes, `${at}/set/attributes`);
|
|
10710
12516
|
const required = (declaration.attributes ?? []).filter((attribute) => attribute.required === true);
|
|
10711
12517
|
const whole = !proposal || item.ref === void 0;
|
|
10712
12518
|
if (whole) {
|
|
@@ -10715,7 +12521,7 @@ function checkAgainstProfile(envelope, profile, options = {}) {
|
|
|
10715
12521
|
if (Object.hasOwn(carried, attribute.name)) continue;
|
|
10716
12522
|
issues.push({
|
|
10717
12523
|
rule: "profile/missing-required-attribute",
|
|
10718
|
-
path:
|
|
12524
|
+
path: at,
|
|
10719
12525
|
message: `kind "${kind}" requires attribute "${attribute.name}", and this ${noun} does not carry it`
|
|
10720
12526
|
});
|
|
10721
12527
|
}
|
|
@@ -10726,7 +12532,7 @@ function checkAgainstProfile(envelope, profile, options = {}) {
|
|
|
10726
12532
|
if (!required.some((attribute) => attribute.name === name)) return;
|
|
10727
12533
|
issues.push({
|
|
10728
12534
|
rule: "profile/required-attribute-removed",
|
|
10729
|
-
path: `${
|
|
12535
|
+
path: `${at}/set/removeAttributes/${index3}`,
|
|
10730
12536
|
message: `attribute "${String(name)}" is required on kind "${kind}", so a proposal cannot remove it`
|
|
10731
12537
|
});
|
|
10732
12538
|
});
|
|
@@ -10952,17 +12758,17 @@ function formIssues(file) {
|
|
|
10952
12758
|
const issues = [];
|
|
10953
12759
|
const seen = /* @__PURE__ */ new Map();
|
|
10954
12760
|
file.rules.forEach((rule, index3) => {
|
|
10955
|
-
const
|
|
12761
|
+
const at = `/rules/${index3}`;
|
|
10956
12762
|
const first = seen.get(rule.id);
|
|
10957
12763
|
if (first === void 0) seen.set(rule.id, index3);
|
|
10958
12764
|
else {
|
|
10959
|
-
issues.push({ rule: "rules-format/duplicate-rule-identifier", path: `${
|
|
12765
|
+
issues.push({ rule: "rules-format/duplicate-rule-identifier", path: `${at}/id`, message: `rule "${rule.id}" is already declared at /rules/${first}` });
|
|
10960
12766
|
}
|
|
10961
12767
|
const { element, relationship } = rule;
|
|
10962
12768
|
if (element === void 0 === (relationship === void 0)) {
|
|
10963
12769
|
issues.push({
|
|
10964
12770
|
rule: "rules-format/rule-form",
|
|
10965
|
-
path:
|
|
12771
|
+
path: at,
|
|
10966
12772
|
message: `rule "${rule.id}" must name exactly one of "element" (an item rule) or "relationship" (a link rule)`
|
|
10967
12773
|
});
|
|
10968
12774
|
return;
|
|
@@ -10973,7 +12779,7 @@ function formIssues(file) {
|
|
|
10973
12779
|
];
|
|
10974
12780
|
for (const [name, clause] of clauses) {
|
|
10975
12781
|
if (clause === void 0 || clause === "forbidden") continue;
|
|
10976
|
-
const clauseAt = `${
|
|
12782
|
+
const clauseAt = `${at}/${name}`;
|
|
10977
12783
|
if (!isConditionSet(clause)) continue;
|
|
10978
12784
|
if (name === "then" && Object.keys(clause).length === 0) {
|
|
10979
12785
|
issues.push({ rule: "rules-format/empty-then", path: clauseAt, message: `rule "${rule.id}" requires nothing; name conditions, or "forbidden"` });
|
|
@@ -11035,9 +12841,9 @@ function rulesAgainstProfile(file, profile) {
|
|
|
11035
12841
|
const issues = [];
|
|
11036
12842
|
const elementKinds = new Map((profile.elementKinds ?? []).map((declaration) => [declaration.kind, declaration]));
|
|
11037
12843
|
const relationshipKinds = new Map((profile.relationshipKinds ?? []).map((declaration) => [declaration.kind, declaration]));
|
|
11038
|
-
const checkConditions = (rule, conditions,
|
|
12844
|
+
const checkConditions = (rule, conditions, at, kinds, declaredEnd) => {
|
|
11039
12845
|
for (const [name, values] of Object.entries(conditions ?? {})) {
|
|
11040
|
-
const attributeAt = `${
|
|
12846
|
+
const attributeAt = `${at}/${segment3(name)}`;
|
|
11041
12847
|
const declarations = kinds.map((kind) => (elementKinds.get(kind)?.attributes ?? []).find((attribute) => attribute.name === name)).filter((attribute) => attribute !== void 0);
|
|
11042
12848
|
if (declarations.length === 0) {
|
|
11043
12849
|
issues.push({
|
|
@@ -11068,24 +12874,24 @@ function rulesAgainstProfile(file, profile) {
|
|
|
11068
12874
|
}
|
|
11069
12875
|
};
|
|
11070
12876
|
file.rules.forEach((rule, index3) => {
|
|
11071
|
-
const
|
|
12877
|
+
const at = `/rules/${index3}`;
|
|
11072
12878
|
if (rule.element !== void 0) {
|
|
11073
12879
|
if (!elementKinds.has(rule.element)) {
|
|
11074
12880
|
issues.push({
|
|
11075
12881
|
rule: "rules-format/undeclared-kind",
|
|
11076
|
-
path: `${
|
|
12882
|
+
path: `${at}/element`,
|
|
11077
12883
|
message: `rule "${rule.id}" applies to element kind "${rule.element}", which profile "${profile.id}" does not declare; it declares ${quoted2([...elementKinds.keys()])}`
|
|
11078
12884
|
});
|
|
11079
12885
|
return;
|
|
11080
12886
|
}
|
|
11081
|
-
checkConditions(rule, rule.when, `${
|
|
11082
|
-
if (rule.then !== "forbidden") checkConditions(rule, rule.then, `${
|
|
12887
|
+
checkConditions(rule, rule.when, `${at}/when`, [rule.element]);
|
|
12888
|
+
if (rule.then !== "forbidden") checkConditions(rule, rule.then, `${at}/then`, [rule.element]);
|
|
11083
12889
|
return;
|
|
11084
12890
|
}
|
|
11085
12891
|
if (!relationshipKinds.has(rule.relationship)) {
|
|
11086
12892
|
issues.push({
|
|
11087
12893
|
rule: "rules-format/undeclared-kind",
|
|
11088
|
-
path: `${
|
|
12894
|
+
path: `${at}/relationship`,
|
|
11089
12895
|
message: `rule "${rule.id}" applies to relationship kind "${rule.relationship}", which profile "${profile.id}" does not declare; it declares ${quoted2([...relationshipKinds.keys()])}`
|
|
11090
12896
|
});
|
|
11091
12897
|
return;
|
|
@@ -11101,7 +12907,7 @@ function rulesAgainstProfile(file, profile) {
|
|
|
11101
12907
|
for (const [side, position] of [["from", "source"], ["to", "target"]]) {
|
|
11102
12908
|
const allowed = declaration?.[side];
|
|
11103
12909
|
const described = allowed === void 0 ? void 0 : `${position} of "${rule.relationship}"`;
|
|
11104
|
-
checkConditions(rule, clause[side], `${
|
|
12910
|
+
checkConditions(rule, clause[side], `${at}/${name}/${side}`, allowed ?? anyElement, described);
|
|
11105
12911
|
}
|
|
11106
12912
|
}
|
|
11107
12913
|
});
|
|
@@ -11207,7 +13013,7 @@ async function readProjectRegistry(projectRoot, registryPath = STRUCTURED_EXCHAN
|
|
|
11207
13013
|
const files = [];
|
|
11208
13014
|
const issues = [];
|
|
11209
13015
|
const loaded = [];
|
|
11210
|
-
for (const [index3, listed] of registry.profiles.entries()) {
|
|
13016
|
+
for (const [index3, listed] of (registry.profiles ?? []).entries()) {
|
|
11211
13017
|
const read = await readConfinedJson(root, listed, STRUCTURED_EXCHANGE_PROFILE_CEILINGS.profileBytes, "profile-format");
|
|
11212
13018
|
if (read.ok === "missing") {
|
|
11213
13019
|
issues.push({ rule: "registry/missing-profile", path: `/profiles/${index3}`, message: `"${listed}" does not exist`, file: registryFile });
|
|
@@ -11269,7 +13075,8 @@ async function readProjectRegistry(projectRoot, registryPath = STRUCTURED_EXCHAN
|
|
|
11269
13075
|
state: "usable",
|
|
11270
13076
|
context: { profiles, ...registry.default !== void 0 ? { default: registry.default } : {}, ...rules.size > 0 ? { rules } : {} },
|
|
11271
13077
|
files,
|
|
11272
|
-
filesByProfile
|
|
13078
|
+
filesByProfile,
|
|
13079
|
+
...registry.appearance !== void 0 ? { appearance: registry.appearance } : {}
|
|
11273
13080
|
};
|
|
11274
13081
|
}
|
|
11275
13082
|
|
|
@@ -12370,7 +14177,7 @@ function rulePatterns(profile, rules, sources) {
|
|
|
12370
14177
|
}
|
|
12371
14178
|
|
|
12372
14179
|
// shared/bin/validate-structured-exchange.mjs
|
|
12373
|
-
var VERSION = `validate-structured-exchange ${false ? "development" : "0.
|
|
14180
|
+
var VERSION = `validate-structured-exchange ${false ? "development" : "0.34.0"}`;
|
|
12374
14181
|
var USAGE = `validate-structured-exchange [file]
|
|
12375
14182
|
validate-structured-exchange --profile <profile.json> [file]
|
|
12376
14183
|
validate-structured-exchange --check-profile <profile.json>
|