@openship/protocol 0.0.3 → 0.1.1
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/README.md +4 -0
- package/dist/package-meta.json +2 -2
- package/dist/skill/SKILL.md +1 -1
- package/dist/skill/references/examples/invalid/systems-ownership.json +29 -7
- package/dist/skill/references/examples/invalid/systems.json +63 -12
- package/dist/skill/references/examples/valid/systems-layered.json +353 -0
- package/dist/skill/references/examples/valid/systems.json +140 -25
- package/dist/skill/references/openship-systems.md +87 -69
- package/dist/skill/references/openship.md +1 -1
- package/dist/skill/references/schemas/systems.schema.json +554 -57
- package/package.json +1 -1
- package/src/index.d.ts +12 -4
- package/src/index.js +130 -39
|
@@ -6,11 +6,31 @@
|
|
|
6
6
|
"openship": "1.0",
|
|
7
7
|
"capability": "sources",
|
|
8
8
|
"digest": "sha256:1d322539e651a3c2d7c51eb8b33160627395b9601bff909e599771b806d9e565",
|
|
9
|
-
"project": {
|
|
10
|
-
|
|
9
|
+
"project": {
|
|
10
|
+
"name": "Example",
|
|
11
|
+
"description": "An example OpenShip project."
|
|
12
|
+
},
|
|
13
|
+
"totals": {
|
|
14
|
+
"files": 2,
|
|
15
|
+
"bytes": 53
|
|
16
|
+
},
|
|
11
17
|
"files": [
|
|
12
|
-
{
|
|
13
|
-
|
|
18
|
+
{
|
|
19
|
+
"path": "app/page.js",
|
|
20
|
+
"size": 34,
|
|
21
|
+
"sha256": "6ce070542590adb63fd9621ff65be91446f8bd9b65465cda5e4ec43e5d86dc5e",
|
|
22
|
+
"encoding": "utf-8",
|
|
23
|
+
"mediaType": "text/plain; charset=utf-8",
|
|
24
|
+
"type": "file"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"path": "package.json",
|
|
28
|
+
"size": 19,
|
|
29
|
+
"sha256": "9579cf52285b23b618b615d704b19d04ff591ae513f6ae34ef37e2b9a067cb12",
|
|
30
|
+
"encoding": "utf-8",
|
|
31
|
+
"mediaType": "application/json; charset=utf-8",
|
|
32
|
+
"type": "file"
|
|
33
|
+
}
|
|
14
34
|
]
|
|
15
35
|
},
|
|
16
36
|
"bundle": {
|
|
@@ -18,38 +38,133 @@
|
|
|
18
38
|
"capability": "sources",
|
|
19
39
|
"digest": "sha256:1d322539e651a3c2d7c51eb8b33160627395b9601bff909e599771b806d9e565",
|
|
20
40
|
"files": {
|
|
21
|
-
"app/page.js": {
|
|
22
|
-
|
|
41
|
+
"app/page.js": {
|
|
42
|
+
"encoding": "utf-8",
|
|
43
|
+
"content": "export default function Page() {}\n"
|
|
44
|
+
},
|
|
45
|
+
"package.json": {
|
|
46
|
+
"encoding": "utf-8",
|
|
47
|
+
"content": "{\"name\":\"example\"}\n"
|
|
48
|
+
}
|
|
23
49
|
}
|
|
24
50
|
}
|
|
25
51
|
},
|
|
26
52
|
"system": {
|
|
27
53
|
"id": "example-system",
|
|
28
54
|
"name": "Example system",
|
|
29
|
-
"rootNodeId": "s.root",
|
|
30
|
-
"nodes": [
|
|
31
|
-
{ "id": "s.root", "kind": "Root", "name": "Example", "metadata": { "ownership": "first_party" } },
|
|
32
|
-
{ "id": "h.runtime", "kind": "Host", "name": "Application runtime", "parentId": "s.root", "metadata": { "ownership": "first_party" } },
|
|
33
|
-
{ "id": "p.web", "kind": "Process", "name": "Web process", "parentId": "h.runtime", "sourceSelectors": ["app/**"], "metadata": { "ownership": "first_party" } },
|
|
34
|
-
{ "id": "l.config", "kind": "Library", "name": "Project configuration", "sourceSelectors": ["package.json"], "metadata": { "ownership": "third_party" } }
|
|
35
|
-
],
|
|
36
|
-
"edges": [
|
|
37
|
-
{ "id": "e.web.config", "type": "Dependency", "fromNodeId": "p.web", "toNodeId": "l.config" }
|
|
38
|
-
],
|
|
39
55
|
"context": {
|
|
40
|
-
"concerns": [
|
|
56
|
+
"concerns": [
|
|
57
|
+
"Interfaces",
|
|
58
|
+
"Implementation"
|
|
59
|
+
],
|
|
41
60
|
"documents": [
|
|
42
|
-
{
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
{
|
|
62
|
+
"kind": "Document",
|
|
63
|
+
"hash": "sha256:77760f8cb9fdaaadd3c22612d97fba630f78730c8d750c6cce02754b689b11da",
|
|
64
|
+
"title": "API contract",
|
|
65
|
+
"language": "en",
|
|
66
|
+
"text": "The API returns JSON."
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"kind": "Skill",
|
|
70
|
+
"hash": "sha256:bae5f866c2994c1cec740965e45935920376a2df1fb933e798c3e2c3b8c0e391",
|
|
71
|
+
"title": "Node implementation",
|
|
72
|
+
"language": "en",
|
|
73
|
+
"text": "Use Node.js."
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"kind": "Prompt",
|
|
77
|
+
"hash": "sha256:416a3efe045d89a00fa0cca4516b8bdd442a8f65a42e35a5c102067f3ecb429d",
|
|
78
|
+
"title": "System prompt",
|
|
79
|
+
"language": "en",
|
|
80
|
+
"text": "Keep changes minimal."
|
|
81
|
+
}
|
|
45
82
|
],
|
|
46
83
|
"matrix": [
|
|
47
|
-
{
|
|
84
|
+
{
|
|
85
|
+
"nodeId": "p.web",
|
|
86
|
+
"concern": "Interfaces",
|
|
87
|
+
"documentRefs": [
|
|
88
|
+
"sha256:77760f8cb9fdaaadd3c22612d97fba630f78730c8d750c6cce02754b689b11da"
|
|
89
|
+
],
|
|
90
|
+
"skillRefs": []
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"systemPromptRefs": [
|
|
94
|
+
"sha256:416a3efe045d89a00fa0cca4516b8bdd442a8f65a42e35a5c102067f3ecb429d"
|
|
48
95
|
],
|
|
49
|
-
"systemPromptRefs": ["sha256:416a3efe045d89a00fa0cca4516b8bdd442a8f65a42e35a5c102067f3ecb429d"],
|
|
50
96
|
"artifacts": [
|
|
51
|
-
{
|
|
97
|
+
{
|
|
98
|
+
"id": "a.web.code",
|
|
99
|
+
"nodeId": "p.web",
|
|
100
|
+
"concern": "Implementation",
|
|
101
|
+
"type": "Code",
|
|
102
|
+
"sourcePaths": [
|
|
103
|
+
"app/page.js"
|
|
104
|
+
]
|
|
105
|
+
}
|
|
52
106
|
]
|
|
53
|
-
}
|
|
54
|
-
|
|
107
|
+
},
|
|
108
|
+
"layers": [
|
|
109
|
+
{
|
|
110
|
+
"rootNodeId": "s.root",
|
|
111
|
+
"nodes": [
|
|
112
|
+
{
|
|
113
|
+
"id": "s.root",
|
|
114
|
+
"kind": "Root",
|
|
115
|
+
"name": "Example",
|
|
116
|
+
"metadata": {
|
|
117
|
+
"ownership": "first_party"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": "h.runtime",
|
|
122
|
+
"kind": "Host",
|
|
123
|
+
"name": "Application runtime",
|
|
124
|
+
"parentId": "s.root",
|
|
125
|
+
"metadata": {
|
|
126
|
+
"ownership": "first_party"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"id": "p.web",
|
|
131
|
+
"kind": "Process",
|
|
132
|
+
"name": "Web process",
|
|
133
|
+
"parentId": "h.runtime",
|
|
134
|
+
"sourceSelectors": [
|
|
135
|
+
"app/**"
|
|
136
|
+
],
|
|
137
|
+
"metadata": {
|
|
138
|
+
"ownership": "first_party"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"id": "l.config",
|
|
143
|
+
"kind": "Library",
|
|
144
|
+
"name": "Project configuration",
|
|
145
|
+
"sourceSelectors": [
|
|
146
|
+
"package.json"
|
|
147
|
+
],
|
|
148
|
+
"metadata": {
|
|
149
|
+
"ownership": "third_party"
|
|
150
|
+
},
|
|
151
|
+
"parentId": "s.root"
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
"edges": [
|
|
155
|
+
{
|
|
156
|
+
"id": "e.web.config",
|
|
157
|
+
"type": "Dependency",
|
|
158
|
+
"fromNodeId": "p.web",
|
|
159
|
+
"toNodeId": "l.config"
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
"id": "technical",
|
|
163
|
+
"name": "Technical",
|
|
164
|
+
"role": "technical"
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
"refinements": []
|
|
168
|
+
},
|
|
169
|
+
"systemsVersion": "2.0"
|
|
55
170
|
}
|
|
@@ -1,98 +1,118 @@
|
|
|
1
|
-
# OpenShip Systems
|
|
1
|
+
# OpenShip Systems 2.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Systems publishes one JSON document containing a complete Sources snapshot, ordered design layers, explicit implementation mappings, optional instance descriptions, and shared context. Systems 2.0 replaces the previous single-graph format; legacy Systems documents are unsupported. Sources and Changes remain OpenShip 1.0.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Top-level document
|
|
5
|
+
## Envelope and system
|
|
8
6
|
|
|
9
7
|
```json
|
|
10
8
|
{
|
|
11
9
|
"openship": "1.0",
|
|
12
10
|
"capability": "systems",
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
"bundle": { "openship": "1.0", "capability": "sources", "digest": "sha256:...", "files": {} }
|
|
16
|
-
},
|
|
11
|
+
"systemsVersion": "2.0",
|
|
12
|
+
"source": { "manifest": {}, "bundle": {} },
|
|
17
13
|
"system": {
|
|
18
|
-
"id": "example
|
|
19
|
-
"name": "Example
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
14
|
+
"id": "example",
|
|
15
|
+
"name": "Example",
|
|
16
|
+
"layers": [],
|
|
17
|
+
"refinements": [],
|
|
18
|
+
"instances": []
|
|
23
19
|
}
|
|
24
20
|
}
|
|
25
21
|
```
|
|
26
22
|
|
|
27
|
-
`source.manifest` and `source.bundle` MUST
|
|
23
|
+
This illustrates the envelope only: `source.manifest` and `source.bundle` MUST be valid, complete Sources, and `layers` MUST contain at least one layer. See [the complete layered example](examples/valid/systems-layered.json) and [the schema](schemas/systems.schema.json).
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
The old `system.nodes`, `system.edges`, and `system.rootNodeId` members are forbidden. Metadata and unrecognized extension members MUST be preserved. Self-containment covers the design and source bytes; external secret and runtime-state references need not resolve within the document. Consumers MUST NOT interpret validation as proof of deployment or runtime health.
|
|
30
26
|
|
|
31
|
-
##
|
|
27
|
+
## Ordered design layers
|
|
32
28
|
|
|
33
|
-
|
|
29
|
+
Each layer has `id`, `name`, `role`, `rootNodeId`, `nodes`, and `edges`. Array order runs from abstract to concrete. Layer IDs MUST be unique. Roles are `logical`, `technical`, `provider`, or `custom`; roles MAY repeat and standard roles MAY be omitted.
|
|
34
30
|
|
|
35
|
-
|
|
|
31
|
+
| Recommended role | Decisions represented |
|
|
36
32
|
|---|---|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
| logical | Responsibilities, contracts, logical entities and invariants, required initial data. |
|
|
34
|
+
| technical | Frameworks, runtimes, database engines, schemas, migrations and seed scripts. |
|
|
35
|
+
| provider | Hosting providers, intended regions, resources and deployment settings. |
|
|
36
|
+
|
|
37
|
+
Any positive number of layers is supported. Each is an explicit graph, not a generated projection or an inherited configuration overlay. Alternative branches are not defined in this version.
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
## Nodes, containment and sources
|
|
40
|
+
|
|
41
|
+
Node kinds are `Root`, `Block`, `Store`, `Host`, `Container`, `Process`, and `Library`. Block describes a capability; Store describes persistent data. The other kinds describe a system boundary, execution environment, grouped runtime, executable component, and reusable dependency respectively.
|
|
44
42
|
|
|
45
43
|
```json
|
|
46
44
|
{
|
|
47
|
-
"id": "
|
|
48
|
-
"kind": "
|
|
49
|
-
"name": "
|
|
50
|
-
"parentId": "
|
|
51
|
-
"
|
|
52
|
-
"
|
|
45
|
+
"id": "technical.database",
|
|
46
|
+
"kind": "Store",
|
|
47
|
+
"name": "PostgreSQL database",
|
|
48
|
+
"parentId": "technical.root",
|
|
49
|
+
"metadata": { "ownership": "first_party" },
|
|
50
|
+
"sourceSelectors": ["db/**"],
|
|
51
|
+
"configuration": [
|
|
52
|
+
{ "name": "engine", "description": "Database engine", "required": true, "value": "PostgreSQL" }
|
|
53
|
+
]
|
|
53
54
|
}
|
|
54
55
|
```
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
- Node IDs MUST be globally unique across all layers. IDs match `^[A-Za-z0-9._:-]+$`.
|
|
58
|
+
- Each layer MUST have exactly one parentless Root identified by its `rootNodeId`. Every other node, including Library, MUST have a parent in the same layer. Containment MUST be acyclic; no kind-specific parent restrictions apply.
|
|
59
|
+
- Every node MUST declare `metadata.ownership`: `first_party` means publisher-controlled implementation or operation; `third_party` means external control.
|
|
60
|
+
- Optional source selectors select an exact Manifest path or a directory ending in `/**`. No other wildcards are supported. Every selector MUST match at least one Manifest path. Sharing selected paths is allowed.
|
|
61
|
+
|
|
62
|
+
## Connections and refinements
|
|
57
63
|
|
|
58
|
-
-
|
|
59
|
-
- `first_party` means the system publisher owns or controls the component's implementation or operation. `third_party` means an external provider owns or controls it.
|
|
60
|
-
- Exactly one node has kind `Root`; its ID equals `rootNodeId` and it has no parent.
|
|
61
|
-
- Every Host has the Root as parent.
|
|
62
|
-
- Every Container has a Host parent.
|
|
63
|
-
- Every Process has a Host or Container parent.
|
|
64
|
-
- Library has no parent. Process and Library cannot contain children.
|
|
65
|
-
- IDs are unique and match `^[A-Za-z0-9._:-]+$`.
|
|
66
|
-
- The containment graph is acyclic.
|
|
67
|
-
- Metadata is open-ended beyond the required, typed `ownership` member. Boundary, ID prefixes, host naming, and other metadata are not required by v1.
|
|
64
|
+
Layer-local edges have `id`, `type`, `fromNodeId`, `toNodeId`, and optional metadata. IDs MUST be unique within their layer. Endpoints MUST be non-root nodes in that layer. Types are Runtime (cycles allowed), Dataflow (acyclic), and Dependency (acyclic). Endpoint kinds do not constrain the connection type.
|
|
68
65
|
|
|
69
|
-
|
|
66
|
+
Refinements have `id`, `fromNodeId`, and `toNodeId`. IDs MUST be unique within `system.refinements`. The source MUST belong to a later layer than the target. Thus the concrete source implements the more abstract target. Many-to-many mappings, skipped layers, and root mappings are allowed. Refinements neither imply containment nor copy configuration, documents, or runtime edges.
|
|
70
67
|
|
|
71
|
-
|
|
68
|
+
## Domains (optional)
|
|
69
|
+
|
|
70
|
+
`system.domains` MAY declare an ordered list of domains. A domain groups blocks independently of layers, containment, and refinement. Each requires a unique `id`, a nonempty `name`, and `nodeIds`; an optional nonempty `description` explains its scope. Domain IDs use the standard ID grammar. Member IDs MUST be unique within the domain and MUST reference existing nodes anywhere in the system.
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
"domains": [
|
|
74
|
+
{ "id": "web", "name": "Web app", "nodeIds": ["logical.web", "technical.web"] },
|
|
75
|
+
{ "id": "state", "name": "State", "nodeIds": ["technical.web", "technical.database"] }
|
|
76
|
+
]
|
|
77
|
+
```
|
|
72
78
|
|
|
73
|
-
|
|
79
|
+
A node MAY belong to zero, one, or multiple domains. Empty domains and an empty domain list are valid. Membership is explicit and is not inherited through parents or refinements. Omitting domains preserves the existing Systems behavior.
|
|
74
80
|
|
|
75
|
-
|
|
81
|
+
Viewers SHOULD select all domains initially. When filtering, a node matches if it has no domain or belongs to any selected domain. Keep the layer root and ancestors needed to render matching nodes as structural boundaries; this does not make other children visible. Hide connections whose endpoints do not match. Domain filters are presentation controls, not access controls. Keep domain selections across layer changes.
|
|
76
82
|
|
|
77
|
-
|
|
83
|
+
Domains are an additive capability in package 0.1.1. The envelope remains `openship: "1.0"` and `systemsVersion: "2.0"`.
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
## Configuration
|
|
86
|
+
|
|
87
|
+
Nodes and instance bindings MAY contain a `configuration` array. Each entry requires a unique `name`, a nonempty `description`, and a boolean `required` flag. Optional `value` contains JSON data; its absence means unresolved, whereas an explicit null is a supplied value.
|
|
88
|
+
|
|
89
|
+
A sensitive entry uses `sensitive: true` and MUST NOT contain a literal value. An optional `secretRef` is `{ "nodeId": "provider.app", "key": "DATABASE_URL" }`; its node MUST exist and scopes the external key to a component. Any entry with `secretRef` MUST NOT also contain `value`. A secret reference is descriptive: validation does not resolve it or require the external key to exist. Producers MUST classify credentials as sensitive and MUST NOT publish credential values elsewhere in metadata or context.
|
|
90
|
+
|
|
91
|
+
## Instances and database state
|
|
92
|
+
|
|
93
|
+
Instances are separate from design layers. Each has a unique `id`, `name`, `environment`, `layerId`, and `bindings` array. Multiple instances MAY bind the same layer. Each binding refers to a distinct non-root node in that layer and MAY include `resourceId`, configuration, and database `state`. Missing resource IDs are unresolved.
|
|
84
94
|
|
|
85
95
|
```json
|
|
86
96
|
{
|
|
87
|
-
"id": "
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
97
|
+
"id": "production",
|
|
98
|
+
"name": "Production target",
|
|
99
|
+
"environment": "production",
|
|
100
|
+
"layerId": "provider",
|
|
101
|
+
"bindings": [{
|
|
102
|
+
"nodeId": "provider.database",
|
|
103
|
+
"configuration": [{
|
|
104
|
+
"name": "DATABASE_URL", "description": "Database connection", "required": true,
|
|
105
|
+
"sensitive": true, "secretRef": { "nodeId": "provider.database", "key": "DATABASE_URL" }
|
|
106
|
+
}]
|
|
107
|
+
}]
|
|
92
108
|
}
|
|
93
109
|
```
|
|
94
110
|
|
|
95
|
-
|
|
111
|
+
Instance values are explicit observations or supplied descriptions, never implicit overrides of intended design values. Consumers SHOULD display them separately.
|
|
112
|
+
|
|
113
|
+
Only Store bindings may include state. State MAY contain `appliedMigration` and a `snapshot` object with required `ref` and RFC3339 `capturedAt`, and optional `sha256:...` digest. Omitted state means not supplied, not an empty database. References are opaque identifiers; consumers MUST NOT automatically fetch or restore them.
|
|
114
|
+
|
|
115
|
+
Logical entities and invariants belong in shared Data Model documents assigned to Store nodes. Technical schema, migration and seed files use source selectors or Code artifacts. Actual database records are not required. A snapshot reference does not establish that a deployment currently contains that state.
|
|
96
116
|
|
|
97
117
|
## Optional context
|
|
98
118
|
|
|
@@ -139,11 +159,11 @@ kind + "\n" + title + "\n" + language + "\n" + text
|
|
|
139
159
|
|
|
140
160
|
Matrix assignments connect a node, a declared concern, and one or more `Document` or `Skill` hashes. References MUST resolve to documents of the corresponding kind.
|
|
141
161
|
|
|
142
|
-
Prompts are not ordinary matrix references. `systemPromptRefs` belongs to context, references only `Prompt` documents, and applies
|
|
162
|
+
Prompts are not ordinary matrix references. `systemPromptRefs` belongs to context, references only `Prompt` documents, and applies to the overall system.
|
|
143
163
|
|
|
144
164
|
### Artifacts
|
|
145
165
|
|
|
146
|
-
Artifact types are `Summary`, `Docs`, and `Code`. Each belongs to one node and one declared concern.
|
|
166
|
+
Artifact types are `Summary`, `Docs`, and `Code`. Each belongs to one globally identified node and one declared concern.
|
|
147
167
|
|
|
148
168
|
- Summary and Docs carry UTF-8 `text` and optional language.
|
|
149
169
|
- Code carries `sourcePaths` that resolve to Manifest files.
|
|
@@ -153,13 +173,11 @@ Artifact IDs are unique within the system.
|
|
|
153
173
|
|
|
154
174
|
## Validation order
|
|
155
175
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
5. Concern declarations and document hashes.
|
|
163
|
-
6. Matrix, prompt, artifact, and supersession references.
|
|
176
|
+
1. Envelope, Systems version, and embedded Sources integrity.
|
|
177
|
+
2. Layer IDs, global node IDs, roots, containment, configuration and source selectors.
|
|
178
|
+
3. Layer-local edges and cycle checks.
|
|
179
|
+
4. Domain declarations and member references; refinement endpoints and order.
|
|
180
|
+
5. Instance membership, bindings, configuration, state and secret scopes.
|
|
181
|
+
6. Shared document hashes, concerns, matrix/artifact references, prompts and supersession chains.
|
|
164
182
|
|
|
165
|
-
Unknown
|
|
183
|
+
Unknown node, edge, document, artifact or layer-role values are invalid. Use the `custom` role for additional refinement levels.
|
|
@@ -7,7 +7,7 @@ OpenShip is a public interface between a running project and the people or agent
|
|
|
7
7
|
|
|
8
8
|
1. **Sources** publishes an integrity-checked source snapshot.
|
|
9
9
|
2. **Changes** accepts a patch against a Sources digest and produces an isolated candidate origin.
|
|
10
|
-
3. **Systems** publishes a self-contained JSON description of source,
|
|
10
|
+
3. **Systems** publishes a self-contained JSON description of source, ordered design layers, instance bindings, and optional agent context. Systems uses the additional `systemsVersion: "2.0"` discriminator.
|
|
11
11
|
|
|
12
12
|
Sources is the foundation. Changes depends on Sources. Systems embeds a complete Sources snapshot but does not require Changes.
|
|
13
13
|
|