@open-agent-toolkit/cli 0.2.72 → 0.2.74
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/assets/agents/oat-reviewer.md +4 -3
- package/assets/agents/recon-worker.md +42 -8
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/configuration.md +3 -56
- package/assets/docs/cli-utilities/tool-packs.md +4 -4
- package/assets/docs/contributing/code.md +2 -2
- package/assets/docs/contributing/index.md +0 -1
- package/assets/docs/reference/cli-reference.md +1 -1
- package/assets/docs/reference/troubleshooting.md +17 -40
- package/assets/docs/workflows/projects/artifacts.md +16 -34
- package/assets/docs/workflows/projects/lifecycle.md +20 -19
- package/assets/docs/workflows/skills/explainer-kit.md +180 -440
- package/assets/docs/workflows/skills/index.md +1 -2
- package/assets/docs/workflows/skills/recon.md +114 -23
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/explainer-kit/SKILL.md +96 -171
- package/assets/skills/explainer-kit/recipes/engineer-tour.json +1 -22
- package/assets/skills/explainer-kit/recipes/program-recap.json +1 -29
- package/assets/skills/explainer-kit/recipes/project-explainer.json +1 -22
- package/assets/skills/explainer-kit/recipes/project-recap.v2.json +1 -43
- package/assets/skills/explainer-kit/references/fact-base-contract.md +76 -101
- package/assets/skills/explainer-kit/references/recap-authoring.md +99 -0
- package/assets/skills/explainer-kit/schemas/manifest.schema.json +13 -135
- package/assets/skills/explainer-kit/scripts/bundle.mjs +712 -0
- package/assets/skills/explainer-kit/scripts/lib/claim-subject.mjs +40 -0
- package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +113 -1504
- package/assets/skills/explainer-kit/scripts/lib/failure.mjs +13 -0
- package/assets/skills/explainer-kit/scripts/lib/package-coverage.mjs +57 -403
- package/assets/skills/explainer-kit/scripts/lib/qa-result.mjs +168 -0
- package/assets/skills/explainer-kit/scripts/lib/qa.mjs +90 -488
- package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +28 -545
- package/assets/skills/explainer-kit/scripts/lib/run-package.mjs +120 -0
- package/assets/skills/explainer-kit/scripts/lib/sanitize.mjs +42 -0
- package/assets/skills/explainer-kit/scripts/record.mjs +335 -0
- package/assets/skills/explainer-kit/scripts/verify.mjs +648 -0
- package/assets/skills/oat-explainer-kit/SKILL.md +57 -117
- package/assets/skills/oat-explainer-kit/references/config-contract.md +20 -64
- package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +85 -237
- package/assets/skills/oat-explainer-kit/scripts/bind-project-sources.mjs +18 -10
- package/assets/skills/oat-explainer-kit/scripts/check-core.mjs +1 -0
- package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +256 -21
- package/assets/skills/oat-explainer-kit/scripts/persist-intent.mjs +82 -3
- package/assets/skills/oat-explainer-kit/scripts/resolve-config.mjs +0 -162
- package/assets/skills/oat-explainer-kit/scripts/resolve-intent.mjs +57 -123
- package/assets/skills/oat-project-autonomous/SKILL.md +14 -13
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +165 -165
- package/assets/skills/oat-project-complete/SKILL.md +168 -349
- package/assets/skills/oat-project-complete/scripts/consume-persisted-recap-intent.mjs +125 -0
- package/assets/skills/oat-project-complete/scripts/execute-synced-archive-entry.mjs +0 -30
- package/assets/skills/oat-project-complete/scripts/parse-completion-retry-fields.mjs +4 -37
- package/assets/skills/oat-project-complete/scripts/parse-synced-archive-resume-fields.mjs +17 -16
- package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +9 -174
- package/assets/skills/oat-project-complete/scripts/resolve-completion-retry.mjs +1 -2
- package/assets/skills/oat-project-document/SKILL.md +1 -1
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +165 -165
- package/assets/skills/oat-project-implement/SKILL.md +1 -1
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +44 -56
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +165 -165
- package/assets/skills/oat-project-lite/SKILL.md +1 -1
- package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +165 -165
- package/assets/skills/oat-project-plan/SKILL.md +5 -6
- package/assets/skills/oat-project-pr-final/SKILL.md +1 -1
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +165 -165
- package/assets/skills/oat-project-quick-start/SKILL.md +1 -1
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +165 -165
- package/assets/skills/oat-project-review-receive/SKILL.md +14 -1
- package/assets/skills/oat-project-summary/SKILL.md +35 -25
- package/assets/skills/oat-wave-execute/SKILL.md +11 -36
- package/assets/skills/oat-wave-program/SKILL.md +13 -37
- package/assets/skills/recon/SKILL.md +103 -40
- package/assets/skills/recon/references/packet-contract.md +150 -67
- package/assets/skills/recon/references/profiles.md +38 -16
- package/assets/skills/recon/references/worker-contract.md +39 -8
- package/assets/skills/recon/scripts/lib/contracts.mjs +703 -55
- package/assets/skills/recon/scripts/lib/routing.mjs +588 -0
- package/assets/skills/recon/scripts/lib/validated-run.mjs +2 -0
- package/assets/skills/recon/scripts/prepare-routing.mjs +88 -0
- package/assets/skills/recon/scripts/render-packet.mjs +69 -1
- package/assets/skills/recon/scripts/validate-packet.mjs +473 -56
- package/assets/skills/subagent-orchestration/SKILL.md +18 -9
- package/assets/skills/subagent-orchestration/references/model-selection-principles.md +17 -8
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +9 -113
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +32 -184
- package/dist/commands/project/archive/explainer-package-coverage.d.ts +3 -8
- package/dist/commands/project/archive/explainer-package-coverage.d.ts.map +1 -1
- package/dist/commands/project/archive/explainer-package-coverage.js +1 -1
- package/dist/config/oat-config.d.ts +0 -11
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +0 -34
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +0 -8
- package/dist/release/public-package-contract.d.ts.map +1 -1
- package/dist/release/public-package-contract.js +2 -10
- package/dist/validation/project-state.d.ts.map +1 -1
- package/dist/validation/project-state.js +42 -3
- package/package.json +2 -2
- package/assets/docs/contributing/explainer-kit-verification.md +0 -133
- package/assets/docs/workflows/skills/explainer-kit-providers.md +0 -155
- package/assets/skills/explainer-kit/briefs/deep-dive.md +0 -35
- package/assets/skills/explainer-kit/briefs/project-page.md +0 -38
- package/assets/skills/explainer-kit/briefs/supporting-diagram.md +0 -28
- package/assets/skills/explainer-kit/briefs/walkthrough-deck.md +0 -35
- package/assets/skills/explainer-kit/examples/project-explainer/content.md +0 -31
- package/assets/skills/explainer-kit/examples/project-explainer/fact-base.md +0 -22
- package/assets/skills/explainer-kit/examples/project-recap/content.md +0 -77
- package/assets/skills/explainer-kit/examples/project-recap/fact-base.json +0 -104
- package/assets/skills/explainer-kit/examples/project-recap/fact-base.md +0 -44
- package/assets/skills/explainer-kit/examples/theme-bundle.json +0 -87
- package/assets/skills/explainer-kit/recipes/project-recap.v1.json +0 -93
- package/assets/skills/explainer-kit/references/contracts.md +0 -324
- package/assets/skills/explainer-kit/references/destination-contract.md +0 -210
- package/assets/skills/explainer-kit/references/extension-contract.md +0 -80
- package/assets/skills/explainer-kit/references/golden-conformance.md +0 -80
- package/assets/skills/explainer-kit/references/visual-review.md +0 -71
- package/assets/skills/explainer-kit/schemas/author-request.v2.schema.json +0 -212
- package/assets/skills/explainer-kit/schemas/author-request.v3.schema.json +0 -241
- package/assets/skills/explainer-kit/schemas/author-result.v2.schema.json +0 -52
- package/assets/skills/explainer-kit/schemas/build-record.schema.json +0 -98
- package/assets/skills/explainer-kit/schemas/durability-evidence.schema.json +0 -53
- package/assets/skills/explainer-kit/schemas/publish-receipt.v1.schema.json +0 -97
- package/assets/skills/explainer-kit/schemas/publish-receipt.v2.schema.json +0 -215
- package/assets/skills/explainer-kit/schemas/publish-request.v1.schema.json +0 -32
- package/assets/skills/explainer-kit/schemas/publish-request.v2.schema.json +0 -34
- package/assets/skills/explainer-kit/schemas/run-request.schema.json +0 -147
- package/assets/skills/explainer-kit/schemas/set-plan.v1.schema.json +0 -149
- package/assets/skills/explainer-kit/schemas/terminal-evidence.v1.schema.json +0 -81
- package/assets/skills/explainer-kit/schemas/visual-review-evidence.v1.schema.json +0 -66
- package/assets/skills/explainer-kit/schemas/visual-review-request.v1.schema.json +0 -117
- package/assets/skills/explainer-kit/schemas/visual-review-result.v1.schema.json +0 -80
- package/assets/skills/explainer-kit/scripts/lib/catalog.mjs +0 -349
- package/assets/skills/explainer-kit/scripts/lib/content-approval.mjs +0 -418
- package/assets/skills/explainer-kit/scripts/lib/diagram.mjs +0 -514
- package/assets/skills/explainer-kit/scripts/lib/durability.mjs +0 -643
- package/assets/skills/explainer-kit/scripts/lib/fact-base.mjs +0 -664
- package/assets/skills/explainer-kit/scripts/lib/internal-references.mjs +0 -538
- package/assets/skills/explainer-kit/scripts/lib/markdown.mjs +0 -414
- package/assets/skills/explainer-kit/scripts/lib/publication-policy.mjs +0 -54
- package/assets/skills/explainer-kit/scripts/lib/records.mjs +0 -954
- package/assets/skills/explainer-kit/scripts/lib/render.mjs +0 -703
- package/assets/skills/explainer-kit/scripts/lib/s3-roots.mjs +0 -353
- package/assets/skills/explainer-kit/scripts/lib/s3-static.mjs +0 -759
- package/assets/skills/explainer-kit/scripts/lib/set-plan.mjs +0 -209
- package/assets/skills/explainer-kit/scripts/lib/source-backlinks.mjs +0 -218
- package/assets/skills/explainer-kit/scripts/lib/terminal-evidence.mjs +0 -157
- package/assets/skills/explainer-kit/scripts/lib/visual-review.mjs +0 -400
- package/assets/skills/explainer-kit/scripts/publish.mjs +0 -76
- package/assets/skills/explainer-kit/scripts/record-durability.mjs +0 -64
- package/assets/skills/explainer-kit/scripts/render-qa.mjs +0 -461
- package/assets/skills/explainer-kit/scripts/run.mjs +0 -3038
- package/assets/skills/explainer-kit/scripts/validate.mjs +0 -59
- package/assets/skills/oat-explainer-kit/references/author-callback.md +0 -53
- package/assets/skills/oat-explainer-kit/references/migration.md +0 -144
- package/assets/skills/oat-explainer-kit/references/visual-review-callback.md +0 -83
- package/assets/skills/oat-explainer-kit/scripts/derive-destination.mjs +0 -91
- package/assets/skills/oat-explainer-kit/scripts/finalize-tracked-run.mjs +0 -531
- package/assets/skills/oat-explainer-kit/scripts/probe-recap-seams.mjs +0 -371
- package/assets/skills/oat-explainer-kit/scripts/run.mjs +0 -905
- package/dist/commands/project/archive/explainer-source-backlinks.d.ts +0 -18
- package/dist/commands/project/archive/explainer-source-backlinks.d.ts.map +0 -1
- package/dist/commands/project/archive/explainer-source-backlinks.js +0 -27
- package/dist/commands/project/archive/explainer-terminal-evidence.d.ts +0 -29
- package/dist/commands/project/archive/explainer-terminal-evidence.d.ts.map +0 -1
- package/dist/commands/project/archive/explainer-terminal-evidence.js +0 -37
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "explainer-kit.visual-review-evidence/v1",
|
|
4
|
-
"type": "object",
|
|
5
|
-
"additionalProperties": false,
|
|
6
|
-
"required": [
|
|
7
|
-
"schemaVersion",
|
|
8
|
-
"requestHash",
|
|
9
|
-
"attempt",
|
|
10
|
-
"disposition",
|
|
11
|
-
"reasons"
|
|
12
|
-
],
|
|
13
|
-
"properties": {
|
|
14
|
-
"schemaVersion": {
|
|
15
|
-
"const": "explainer-kit.visual-review-evidence/v1"
|
|
16
|
-
},
|
|
17
|
-
"requestHash": { "$ref": "#/$defs/hash" },
|
|
18
|
-
"attempt": { "enum": [1, 2] },
|
|
19
|
-
"disposition": { "enum": ["pass", "correct", "failed"] },
|
|
20
|
-
"reasons": {
|
|
21
|
-
"type": "array",
|
|
22
|
-
"minItems": 0,
|
|
23
|
-
"maxItems": 50,
|
|
24
|
-
"items": { "$ref": "#/$defs/reason" }
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"$defs": {
|
|
28
|
-
"hash": {
|
|
29
|
-
"type": "string",
|
|
30
|
-
"pattern": "^sha256:[a-f0-9]{64}$"
|
|
31
|
-
},
|
|
32
|
-
"reason": {
|
|
33
|
-
"type": "object",
|
|
34
|
-
"additionalProperties": false,
|
|
35
|
-
"required": ["stage", "kind", "count"],
|
|
36
|
-
"properties": {
|
|
37
|
-
"stage": {
|
|
38
|
-
"enum": [
|
|
39
|
-
"planning",
|
|
40
|
-
"authoring",
|
|
41
|
-
"rendering",
|
|
42
|
-
"link-validation",
|
|
43
|
-
"browser-review",
|
|
44
|
-
"visual-review",
|
|
45
|
-
"durability",
|
|
46
|
-
"finalization"
|
|
47
|
-
]
|
|
48
|
-
},
|
|
49
|
-
"kind": {
|
|
50
|
-
"enum": [
|
|
51
|
-
"finding",
|
|
52
|
-
"provider-failure",
|
|
53
|
-
"pipeline-failure",
|
|
54
|
-
"superseded"
|
|
55
|
-
]
|
|
56
|
-
},
|
|
57
|
-
"artifactId": {
|
|
58
|
-
"type": "string",
|
|
59
|
-
"minLength": 1,
|
|
60
|
-
"maxLength": 2000
|
|
61
|
-
},
|
|
62
|
-
"count": { "type": "integer", "minimum": 1, "maximum": 50 }
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "explainer-kit.visual-review-request/v1",
|
|
4
|
-
"title": "VisualReviewRequestV1",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"additionalProperties": false,
|
|
7
|
-
"required": [
|
|
8
|
-
"schemaVersion",
|
|
9
|
-
"requestId",
|
|
10
|
-
"requestHash",
|
|
11
|
-
"browserRuntime",
|
|
12
|
-
"captureIdentity",
|
|
13
|
-
"plan",
|
|
14
|
-
"renderedArtifacts"
|
|
15
|
-
],
|
|
16
|
-
"properties": {
|
|
17
|
-
"schemaVersion": {
|
|
18
|
-
"const": "explainer-kit.visual-review-request/v1"
|
|
19
|
-
},
|
|
20
|
-
"requestId": { "$ref": "#/$defs/safeId" },
|
|
21
|
-
"requestHash": { "$ref": "#/$defs/hash" },
|
|
22
|
-
"browserRuntime": { "$ref": "#/$defs/browserRuntime" },
|
|
23
|
-
"captureIdentity": { "$ref": "#/$defs/hash" },
|
|
24
|
-
"plan": { "$ref": "explainer-kit.set-plan/v1" },
|
|
25
|
-
"renderedArtifacts": {
|
|
26
|
-
"type": "array",
|
|
27
|
-
"items": { "$ref": "#/$defs/renderedArtifact" },
|
|
28
|
-
"minItems": 1,
|
|
29
|
-
"uniqueItems": true
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
"$defs": {
|
|
33
|
-
"safeRelativePath": {
|
|
34
|
-
"type": "string",
|
|
35
|
-
"minLength": 1,
|
|
36
|
-
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\).+$"
|
|
37
|
-
},
|
|
38
|
-
"safeId": {
|
|
39
|
-
"type": "string",
|
|
40
|
-
"pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$"
|
|
41
|
-
},
|
|
42
|
-
"hash": {
|
|
43
|
-
"type": "string",
|
|
44
|
-
"pattern": "^sha256:[a-f0-9]{64}$"
|
|
45
|
-
},
|
|
46
|
-
"browserRuntime": {
|
|
47
|
-
"type": "object",
|
|
48
|
-
"additionalProperties": false,
|
|
49
|
-
"required": ["kind", "name", "version"],
|
|
50
|
-
"properties": {
|
|
51
|
-
"kind": { "enum": ["launched", "fixture"] },
|
|
52
|
-
"name": { "const": "chromium" },
|
|
53
|
-
"version": { "type": "string", "minLength": 1 }
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
"renderedArtifact": {
|
|
57
|
-
"type": "object",
|
|
58
|
-
"additionalProperties": false,
|
|
59
|
-
"required": ["artifactId", "renderedPath", "renderedHash", "evidence"],
|
|
60
|
-
"properties": {
|
|
61
|
-
"artifactId": {
|
|
62
|
-
"type": "string",
|
|
63
|
-
"pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$"
|
|
64
|
-
},
|
|
65
|
-
"renderedPath": { "$ref": "#/$defs/safeRelativePath" },
|
|
66
|
-
"renderedHash": { "$ref": "#/$defs/hash" },
|
|
67
|
-
"cohesionObservations": {
|
|
68
|
-
"type": "array",
|
|
69
|
-
"items": { "$ref": "#/$defs/cohesionObservation" },
|
|
70
|
-
"uniqueItems": true
|
|
71
|
-
},
|
|
72
|
-
"evidence": {
|
|
73
|
-
"type": "array",
|
|
74
|
-
"items": { "$ref": "#/$defs/evidence" },
|
|
75
|
-
"minItems": 1,
|
|
76
|
-
"uniqueItems": true
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
"cohesionObservation": {
|
|
81
|
-
"type": "object",
|
|
82
|
-
"additionalProperties": false,
|
|
83
|
-
"required": ["artifactId", "contentHash", "group", "claim", "value"],
|
|
84
|
-
"properties": {
|
|
85
|
-
"artifactId": { "$ref": "#/$defs/safeId" },
|
|
86
|
-
"contentHash": { "$ref": "#/$defs/hash" },
|
|
87
|
-
"group": {
|
|
88
|
-
"enum": ["terminology", "statuses", "numericClaims"]
|
|
89
|
-
},
|
|
90
|
-
"claim": { "type": "string", "minLength": 1 },
|
|
91
|
-
"value": {
|
|
92
|
-
"oneOf": [{ "type": "string", "minLength": 1 }, { "type": "number" }]
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
"evidence": {
|
|
97
|
-
"type": "object",
|
|
98
|
-
"additionalProperties": false,
|
|
99
|
-
"required": [
|
|
100
|
-
"viewport",
|
|
101
|
-
"screenshotPath",
|
|
102
|
-
"screenshotHash",
|
|
103
|
-
"metricsPath",
|
|
104
|
-
"metricsHash",
|
|
105
|
-
"captureIdentity"
|
|
106
|
-
],
|
|
107
|
-
"properties": {
|
|
108
|
-
"viewport": { "enum": ["desktop", "tablet", "mobile"] },
|
|
109
|
-
"screenshotPath": { "$ref": "#/$defs/safeRelativePath" },
|
|
110
|
-
"screenshotHash": { "$ref": "#/$defs/hash" },
|
|
111
|
-
"metricsPath": { "$ref": "#/$defs/safeRelativePath" },
|
|
112
|
-
"metricsHash": { "$ref": "#/$defs/hash" },
|
|
113
|
-
"captureIdentity": { "$ref": "#/$defs/hash" }
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "explainer-kit.visual-review-result/v1",
|
|
4
|
-
"title": "VisualReviewResultV1",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"additionalProperties": false,
|
|
7
|
-
"required": [
|
|
8
|
-
"schemaVersion",
|
|
9
|
-
"reviewId",
|
|
10
|
-
"requestId",
|
|
11
|
-
"requestHash",
|
|
12
|
-
"reviewedAt",
|
|
13
|
-
"disposition",
|
|
14
|
-
"artifactIds",
|
|
15
|
-
"findings"
|
|
16
|
-
],
|
|
17
|
-
"properties": {
|
|
18
|
-
"schemaVersion": {
|
|
19
|
-
"const": "explainer-kit.visual-review-result/v1"
|
|
20
|
-
},
|
|
21
|
-
"reviewId": { "$ref": "#/$defs/safeId" },
|
|
22
|
-
"requestId": { "$ref": "#/$defs/safeId" },
|
|
23
|
-
"requestHash": { "$ref": "#/$defs/hash" },
|
|
24
|
-
"reviewedAt": { "type": "string", "format": "date-time" },
|
|
25
|
-
"disposition": { "enum": ["pass", "correct", "fail"] },
|
|
26
|
-
"artifactIds": {
|
|
27
|
-
"type": "array",
|
|
28
|
-
"items": { "$ref": "#/$defs/safeId" },
|
|
29
|
-
"minItems": 1,
|
|
30
|
-
"uniqueItems": true
|
|
31
|
-
},
|
|
32
|
-
"findings": {
|
|
33
|
-
"type": "array",
|
|
34
|
-
"items": { "$ref": "#/$defs/finding" },
|
|
35
|
-
"uniqueItems": true
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
"$defs": {
|
|
39
|
-
"safeId": {
|
|
40
|
-
"type": "string",
|
|
41
|
-
"pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*$"
|
|
42
|
-
},
|
|
43
|
-
"hash": {
|
|
44
|
-
"type": "string",
|
|
45
|
-
"pattern": "^sha256:[a-f0-9]{64}$"
|
|
46
|
-
},
|
|
47
|
-
"finding": {
|
|
48
|
-
"type": "object",
|
|
49
|
-
"additionalProperties": false,
|
|
50
|
-
"required": [
|
|
51
|
-
"artifactId",
|
|
52
|
-
"rubric",
|
|
53
|
-
"severity",
|
|
54
|
-
"evidence",
|
|
55
|
-
"correction"
|
|
56
|
-
],
|
|
57
|
-
"properties": {
|
|
58
|
-
"artifactId": { "$ref": "#/$defs/safeId" },
|
|
59
|
-
"rubric": {
|
|
60
|
-
"enum": [
|
|
61
|
-
"first-viewport",
|
|
62
|
-
"hierarchy",
|
|
63
|
-
"representation",
|
|
64
|
-
"legibility",
|
|
65
|
-
"medium-fit",
|
|
66
|
-
"cohesion",
|
|
67
|
-
"coverage",
|
|
68
|
-
"redundancy",
|
|
69
|
-
"interaction"
|
|
70
|
-
]
|
|
71
|
-
},
|
|
72
|
-
"severity": {
|
|
73
|
-
"enum": ["critical", "important", "medium", "minor"]
|
|
74
|
-
},
|
|
75
|
-
"evidence": { "type": "string", "minLength": 1 },
|
|
76
|
-
"correction": { "type": "string", "minLength": 1 }
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,349 +0,0 @@
|
|
|
1
|
-
import { canonicalStringify, validateContract } from './contracts.mjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Bumped to v2 when the root `publicVerification` marker was added below.
|
|
5
|
-
*
|
|
6
|
-
* The catalog is serialized, hashed, and recorded as an auxiliary artifact in
|
|
7
|
-
* the publish receipt, so adding a root key changes the bytes. Released
|
|
8
|
-
* `0.2.30` emits the v1 shape, which has no such key: leaving both shapes under
|
|
9
|
-
* one version string would put two different wire formats behind one identifier
|
|
10
|
-
* for anyone parsing `catalog.json` by declared version.
|
|
11
|
-
*
|
|
12
|
-
* There is deliberately no v1 read path. Unlike `publish-request/v1` and
|
|
13
|
-
* `publish-receipt/v1`, which are retained because a v1 record can still be
|
|
14
|
-
* replayed, the catalog is regenerate-only and never reconstructed from a v1
|
|
15
|
-
* receipt: every rebuild site short-circuits on a non-v2 receipt
|
|
16
|
-
* (`durability.mjs` verifyPublishEvidence, `run.mjs` publicationValidationContext,
|
|
17
|
-
* and the normative `private-wrapper.mjs` example), and `0.2.30` emits
|
|
18
|
-
* `publish-receipt/v1` only. Accepting v1 here would be unreachable code. If a
|
|
19
|
-
* future reader ever does replay a v1-era catalog, it must reconstruct that
|
|
20
|
-
* shape explicitly rather than relaxing this constant.
|
|
21
|
-
*/
|
|
22
|
-
const CATALOG_SCHEMA_VERSION = 'explainer-kit.initiative-catalog/v2';
|
|
23
|
-
|
|
24
|
-
export const PUBLIC_VERIFICATION_REQUIRED = 'required';
|
|
25
|
-
export const PUBLIC_VERIFICATION_SKIPPED_BY_POLICY = 'skipped-by-policy';
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Single source of truth for public-verification state.
|
|
29
|
-
*
|
|
30
|
-
* The catalog is built, serialized and hashed *before* the first upload and long
|
|
31
|
-
* before any per-artifact public verification runs, so it can never carry a
|
|
32
|
-
* verification *outcome*: writing one would either require re-uploading the
|
|
33
|
-
* catalog or invalidate the hash the receipt records for it. It therefore
|
|
34
|
-
* carries verification *policy* only, and the authoritative outcome stays in the
|
|
35
|
-
* run's publish receipt, which the catalog's `runId` identifies.
|
|
36
|
-
*
|
|
37
|
-
* Both the catalog marker and the receipt's skipped status are derived from this
|
|
38
|
-
* one result so the two cannot drift apart.
|
|
39
|
-
*/
|
|
40
|
-
export function resolvePublicVerificationPolicy(publicAccess) {
|
|
41
|
-
return publicAccess === 'protected'
|
|
42
|
-
? {
|
|
43
|
-
publicAccess: 'protected',
|
|
44
|
-
catalogMarker: PUBLIC_VERIFICATION_SKIPPED_BY_POLICY,
|
|
45
|
-
verifyPublicly: false,
|
|
46
|
-
receiptSkipStatus: 'skipped-protected',
|
|
47
|
-
}
|
|
48
|
-
: {
|
|
49
|
-
publicAccess: 'public',
|
|
50
|
-
catalogMarker: PUBLIC_VERIFICATION_REQUIRED,
|
|
51
|
-
verifyPublicly: true,
|
|
52
|
-
receiptSkipStatus: 'skipped-protected',
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* The public-access policy must be stated explicitly, never defaulted.
|
|
58
|
-
*
|
|
59
|
-
* It selects the catalog's `publicVerification` marker, which is part of the
|
|
60
|
-
* serialized bytes and therefore of the catalog hash the receipt records. An
|
|
61
|
-
* options bag that silently defaulted to the permissive `public` branch is what
|
|
62
|
-
* let four call sites omit it and still produce a plausible-looking catalog:
|
|
63
|
-
* the connector published `skipped-by-policy` for a `protected` run while the
|
|
64
|
-
* durability verifier rebuilt `required`, so the hashes diverged and no
|
|
65
|
-
* `protected` publication could ever be recorded durable.
|
|
66
|
-
*
|
|
67
|
-
* Passing `{ publicAccess: undefined }` is allowed and means `public` — that is
|
|
68
|
-
* the correct reading for `publish-request/v1` and `publish-receipt/v1`, which
|
|
69
|
-
* have no such field. Omitting the key entirely is a programming error.
|
|
70
|
-
*/
|
|
71
|
-
function requiredPublicAccess(options, caller) {
|
|
72
|
-
if (
|
|
73
|
-
options === null ||
|
|
74
|
-
typeof options !== 'object' ||
|
|
75
|
-
!('publicAccess' in options)
|
|
76
|
-
) {
|
|
77
|
-
throw new TypeError(
|
|
78
|
-
`${caller} requires an explicit { publicAccess } policy: it selects the catalog's publicVerification marker and therefore its hash. Pass { publicAccess: undefined } for v1 records, which are public by definition.`,
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
return options.publicAccess;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function initiativeCatalogPath(slug) {
|
|
85
|
-
if (typeof slug !== 'string' || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug)) {
|
|
86
|
-
throw new TypeError('Initiative catalog requires a safe initiative slug.');
|
|
87
|
-
}
|
|
88
|
-
return `site/initiatives/${slug}/catalog.json`;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function catalogFromManifest(manifest, publicBaseUrl, options) {
|
|
92
|
-
const publicAccess = requiredPublicAccess(options, 'catalogFromManifest');
|
|
93
|
-
const validation = validateContract('manifest', manifest);
|
|
94
|
-
if (!validation.valid) {
|
|
95
|
-
throw new TypeError(
|
|
96
|
-
`Initiative catalog requires a valid finalized manifest: ${validation.errors[0].message}`,
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
const baseUrl = normalizePublicBaseUrl(publicBaseUrl);
|
|
100
|
-
const artifacts = manifest.artifacts.map((artifact) => {
|
|
101
|
-
if (
|
|
102
|
-
artifact.status !== 'built' ||
|
|
103
|
-
typeof artifact.renderedPath !== 'string' ||
|
|
104
|
-
!artifact.renderedPath.startsWith('site/') ||
|
|
105
|
-
typeof artifact.hash !== 'string'
|
|
106
|
-
) {
|
|
107
|
-
throw new TypeError(
|
|
108
|
-
`Initiative catalog cannot publish non-built artifact ${artifact.id}.`,
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
id: artifact.id,
|
|
113
|
-
type: artifact.type,
|
|
114
|
-
status: artifact.status,
|
|
115
|
-
renderedPath: artifact.renderedPath,
|
|
116
|
-
...(artifact.mediaType && { mediaType: artifact.mediaType }),
|
|
117
|
-
hash: artifact.hash,
|
|
118
|
-
url: absoluteArtifactUrl(baseUrl, artifact.renderedPath),
|
|
119
|
-
};
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
schemaVersion: CATALOG_SCHEMA_VERSION,
|
|
124
|
-
runId: manifest.runId,
|
|
125
|
-
slug: manifest.slug,
|
|
126
|
-
recipe: structuredClone(manifest.recipe),
|
|
127
|
-
createdAt: manifest.createdAt,
|
|
128
|
-
// Policy, never outcome. See resolvePublicVerificationPolicy.
|
|
129
|
-
publicVerification:
|
|
130
|
-
resolvePublicVerificationPolicy(publicAccess).catalogMarker,
|
|
131
|
-
artifacts,
|
|
132
|
-
sourceBacklinks: structuredClone(manifest.source.backlinks ?? []),
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export function validateInitiativeCatalog(
|
|
137
|
-
catalog,
|
|
138
|
-
manifest,
|
|
139
|
-
publicBaseUrl,
|
|
140
|
-
options,
|
|
141
|
-
) {
|
|
142
|
-
const publicAccess = requiredPublicAccess(
|
|
143
|
-
options,
|
|
144
|
-
'validateInitiativeCatalog',
|
|
145
|
-
);
|
|
146
|
-
const errors = [];
|
|
147
|
-
let normalizedPublicBaseUrl;
|
|
148
|
-
try {
|
|
149
|
-
normalizedPublicBaseUrl = normalizePublicBaseUrl(publicBaseUrl);
|
|
150
|
-
} catch (error) {
|
|
151
|
-
add(
|
|
152
|
-
errors,
|
|
153
|
-
'$.artifacts',
|
|
154
|
-
'catalog-public-root',
|
|
155
|
-
error instanceof Error
|
|
156
|
-
? error.message
|
|
157
|
-
: 'Initiative catalog requires an HTTPS public base URL.',
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
if (!catalog || typeof catalog !== 'object' || Array.isArray(catalog)) {
|
|
161
|
-
return {
|
|
162
|
-
valid: false,
|
|
163
|
-
errors: [
|
|
164
|
-
{
|
|
165
|
-
path: '$',
|
|
166
|
-
code: 'catalog-shape',
|
|
167
|
-
message: 'Initiative catalog must be an object.',
|
|
168
|
-
},
|
|
169
|
-
],
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
const expectedRootKeys = new Set([
|
|
173
|
-
'schemaVersion',
|
|
174
|
-
'runId',
|
|
175
|
-
'slug',
|
|
176
|
-
'recipe',
|
|
177
|
-
'createdAt',
|
|
178
|
-
'publicVerification',
|
|
179
|
-
'artifacts',
|
|
180
|
-
'sourceBacklinks',
|
|
181
|
-
]);
|
|
182
|
-
if (Object.keys(catalog).some((key) => !expectedRootKeys.has(key))) {
|
|
183
|
-
add(
|
|
184
|
-
errors,
|
|
185
|
-
'$',
|
|
186
|
-
'catalog-shape',
|
|
187
|
-
'Initiative catalog contains an unknown property.',
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
for (const [field, expected] of [
|
|
192
|
-
['schemaVersion', CATALOG_SCHEMA_VERSION],
|
|
193
|
-
['runId', manifest?.runId],
|
|
194
|
-
['slug', manifest?.slug],
|
|
195
|
-
['createdAt', manifest?.createdAt],
|
|
196
|
-
]) {
|
|
197
|
-
if (catalog[field] !== expected) {
|
|
198
|
-
add(
|
|
199
|
-
errors,
|
|
200
|
-
`$.${field}`,
|
|
201
|
-
'catalog-manifest-mismatch',
|
|
202
|
-
`Catalog ${field} does not match the finalized manifest.`,
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
// Derived from the same resolver the receipt status comes from, so a catalog
|
|
207
|
-
// that disagrees with the run's resolved verification policy is rejected.
|
|
208
|
-
const expectedPublicVerification =
|
|
209
|
-
resolvePublicVerificationPolicy(publicAccess).catalogMarker;
|
|
210
|
-
if (catalog.publicVerification !== expectedPublicVerification) {
|
|
211
|
-
add(
|
|
212
|
-
errors,
|
|
213
|
-
'$.publicVerification',
|
|
214
|
-
'catalog-verification-policy',
|
|
215
|
-
`Catalog publicVerification must be ${expectedPublicVerification} for this run's public access policy.`,
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (
|
|
220
|
-
canonicalStringify(catalog.recipe) !== canonicalStringify(manifest?.recipe)
|
|
221
|
-
) {
|
|
222
|
-
add(
|
|
223
|
-
errors,
|
|
224
|
-
'$.recipe',
|
|
225
|
-
'catalog-manifest-mismatch',
|
|
226
|
-
'Catalog recipe does not match the finalized manifest.',
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const catalogArtifacts = Array.isArray(catalog.artifacts)
|
|
231
|
-
? catalog.artifacts
|
|
232
|
-
: [];
|
|
233
|
-
const manifestArtifacts = Array.isArray(manifest?.artifacts)
|
|
234
|
-
? manifest.artifacts
|
|
235
|
-
: [];
|
|
236
|
-
if (
|
|
237
|
-
!Array.isArray(catalog.artifacts) ||
|
|
238
|
-
catalogArtifacts.length !== manifestArtifacts.length
|
|
239
|
-
) {
|
|
240
|
-
add(
|
|
241
|
-
errors,
|
|
242
|
-
'$.artifacts',
|
|
243
|
-
'catalog-artifact-parity',
|
|
244
|
-
'Catalog artifacts must exactly cover the finalized manifest artifacts.',
|
|
245
|
-
);
|
|
246
|
-
}
|
|
247
|
-
for (const [index, artifact] of manifestArtifacts.entries()) {
|
|
248
|
-
const entry = catalogArtifacts[index];
|
|
249
|
-
const expected = {
|
|
250
|
-
id: artifact.id,
|
|
251
|
-
type: artifact.type,
|
|
252
|
-
status: artifact.status,
|
|
253
|
-
renderedPath: artifact.renderedPath,
|
|
254
|
-
...(artifact.mediaType && { mediaType: artifact.mediaType }),
|
|
255
|
-
hash: artifact.hash,
|
|
256
|
-
url:
|
|
257
|
-
normalizedPublicBaseUrl === undefined
|
|
258
|
-
? undefined
|
|
259
|
-
: absoluteArtifactUrl(normalizedPublicBaseUrl, artifact.renderedPath),
|
|
260
|
-
};
|
|
261
|
-
const actual = entry && typeof entry === 'object' ? entry : undefined;
|
|
262
|
-
if (canonicalStringify(actual) !== canonicalStringify(expected)) {
|
|
263
|
-
add(
|
|
264
|
-
errors,
|
|
265
|
-
`$.artifacts[${index}]`,
|
|
266
|
-
'catalog-artifact-mismatch',
|
|
267
|
-
`Catalog artifact ${artifact.id} is stale or does not match the finalized manifest.`,
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (
|
|
273
|
-
canonicalStringify(catalog.sourceBacklinks) !==
|
|
274
|
-
canonicalStringify(manifest?.source?.backlinks ?? [])
|
|
275
|
-
) {
|
|
276
|
-
add(
|
|
277
|
-
errors,
|
|
278
|
-
'$.sourceBacklinks',
|
|
279
|
-
'catalog-source-mismatch',
|
|
280
|
-
'Catalog source backlinks do not match the finalized manifest.',
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
for (const [index, backlink] of (Array.isArray(catalog.sourceBacklinks)
|
|
284
|
-
? catalog.sourceBacklinks
|
|
285
|
-
: []
|
|
286
|
-
).entries()) {
|
|
287
|
-
if (
|
|
288
|
-
typeof backlink?.sourceId !== 'string' ||
|
|
289
|
-
!isImmutableGithubUrl(backlink?.url)
|
|
290
|
-
) {
|
|
291
|
-
add(
|
|
292
|
-
errors,
|
|
293
|
-
`$.sourceBacklinks[${index}]`,
|
|
294
|
-
'catalog-source-url',
|
|
295
|
-
'Catalog source backlinks must be immutable absolute GitHub URLs.',
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return { valid: errors.length === 0, errors };
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
export function serializeInitiativeCatalog(catalog) {
|
|
304
|
-
return `${JSON.stringify(catalog, null, 2)}\n`;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
function normalizePublicBaseUrl(value) {
|
|
308
|
-
let url;
|
|
309
|
-
try {
|
|
310
|
-
url = new URL(value);
|
|
311
|
-
} catch {
|
|
312
|
-
throw new TypeError(
|
|
313
|
-
'Initiative catalog requires an HTTPS public base URL.',
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
if (
|
|
317
|
-
url.protocol !== 'https:' ||
|
|
318
|
-
url.username ||
|
|
319
|
-
url.password ||
|
|
320
|
-
url.search ||
|
|
321
|
-
url.hash
|
|
322
|
-
) {
|
|
323
|
-
throw new TypeError(
|
|
324
|
-
'Initiative catalog requires credential-free HTTPS without query or fragment.',
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
return url.href.replace(/\/+$/, '');
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
function absoluteArtifactUrl(baseUrl, renderedPath) {
|
|
331
|
-
return `${baseUrl}/${renderedPath
|
|
332
|
-
.slice('site/'.length)
|
|
333
|
-
.split('/')
|
|
334
|
-
.map((part) => encodeURIComponent(part))
|
|
335
|
-
.join('/')}`;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function isImmutableGithubUrl(value) {
|
|
339
|
-
return (
|
|
340
|
-
typeof value === 'string' &&
|
|
341
|
-
/^https:\/\/github\.com\/[^/]+\/[^/]+\/blob\/[a-f0-9]{40}\/.+#L[1-9][0-9]*(?:-L[1-9][0-9]*)?$/.test(
|
|
342
|
-
value,
|
|
343
|
-
)
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function add(errors, path, code, message) {
|
|
348
|
-
errors.push({ path, code, message });
|
|
349
|
-
}
|