@openship/protocol 0.1.2 → 0.2.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/README.md +2 -0
- package/dist/package-meta.json +2 -2
- package/dist/skill/references/examples/invalid/discovery-mcp.json +7 -1
- package/dist/skill/references/examples/invalid/discovery.json +7 -1
- package/dist/skill/references/examples/invalid/sources-manifest.json +19 -4
- package/dist/skill/references/examples/invalid/systems-ownership.json +4 -1
- package/dist/skill/references/examples/invalid/systems.json +4 -1
- package/dist/skill/references/examples/valid/discovery.json +7 -1
- package/dist/skill/references/examples/valid/sources-manifest.json +11 -3
- package/dist/skill/references/examples/valid/systems-layered.json +4 -1
- package/dist/skill/references/examples/valid/systems.json +4 -1
- package/dist/skill/references/openship-sources.md +5 -2
- package/dist/skill/references/openship.md +5 -2
- package/dist/skill/references/schemas/discovery.schema.json +130 -29
- package/dist/skill/references/schemas/sources-manifest.schema.json +226 -39
- package/package.json +1 -1
- package/src/index.d.ts +3 -2
- package/src/index.js +8 -2
package/README.md
CHANGED
|
@@ -17,3 +17,5 @@ The package contains the exact canonical `skills/openship` schemas, examples, an
|
|
|
17
17
|
Version 0.1.0 replaces legacy Systems with `systemsVersion: "2.0"`: `system.layers`, `system.refinements`, and optional `system.instances`. Sources and Changes retain their 1.0 formats. Consumers must migrate; `validateSystems` explicitly rejects the legacy graph. Each layer is independently renderable, while node IDs and shared context span the entire system.
|
|
18
18
|
|
|
19
19
|
Version 0.1.1 adds optional `system.domains` entries (`id`, `name`, `nodeIds`, optional `description`). Membership may overlap and span layers. Documents without domains remain valid; `openship: "1.0"` and `systemsVersion: "2.0"` do not change.
|
|
20
|
+
|
|
21
|
+
Version 0.2.0 replaces `project.description` with four required non-empty strings in discovery and Sources manifests: `productDescription`, `productSummary`, `technicalDescription`, and `technicalSummary`. Descriptions are plain text with a maximum of 120 Unicode code points each. Summaries contain Markdown; the technical summary includes implementation, technology, and deployment instructions. Old description-only documents are rejected. The envelope remains `openship: "1.0"` and Systems remains `systemsVersion: "2.0"`; all providers and consumers must upgrade together.
|
package/dist/package-meta.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"openship": "1.0",
|
|
3
3
|
"package": "@openship/protocol",
|
|
4
|
-
"packageVersion": "0.
|
|
4
|
+
"packageVersion": "0.2.0",
|
|
5
5
|
"source": "https://github.com/openshipdev/openship/tree/main/skills/openship",
|
|
6
|
-
"sourceCommit": "
|
|
6
|
+
"sourceCommit": "4915be31602a94653da5e56c22f0609736668ea0"
|
|
7
7
|
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"openship": "1.0",
|
|
3
3
|
"capability": "discovery",
|
|
4
|
-
"project": {
|
|
4
|
+
"project": {
|
|
5
|
+
"name": "Broken MCP",
|
|
6
|
+
"productDescription": "The MCP URL is not absolute HTTPS.",
|
|
7
|
+
"productSummary": "# Product\n\nThe MCP URL is not absolute HTTPS.",
|
|
8
|
+
"technicalDescription": "A source snapshot published through OpenShip.",
|
|
9
|
+
"technicalSummary": "# Implementation\n\nRetrieve the source bundle, install its dependencies, and follow its deployment documentation."
|
|
10
|
+
},
|
|
5
11
|
"agent": {
|
|
6
12
|
"summary": "OpenShip exposes capabilities for a running project.",
|
|
7
13
|
"instructions": "Fetch and read agent.skill before using any capability.",
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"openship": "1.0",
|
|
3
3
|
"capability": "discovery",
|
|
4
|
-
"project": {
|
|
4
|
+
"project": {
|
|
5
|
+
"name": "Broken",
|
|
6
|
+
"productDescription": "Sources is missing.",
|
|
7
|
+
"productSummary": "# Product\n\nSources is missing.",
|
|
8
|
+
"technicalDescription": "A source snapshot published through OpenShip.",
|
|
9
|
+
"technicalSummary": "# Implementation\n\nRetrieve the source bundle, install its dependencies, and follow its deployment documentation."
|
|
10
|
+
},
|
|
5
11
|
"agent": {
|
|
6
12
|
"summary": "OpenShip exposes capabilities for a running project.",
|
|
7
13
|
"instructions": "Fetch and read agent.skill before using any capability.",
|
|
@@ -2,10 +2,25 @@
|
|
|
2
2
|
"openship": "1.0",
|
|
3
3
|
"capability": "sources",
|
|
4
4
|
"digest": "sha256:1d322539e651a3c2d7c51eb8b33160627395b9601bff909e599771b806d9e565",
|
|
5
|
-
"project": {
|
|
6
|
-
|
|
5
|
+
"project": {
|
|
6
|
+
"name": "Broken",
|
|
7
|
+
"productDescription": "Contains an unsafe path.",
|
|
8
|
+
"productSummary": "# Product\n\nContains an unsafe path.",
|
|
9
|
+
"technicalDescription": "A source snapshot published through OpenShip.",
|
|
10
|
+
"technicalSummary": "# Implementation\n\nRetrieve the source bundle, install its dependencies, and follow its deployment documentation."
|
|
11
|
+
},
|
|
12
|
+
"totals": {
|
|
13
|
+
"files": 1,
|
|
14
|
+
"bytes": 1
|
|
15
|
+
},
|
|
7
16
|
"files": [
|
|
8
|
-
{
|
|
17
|
+
{
|
|
18
|
+
"path": "../secret",
|
|
19
|
+
"size": 1,
|
|
20
|
+
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
21
|
+
"encoding": "utf-8",
|
|
22
|
+
"mediaType": "text/plain",
|
|
23
|
+
"type": "file"
|
|
24
|
+
}
|
|
9
25
|
]
|
|
10
26
|
}
|
|
11
|
-
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
"digest": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
9
9
|
"project": {
|
|
10
10
|
"name": "Broken ownership",
|
|
11
|
-
"
|
|
11
|
+
"productDescription": "A Systems node with non-conformant ownership.",
|
|
12
|
+
"productSummary": "# Product\n\nA Systems node with non-conformant ownership.",
|
|
13
|
+
"technicalDescription": "A source snapshot published through OpenShip.",
|
|
14
|
+
"technicalSummary": "# Implementation\n\nRetrieve the source bundle, install its dependencies, and follow its deployment documentation."
|
|
12
15
|
},
|
|
13
16
|
"totals": {
|
|
14
17
|
"files": 0,
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
"digest": "sha256:1d322539e651a3c2d7c51eb8b33160627395b9601bff909e599771b806d9e565",
|
|
9
9
|
"project": {
|
|
10
10
|
"name": "Broken",
|
|
11
|
-
"
|
|
11
|
+
"productDescription": "The runtime edge targets a Library.",
|
|
12
|
+
"productSummary": "# Product\n\nThe runtime edge targets a Library.",
|
|
13
|
+
"technicalDescription": "A source snapshot published through OpenShip.",
|
|
14
|
+
"technicalSummary": "# Implementation\n\nRetrieve the source bundle, install its dependencies, and follow its deployment documentation."
|
|
12
15
|
},
|
|
13
16
|
"totals": {
|
|
14
17
|
"files": 0,
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"openship": "1.0",
|
|
3
3
|
"capability": "discovery",
|
|
4
|
-
"project": {
|
|
4
|
+
"project": {
|
|
5
|
+
"name": "Example",
|
|
6
|
+
"productDescription": "An example OpenShip project.",
|
|
7
|
+
"productSummary": "# Product\n\nAn example OpenShip project.",
|
|
8
|
+
"technicalDescription": "A source snapshot published through OpenShip.",
|
|
9
|
+
"technicalSummary": "# Implementation\n\nRetrieve the source bundle, install its dependencies, and follow its deployment documentation."
|
|
10
|
+
},
|
|
5
11
|
"agent": {
|
|
6
12
|
"summary": "OpenShip lets this running project publish verifiable source code and optionally accept isolated changes or describe its complete system.",
|
|
7
13
|
"instructions": "Fetch and read agent.skill before interpreting or using any advertised capability. Resolve relative links in the skill against the skill URL.",
|
|
@@ -3,8 +3,17 @@
|
|
|
3
3
|
"capability": "sources",
|
|
4
4
|
"generatedAt": "2026-08-21T12:00:00.000Z",
|
|
5
5
|
"digest": "sha256:1d322539e651a3c2d7c51eb8b33160627395b9601bff909e599771b806d9e565",
|
|
6
|
-
"project": {
|
|
7
|
-
|
|
6
|
+
"project": {
|
|
7
|
+
"name": "Example",
|
|
8
|
+
"productDescription": "An example OpenShip project.",
|
|
9
|
+
"productSummary": "# Product\n\nAn example OpenShip project.",
|
|
10
|
+
"technicalDescription": "A source snapshot published through OpenShip.",
|
|
11
|
+
"technicalSummary": "# Implementation\n\nRetrieve the source bundle, install its dependencies, and follow its deployment documentation."
|
|
12
|
+
},
|
|
13
|
+
"totals": {
|
|
14
|
+
"files": 2,
|
|
15
|
+
"bytes": 53
|
|
16
|
+
},
|
|
8
17
|
"files": [
|
|
9
18
|
{
|
|
10
19
|
"path": "app/page.js",
|
|
@@ -24,4 +33,3 @@
|
|
|
24
33
|
}
|
|
25
34
|
]
|
|
26
35
|
}
|
|
27
|
-
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
"digest": "sha256:1d322539e651a3c2d7c51eb8b33160627395b9601bff909e599771b806d9e565",
|
|
9
9
|
"project": {
|
|
10
10
|
"name": "Example",
|
|
11
|
-
"
|
|
11
|
+
"productDescription": "An example OpenShip project.",
|
|
12
|
+
"productSummary": "# Product\n\nAn example OpenShip project.",
|
|
13
|
+
"technicalDescription": "A source snapshot published through OpenShip.",
|
|
14
|
+
"technicalSummary": "# Implementation\n\nRetrieve the source bundle, install its dependencies, and follow its deployment documentation."
|
|
12
15
|
},
|
|
13
16
|
"totals": {
|
|
14
17
|
"files": 2,
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
"digest": "sha256:1d322539e651a3c2d7c51eb8b33160627395b9601bff909e599771b806d9e565",
|
|
9
9
|
"project": {
|
|
10
10
|
"name": "Example",
|
|
11
|
-
"
|
|
11
|
+
"productDescription": "An example OpenShip project.",
|
|
12
|
+
"productSummary": "# Product\n\nAn example OpenShip project.",
|
|
13
|
+
"technicalDescription": "A source snapshot published through OpenShip.",
|
|
14
|
+
"technicalSummary": "# Implementation\n\nRetrieve the source bundle, install its dependencies, and follow its deployment documentation."
|
|
12
15
|
},
|
|
13
16
|
"totals": {
|
|
14
17
|
"files": 2,
|
|
@@ -32,7 +32,10 @@ remain normative and required.
|
|
|
32
32
|
"digest": "sha256:1c413f...",
|
|
33
33
|
"project": {
|
|
34
34
|
"name": "Example",
|
|
35
|
-
"
|
|
35
|
+
"productDescription": "An example product.",
|
|
36
|
+
"productSummary": "## Product\n\nWhat this product does and the problem it solves.",
|
|
37
|
+
"technicalDescription": "A web application.",
|
|
38
|
+
"technicalSummary": "## Implementation\n\nTechnology and deployment instructions.",
|
|
36
39
|
"homepage": "https://example.com",
|
|
37
40
|
"repository": "https://github.com/example/example",
|
|
38
41
|
"license": "MIT"
|
|
@@ -51,7 +54,7 @@ remain normative and required.
|
|
|
51
54
|
}
|
|
52
55
|
```
|
|
53
56
|
|
|
54
|
-
Required members are `openship`, `capability`, `digest`, `project`, `totals`, and `files`. Project name and
|
|
57
|
+
Required members are `openship`, `capability`, `digest`, `project`, `totals`, and `files`. Project name and all four descriptive fields (`productDescription`, `productSummary`, `technicalDescription`, `technicalSummary`) are required non-empty strings. Descriptions are plain text of at most 120 Unicode code points each; summaries are Markdown. Product fields explain what the product does and the problem it solves. Technical fields explain implementation, technology, and deployment. The legacy `project.description` field is replaced without a fallback. Repository, commit, stack, structure, setup, runtime, environment-variable names, ignore rules, generation time, lineage, and other metadata are optional.
|
|
55
58
|
|
|
56
59
|
See [schemas/sources-manifest.schema.json](schemas/sources-manifest.schema.json).
|
|
57
60
|
|
|
@@ -54,7 +54,10 @@ The response MUST be unauthenticated JSON, MUST allow cross-origin reads with `A
|
|
|
54
54
|
"capability": "discovery",
|
|
55
55
|
"project": {
|
|
56
56
|
"name": "Example",
|
|
57
|
-
"
|
|
57
|
+
"productDescription": "A short description of what the product does.",
|
|
58
|
+
"productSummary": "## Product\n\nWhat the product does and the problem it solves.",
|
|
59
|
+
"technicalDescription": "A short description of the implementation.",
|
|
60
|
+
"technicalSummary": "## Implementation\n\nTechnologies, architecture, and deployment instructions."
|
|
58
61
|
},
|
|
59
62
|
"agent": {
|
|
60
63
|
"summary": "OpenShip lets this running project publish verifiable source code and optionally accept isolated changes or describe its complete system.",
|
|
@@ -89,7 +92,7 @@ The response MUST be unauthenticated JSON, MUST allow cross-origin reads with `A
|
|
|
89
92
|
Requirements:
|
|
90
93
|
|
|
91
94
|
- `project`, `agent`, `capabilities`, and `capabilities.sources` are REQUIRED.
|
|
92
|
-
- `project.name` and `project.
|
|
95
|
+
- `project.name`, `project.productDescription`, `project.productSummary`, `project.technicalDescription`, and `project.technicalSummary` are REQUIRED non-empty strings. The descriptions are plain text, each at most 120 Unicode code points. The summaries are Markdown: productSummary explains the product and problem it solves; technicalSummary explains implementation, underlying technology, and deployment. These fields replace project.description; there is no legacy fallback.
|
|
93
96
|
- `agent.summary`, `agent.instructions`, and `agent.skill` are REQUIRED. The summary MUST explain OpenShip in standalone plain language. The instructions MUST explicitly direct an unfamiliar agent to fetch and read `agent.skill` before interpreting or using the capability links.
|
|
94
97
|
- `agent.skill` MUST identify the OpenShip skill entry point. Relative links in that skill MUST be resolved against the skill URL.
|
|
95
98
|
- Every advertised capability MUST contain a standalone `description` explaining what the capability lets an agent do.
|
|
@@ -3,65 +3,162 @@
|
|
|
3
3
|
"$id": "https://openship.dev/schemas/discovery.schema.json",
|
|
4
4
|
"title": "OpenShip v1 discovery",
|
|
5
5
|
"type": "object",
|
|
6
|
-
"required": [
|
|
6
|
+
"required": [
|
|
7
|
+
"openship",
|
|
8
|
+
"capability",
|
|
9
|
+
"project",
|
|
10
|
+
"agent",
|
|
11
|
+
"capabilities"
|
|
12
|
+
],
|
|
7
13
|
"properties": {
|
|
8
|
-
"openship": {
|
|
9
|
-
|
|
14
|
+
"openship": {
|
|
15
|
+
"const": "1.0"
|
|
16
|
+
},
|
|
17
|
+
"capability": {
|
|
18
|
+
"const": "discovery"
|
|
19
|
+
},
|
|
10
20
|
"project": {
|
|
11
21
|
"type": "object",
|
|
12
|
-
"required": [
|
|
22
|
+
"required": [
|
|
23
|
+
"name",
|
|
24
|
+
"productDescription",
|
|
25
|
+
"productSummary",
|
|
26
|
+
"technicalDescription",
|
|
27
|
+
"technicalSummary"
|
|
28
|
+
],
|
|
13
29
|
"properties": {
|
|
14
|
-
"name": {
|
|
15
|
-
|
|
30
|
+
"name": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"minLength": 1
|
|
33
|
+
},
|
|
34
|
+
"productDescription": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"minLength": 1,
|
|
37
|
+
"maxLength": 120
|
|
38
|
+
},
|
|
39
|
+
"productSummary": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"minLength": 1,
|
|
42
|
+
"description": "Markdown text."
|
|
43
|
+
},
|
|
44
|
+
"technicalDescription": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"minLength": 1,
|
|
47
|
+
"maxLength": 120
|
|
48
|
+
},
|
|
49
|
+
"technicalSummary": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"minLength": 1,
|
|
52
|
+
"description": "Markdown text."
|
|
53
|
+
}
|
|
16
54
|
},
|
|
17
55
|
"additionalProperties": true
|
|
18
56
|
},
|
|
19
57
|
"agent": {
|
|
20
58
|
"type": "object",
|
|
21
|
-
"required": [
|
|
59
|
+
"required": [
|
|
60
|
+
"summary",
|
|
61
|
+
"instructions",
|
|
62
|
+
"skill"
|
|
63
|
+
],
|
|
22
64
|
"properties": {
|
|
23
|
-
"summary": {
|
|
24
|
-
|
|
25
|
-
|
|
65
|
+
"summary": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"minLength": 1
|
|
68
|
+
},
|
|
69
|
+
"instructions": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"minLength": 1
|
|
72
|
+
},
|
|
73
|
+
"skill": {
|
|
74
|
+
"$ref": "#/$defs/httpsUrl"
|
|
75
|
+
}
|
|
26
76
|
},
|
|
27
77
|
"additionalProperties": true
|
|
28
78
|
},
|
|
29
|
-
"page": {
|
|
79
|
+
"page": {
|
|
80
|
+
"$ref": "#/$defs/httpsUrl"
|
|
81
|
+
},
|
|
30
82
|
"capabilities": {
|
|
31
83
|
"type": "object",
|
|
32
|
-
"required": [
|
|
84
|
+
"required": [
|
|
85
|
+
"sources"
|
|
86
|
+
],
|
|
33
87
|
"properties": {
|
|
34
88
|
"sources": {
|
|
35
89
|
"type": "object",
|
|
36
|
-
"required": [
|
|
90
|
+
"required": [
|
|
91
|
+
"description",
|
|
92
|
+
"manifest",
|
|
93
|
+
"bundle"
|
|
94
|
+
],
|
|
37
95
|
"properties": {
|
|
38
|
-
"description": {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
96
|
+
"description": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"minLength": 1
|
|
99
|
+
},
|
|
100
|
+
"manifest": {
|
|
101
|
+
"$ref": "#/$defs/httpsUrl"
|
|
102
|
+
},
|
|
103
|
+
"bundle": {
|
|
104
|
+
"$ref": "#/$defs/httpsUrl"
|
|
105
|
+
},
|
|
106
|
+
"mcp": {
|
|
107
|
+
"$ref": "#/$defs/httpsUrl"
|
|
108
|
+
},
|
|
109
|
+
"file": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"pattern": "^https://.+\\{path\\}.+$|^https://.+/\\{path\\}$"
|
|
112
|
+
},
|
|
113
|
+
"archive": {
|
|
114
|
+
"$ref": "#/$defs/httpsUrl"
|
|
115
|
+
},
|
|
116
|
+
"instructions": {
|
|
117
|
+
"$ref": "#/$defs/httpsUrl"
|
|
118
|
+
}
|
|
45
119
|
},
|
|
46
120
|
"additionalProperties": true
|
|
47
121
|
},
|
|
48
122
|
"changes": {
|
|
49
123
|
"type": "object",
|
|
50
|
-
"required": [
|
|
124
|
+
"required": [
|
|
125
|
+
"description",
|
|
126
|
+
"policy",
|
|
127
|
+
"submit",
|
|
128
|
+
"status"
|
|
129
|
+
],
|
|
51
130
|
"properties": {
|
|
52
|
-
"description": {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
131
|
+
"description": {
|
|
132
|
+
"type": "string",
|
|
133
|
+
"minLength": 1
|
|
134
|
+
},
|
|
135
|
+
"policy": {
|
|
136
|
+
"$ref": "#/$defs/httpsUrl"
|
|
137
|
+
},
|
|
138
|
+
"submit": {
|
|
139
|
+
"$ref": "#/$defs/httpsUrl"
|
|
140
|
+
},
|
|
141
|
+
"status": {
|
|
142
|
+
"type": "string",
|
|
143
|
+
"pattern": "^https://.+\\{changeId\\}.+$|^https://.+/\\{changeId\\}$"
|
|
144
|
+
}
|
|
56
145
|
},
|
|
57
146
|
"additionalProperties": true
|
|
58
147
|
},
|
|
59
148
|
"systems": {
|
|
60
149
|
"type": "object",
|
|
61
|
-
"required": [
|
|
150
|
+
"required": [
|
|
151
|
+
"description",
|
|
152
|
+
"document"
|
|
153
|
+
],
|
|
62
154
|
"properties": {
|
|
63
|
-
"description": {
|
|
64
|
-
|
|
155
|
+
"description": {
|
|
156
|
+
"type": "string",
|
|
157
|
+
"minLength": 1
|
|
158
|
+
},
|
|
159
|
+
"document": {
|
|
160
|
+
"$ref": "#/$defs/httpsUrl"
|
|
161
|
+
}
|
|
65
162
|
},
|
|
66
163
|
"additionalProperties": true
|
|
67
164
|
}
|
|
@@ -70,7 +167,11 @@
|
|
|
70
167
|
}
|
|
71
168
|
},
|
|
72
169
|
"$defs": {
|
|
73
|
-
"httpsUrl": {
|
|
170
|
+
"httpsUrl": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"format": "uri",
|
|
173
|
+
"pattern": "^https://"
|
|
174
|
+
}
|
|
74
175
|
},
|
|
75
176
|
"additionalProperties": true
|
|
76
177
|
}
|
|
@@ -3,74 +3,261 @@
|
|
|
3
3
|
"$id": "https://openship.dev/schemas/sources-manifest.schema.json",
|
|
4
4
|
"title": "OpenShip Sources v1 manifest",
|
|
5
5
|
"type": "object",
|
|
6
|
-
"required": [
|
|
6
|
+
"required": [
|
|
7
|
+
"openship",
|
|
8
|
+
"capability",
|
|
9
|
+
"digest",
|
|
10
|
+
"project",
|
|
11
|
+
"totals",
|
|
12
|
+
"files"
|
|
13
|
+
],
|
|
7
14
|
"properties": {
|
|
8
|
-
"openship": {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
15
|
+
"openship": {
|
|
16
|
+
"const": "1.0"
|
|
17
|
+
},
|
|
18
|
+
"capability": {
|
|
19
|
+
"const": "sources"
|
|
20
|
+
},
|
|
21
|
+
"generatedAt": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"format": "date-time"
|
|
24
|
+
},
|
|
25
|
+
"digest": {
|
|
26
|
+
"$ref": "#/$defs/digest"
|
|
27
|
+
},
|
|
28
|
+
"parent": {
|
|
29
|
+
"$ref": "#/$defs/digest"
|
|
30
|
+
},
|
|
13
31
|
"project": {
|
|
14
32
|
"type": "object",
|
|
15
|
-
"required": [
|
|
33
|
+
"required": [
|
|
34
|
+
"name",
|
|
35
|
+
"productDescription",
|
|
36
|
+
"productSummary",
|
|
37
|
+
"technicalDescription",
|
|
38
|
+
"technicalSummary"
|
|
39
|
+
],
|
|
16
40
|
"properties": {
|
|
17
|
-
"name": {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
41
|
+
"name": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"minLength": 1
|
|
44
|
+
},
|
|
45
|
+
"homepage": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"format": "uri"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"format": "uri"
|
|
52
|
+
},
|
|
53
|
+
"license": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"minLength": 1
|
|
56
|
+
},
|
|
57
|
+
"productDescription": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"minLength": 1,
|
|
60
|
+
"maxLength": 120
|
|
61
|
+
},
|
|
62
|
+
"productSummary": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"minLength": 1,
|
|
65
|
+
"description": "Markdown text."
|
|
66
|
+
},
|
|
67
|
+
"technicalDescription": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"minLength": 1,
|
|
70
|
+
"maxLength": 120
|
|
71
|
+
},
|
|
72
|
+
"technicalSummary": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"minLength": 1,
|
|
75
|
+
"description": "Markdown text."
|
|
76
|
+
}
|
|
22
77
|
},
|
|
23
78
|
"additionalProperties": true
|
|
24
79
|
},
|
|
25
80
|
"commit": {
|
|
26
81
|
"type": "object",
|
|
27
|
-
"required": [
|
|
82
|
+
"required": [
|
|
83
|
+
"sha",
|
|
84
|
+
"dirty"
|
|
85
|
+
],
|
|
28
86
|
"properties": {
|
|
29
|
-
"sha": {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
87
|
+
"sha": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"minLength": 1
|
|
90
|
+
},
|
|
91
|
+
"ref": {
|
|
92
|
+
"type": "string"
|
|
93
|
+
},
|
|
94
|
+
"committedAt": {
|
|
95
|
+
"type": "string",
|
|
96
|
+
"format": "date-time"
|
|
97
|
+
},
|
|
98
|
+
"dirty": {
|
|
99
|
+
"type": "boolean"
|
|
100
|
+
}
|
|
33
101
|
},
|
|
34
102
|
"additionalProperties": true
|
|
35
103
|
},
|
|
36
|
-
"stack": {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
104
|
+
"stack": {
|
|
105
|
+
"type": "array",
|
|
106
|
+
"items": {
|
|
107
|
+
"type": "string"
|
|
108
|
+
},
|
|
109
|
+
"uniqueItems": true
|
|
110
|
+
},
|
|
111
|
+
"structure": {
|
|
112
|
+
"type": "array",
|
|
113
|
+
"items": {
|
|
114
|
+
"type": "object",
|
|
115
|
+
"required": [
|
|
116
|
+
"path",
|
|
117
|
+
"purpose"
|
|
118
|
+
],
|
|
119
|
+
"properties": {
|
|
120
|
+
"path": {
|
|
121
|
+
"type": "string"
|
|
122
|
+
},
|
|
123
|
+
"purpose": {
|
|
124
|
+
"type": "string"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"additionalProperties": true
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"setup": {
|
|
131
|
+
"type": "object",
|
|
132
|
+
"additionalProperties": true
|
|
133
|
+
},
|
|
134
|
+
"env": {
|
|
135
|
+
"type": "array",
|
|
136
|
+
"items": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"pattern": "^[A-Z][A-Z0-9_]*$"
|
|
139
|
+
},
|
|
140
|
+
"uniqueItems": true
|
|
141
|
+
},
|
|
142
|
+
"ignore": {
|
|
143
|
+
"type": "array",
|
|
144
|
+
"items": {
|
|
145
|
+
"type": "string"
|
|
146
|
+
},
|
|
147
|
+
"uniqueItems": true
|
|
148
|
+
},
|
|
149
|
+
"ignoreNames": {
|
|
150
|
+
"type": "array",
|
|
151
|
+
"items": {
|
|
152
|
+
"type": "string"
|
|
153
|
+
},
|
|
154
|
+
"uniqueItems": true
|
|
155
|
+
},
|
|
156
|
+
"fileSet": {
|
|
157
|
+
"type": "string",
|
|
158
|
+
"minLength": 1
|
|
159
|
+
},
|
|
43
160
|
"totals": {
|
|
44
161
|
"type": "object",
|
|
45
|
-
"required": [
|
|
162
|
+
"required": [
|
|
163
|
+
"files",
|
|
164
|
+
"bytes"
|
|
165
|
+
],
|
|
46
166
|
"properties": {
|
|
47
|
-
"files": {
|
|
48
|
-
|
|
167
|
+
"files": {
|
|
168
|
+
"type": "integer",
|
|
169
|
+
"minimum": 0
|
|
170
|
+
},
|
|
171
|
+
"bytes": {
|
|
172
|
+
"type": "integer",
|
|
173
|
+
"minimum": 0
|
|
174
|
+
}
|
|
49
175
|
},
|
|
50
176
|
"additionalProperties": true
|
|
51
177
|
},
|
|
52
178
|
"files": {
|
|
53
179
|
"type": "array",
|
|
54
|
-
"items": {
|
|
180
|
+
"items": {
|
|
181
|
+
"$ref": "#/$defs/file"
|
|
182
|
+
}
|
|
55
183
|
}
|
|
56
184
|
},
|
|
57
185
|
"$defs": {
|
|
58
|
-
"digest": {
|
|
59
|
-
|
|
186
|
+
"digest": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"pattern": "^sha256:[0-9a-f]{64}$"
|
|
189
|
+
},
|
|
190
|
+
"path": {
|
|
191
|
+
"type": "string",
|
|
192
|
+
"minLength": 1,
|
|
193
|
+
"maxLength": 512,
|
|
194
|
+
"pattern": "^(?!/)(?!.*\\\\)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*//)[^\\u0000]+$"
|
|
195
|
+
},
|
|
60
196
|
"file": {
|
|
61
197
|
"type": "object",
|
|
62
|
-
"required": [
|
|
198
|
+
"required": [
|
|
199
|
+
"path",
|
|
200
|
+
"size",
|
|
201
|
+
"sha256",
|
|
202
|
+
"encoding",
|
|
203
|
+
"mediaType",
|
|
204
|
+
"type"
|
|
205
|
+
],
|
|
63
206
|
"properties": {
|
|
64
|
-
"path": {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
207
|
+
"path": {
|
|
208
|
+
"$ref": "#/$defs/path"
|
|
209
|
+
},
|
|
210
|
+
"size": {
|
|
211
|
+
"type": "integer",
|
|
212
|
+
"minimum": 0
|
|
213
|
+
},
|
|
214
|
+
"sha256": {
|
|
215
|
+
"type": "string",
|
|
216
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
217
|
+
},
|
|
218
|
+
"encoding": {
|
|
219
|
+
"enum": [
|
|
220
|
+
"utf-8",
|
|
221
|
+
"base64"
|
|
222
|
+
]
|
|
223
|
+
},
|
|
224
|
+
"mediaType": {
|
|
225
|
+
"type": "string",
|
|
226
|
+
"minLength": 1
|
|
227
|
+
},
|
|
228
|
+
"type": {
|
|
229
|
+
"enum": [
|
|
230
|
+
"file",
|
|
231
|
+
"symlink"
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
"target": {
|
|
235
|
+
"$ref": "#/$defs/path"
|
|
236
|
+
}
|
|
71
237
|
},
|
|
72
238
|
"allOf": [
|
|
73
|
-
{
|
|
239
|
+
{
|
|
240
|
+
"if": {
|
|
241
|
+
"properties": {
|
|
242
|
+
"type": {
|
|
243
|
+
"const": "symlink"
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
"required": [
|
|
247
|
+
"type"
|
|
248
|
+
]
|
|
249
|
+
},
|
|
250
|
+
"then": {
|
|
251
|
+
"properties": {
|
|
252
|
+
"target": {
|
|
253
|
+
"$ref": "#/$defs/path"
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
"required": [
|
|
257
|
+
"target"
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
}
|
|
74
261
|
],
|
|
75
262
|
"additionalProperties": true
|
|
76
263
|
}
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export interface Project { name: string; productDescription: string; productSummary: string; technicalDescription: string; technicalSummary: string; [key: string]: unknown }
|
|
1
2
|
export type OpenShipEncoding = "utf-8" | "base64";
|
|
2
3
|
export type OpenShipCapability = "discovery" | "sources" | "changes" | "systems";
|
|
3
4
|
export type OpenShipMcpOperation = "manifest" | "read";
|
|
@@ -6,10 +7,10 @@ export const OPENSHIP_MCP_TOOL_NAME: "openship";
|
|
|
6
7
|
export const OPENSHIP_MCP_MANIFEST_RESOURCE_URI: "openship://sources/manifest";
|
|
7
8
|
export const OPENSHIP_MCP_FILE_RESOURCE_TEMPLATE: "openship://sources/file{?path}";
|
|
8
9
|
export interface SourceFileMetadata { path: string; size: number; sha256: string; encoding: OpenShipEncoding; mediaType: string; type: "file" | "symlink"; target?: string; [key: string]: unknown }
|
|
9
|
-
export interface SourcesManifest { openship: "1.0"; capability: "sources"; digest: string; project:
|
|
10
|
+
export interface SourcesManifest { openship: "1.0"; capability: "sources"; digest: string; project: Project; totals: { files: number; bytes: number; [key: string]: unknown }; files: SourceFileMetadata[]; [key: string]: unknown }
|
|
10
11
|
export interface SourcesBundle { openship: "1.0"; capability: "sources"; digest: string; files: Record<string, { encoding: OpenShipEncoding; content: string; [key: string]: unknown }>; [key: string]: unknown }
|
|
11
12
|
export interface DiscoveryAgent { summary: string; instructions: string; skill: string; [key: string]: unknown }
|
|
12
|
-
export interface DiscoveryDocument { openship: "1.0"; capability: "discovery"; project:
|
|
13
|
+
export interface DiscoveryDocument { openship: "1.0"; capability: "discovery"; project: Project; agent: DiscoveryAgent; page?: string; capabilities: { sources: { description: string; manifest: string; bundle: string; mcp?: string; [key: string]: unknown }; systems?: { description: string; document: string; [key: string]: unknown }; changes?: { description: string; policy: string; submit: string; status: string; [key: string]: unknown }; [key: string]: unknown }; [key: string]: unknown }
|
|
13
14
|
export type SystemsNodeKind = "Root" | "Block" | "Store" | "Host" | "Container" | "Process" | "Contract" | "Library";
|
|
14
15
|
export type SystemsNodeOwnership = "first_party" | "third_party";
|
|
15
16
|
export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
|
package/src/index.js
CHANGED
|
@@ -130,7 +130,10 @@ export function validateSourcesManifest(value) {
|
|
|
130
130
|
if (!digestPattern.test(manifest.digest)) fail("$.digest", "must be a sha256 digest");
|
|
131
131
|
const project = object(manifest.project, "$.project");
|
|
132
132
|
string(project.name, "$.project.name");
|
|
133
|
-
|
|
133
|
+
for (const key of ["productDescription", "productSummary", "technicalDescription", "technicalSummary"]) {
|
|
134
|
+
const value = string(project[key], `$.project.${key}`);
|
|
135
|
+
if (key.endsWith("Description") && [...value].length > 120) fail(`$.project.${key}`, "must be at most 120 Unicode characters");
|
|
136
|
+
}
|
|
134
137
|
const totals = object(manifest.totals, "$.totals");
|
|
135
138
|
if (!Number.isInteger(totals.files) || totals.files < 0) fail("$.totals.files", "must be a non-negative integer");
|
|
136
139
|
if (!Number.isInteger(totals.bytes) || totals.bytes < 0) fail("$.totals.bytes", "must be a non-negative integer");
|
|
@@ -189,7 +192,10 @@ export function validateDiscovery(value) {
|
|
|
189
192
|
};
|
|
190
193
|
const project = object(discovery.project, "$.project");
|
|
191
194
|
string(project.name, "$.project.name");
|
|
192
|
-
|
|
195
|
+
for (const key of ["productDescription", "productSummary", "technicalDescription", "technicalSummary"]) {
|
|
196
|
+
const value = string(project[key], `$.project.${key}`);
|
|
197
|
+
if (key.endsWith("Description") && [...value].length > 120) fail(`$.project.${key}`, "must be at most 120 Unicode characters");
|
|
198
|
+
}
|
|
193
199
|
const agent = object(discovery.agent, "$.agent");
|
|
194
200
|
string(agent.summary, "$.agent.summary");
|
|
195
201
|
string(agent.instructions, "$.agent.instructions");
|