skill-family-contracts 0.1.3 → 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 +24 -8
- package/package.json +1 -1
- package/src/checker.mjs +18 -14
- package/src/error-codes.json +27 -1
- package/src/errors.mjs +2 -1
- package/src/fixtures/adapter-build-manifest/dialect-01-unsupported.json +7 -0
- package/src/fixtures/adapter-build-manifest/negative-01-path-escape.json +7 -0
- package/src/fixtures/adapter-build-manifest/positive-01-single-file.json +7 -0
- package/src/fixtures/adapter-source/dialect-01-unsupported.json +7 -0
- package/src/fixtures/adapter-source/negative-01-path-escape.json +7 -0
- package/src/fixtures/adapter-source/positive-01-minimal.json +7 -0
- package/src/fixtures/host-capability-fact/dialect-01-unsupported.json +7 -0
- package/src/fixtures/host-capability-fact/negative-01-unknown-without-manual.json +7 -0
- package/src/fixtures/host-capability-fact/positive-01-unknown.json +7 -0
- package/src/fixtures/host-descriptor/dialect-01-unsupported.json +7 -0
- package/src/fixtures/host-descriptor/negative-01-command-data.json +7 -0
- package/src/fixtures/host-descriptor/positive-01-unsupported.json +7 -0
- package/src/fixtures/host-operation-plan/dialect-01-unsupported.json +7 -0
- package/src/fixtures/host-operation-plan/negative-01-unsupported-action.json +7 -0
- package/src/fixtures/host-operation-plan/positive-01-unsupported.json +7 -0
- package/src/fixtures/host-operation-receipt/dialect-01-unsupported.json +7 -0
- package/src/fixtures/host-operation-receipt/negative-01-success-without-hash.json +7 -0
- package/src/fixtures/host-operation-receipt/positive-01-rejected.json +7 -0
- package/src/fixtures/host-probe-result/dialect-01-unsupported.json +7 -0
- package/src/fixtures/host-probe-result/negative-01-unsupported-with-fact.json +7 -0
- package/src/fixtures/host-probe-result/positive-01-unsupported.json +7 -0
- package/src/fixtures/host-registry/dialect-01-unsupported.json +7 -0
- package/src/fixtures/host-registry/negative-01-path-escape.json +7 -0
- package/src/fixtures/host-registry/positive-01-reference.json +7 -0
- package/src/fixtures/report-binding/dialect-01-unsupported-dialect.json +21 -0
- package/src/fixtures/report-binding/negative-01-wrong-kind.json +21 -0
- package/src/fixtures/report-binding/negative-02-short-report-digest.json +21 -0
- package/src/fixtures/report-binding/negative-03-floating-renderer-version.json +21 -0
- package/src/fixtures/report-binding/positive-01-valid-binding.json +21 -0
- package/src/fixtures/report-model/dialect-01-coerce-count-tolerant.json +49 -0
- package/src/fixtures/report-model/dialect-02-coerce-count-strict.json +48 -0
- package/src/fixtures/report-model/negative-01-wrong-kind.json +17 -0
- package/src/fixtures/report-model/negative-02-unknown-field.json +17 -0
- package/src/fixtures/report-model/negative-03-bad-result-digest.json +17 -0
- package/src/fixtures/report-model/negative-04-unsupported-locale.json +22 -0
- package/src/fixtures/report-model/negative-05-empty-evidence.json +46 -0
- package/src/fixtures/report-model/positive-01-full-zh.json +62 -0
- package/src/fixtures/report-model/positive-02-empty-sections-en.json +49 -0
- package/src/fixtures/state-event-envelope/dialect-01-unsupported.json +27 -0
- package/src/fixtures/state-event-envelope/negative-01-zero-fencing.json +27 -0
- package/src/fixtures/state-event-envelope/positive-01-valid.json +27 -0
- package/src/fixtures/state-snapshot-metadata/dialect-01-unsupported.json +20 -0
- package/src/fixtures/state-snapshot-metadata/negative-01-extra-field.json +21 -0
- package/src/fixtures/state-snapshot-metadata/positive-01-valid.json +21 -0
- package/src/index.mjs +18 -4
- package/src/kernel-protocol.json +1 -1
- package/src/registry.json +85 -1
- package/src/rules.json +2 -26
- package/src/schemas/adapter-build-manifest.schema.json +41 -0
- package/src/schemas/adapter-source.schema.json +47 -0
- package/src/schemas/host-capability-fact.schema.json +31 -0
- package/src/schemas/host-descriptor.schema.json +64 -0
- package/src/schemas/host-operation-plan.schema.json +48 -0
- package/src/schemas/host-operation-receipt.schema.json +81 -0
- package/src/schemas/host-probe-result.schema.json +26 -0
- package/src/schemas/host-registry.schema.json +18 -0
- package/src/schemas/report-binding.schema.json +42 -0
- package/src/schemas/report-model.schema.json +308 -0
- package/src/schemas/state-event-envelope.schema.json +38 -0
- package/src/schemas/state-snapshot-metadata.schema.json +25 -0
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
# skill-family-contracts
|
|
5
5
|
|
|
6
|
-
机器可执行工程结构和机制协议的唯一权威包(Contracts
|
|
6
|
+
机器可执行工程结构和机制协议的唯一权威包(Contracts 1.4.0,冻结)。
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
本包拥有:十八类顶层对象的 JSON Schema、Kernel Protocol(内核协议)、稳定错误码、
|
|
9
9
|
协议名/`$id` 登记表,以及九种有限机械检查类型与受限强制规则集。
|
|
10
10
|
本包不执行骨架生成、文件写入、审计或发布;机制实现由 Harness 承担,
|
|
11
11
|
工程命令由 Kit 承担,二者单向消费本包。
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
Schema 验证完全基于 [Ajv](https://ajv.js.org/)(精确版本见 `package.json`),
|
|
14
14
|
按方言路由到对应 Ajv 类;不实现任何手写 Schema 子集解释器。
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## 十八类顶层对象
|
|
17
17
|
|
|
18
18
|
| 对象 | `$id` | Schema 文件 |
|
|
19
19
|
| --- | --- | --- |
|
|
@@ -23,6 +23,18 @@ Schema 验证完全基于 [Ajv](https://ajv.js.org/)(精确版本见 `package.
|
|
|
23
23
|
| `operation-request` | `https://contracts.skill-family.example/v1/operation-request.json` | `src/schemas/operation-request.schema.json` |
|
|
24
24
|
| `operation-result` | `https://contracts.skill-family.example/v1/operation-result.json` | `src/schemas/operation-result.schema.json` |
|
|
25
25
|
| `migration-manifest` | `https://contracts.skill-family.example/v1/migration-manifest.json` | `src/schemas/migration-manifest.schema.json` |
|
|
26
|
+
| `report-model` | `https://contracts.skill-family.example/v1/report-model.json` | `src/schemas/report-model.schema.json` |
|
|
27
|
+
| `report-binding` | `https://contracts.skill-family.example/v1/report-binding.json` | `src/schemas/report-binding.schema.json` |
|
|
28
|
+
| `host-descriptor` | `https://contracts.skill-family.example/v1/host-descriptor.json` | `src/schemas/host-descriptor.schema.json` |
|
|
29
|
+
| `host-capability-fact` | `https://contracts.skill-family.example/v1/host-capability-fact.json` | `src/schemas/host-capability-fact.schema.json` |
|
|
30
|
+
| `adapter-build-manifest` | `https://contracts.skill-family.example/v1/adapter-build-manifest.json` | `src/schemas/adapter-build-manifest.schema.json` |
|
|
31
|
+
| `host-operation-plan` | `https://contracts.skill-family.example/v1/host-operation-plan.json` | `src/schemas/host-operation-plan.schema.json` |
|
|
32
|
+
| `host-operation-receipt` | `https://contracts.skill-family.example/v1/host-operation-receipt.json` | `src/schemas/host-operation-receipt.schema.json` |
|
|
33
|
+
| `adapter-source` | `https://contracts.skill-family.example/v1/adapter-source.json` | `src/schemas/adapter-source.schema.json` |
|
|
34
|
+
| `host-registry` | `https://contracts.skill-family.example/v1/host-registry.json` | `src/schemas/host-registry.schema.json` |
|
|
35
|
+
| `host-probe-result` | `https://contracts.skill-family.example/v1/host-probe-result.json` | `src/schemas/host-probe-result.schema.json` |
|
|
36
|
+
| `state-event-envelope` | `https://contracts.skill-family.example/v1/state-event-envelope.json` | `src/schemas/state-event-envelope.schema.json` |
|
|
37
|
+
| `state-snapshot-metadata` | `https://contracts.skill-family.example/v1/state-snapshot-metadata.json` | `src/schemas/state-snapshot-metadata.schema.json` |
|
|
26
38
|
|
|
27
39
|
所有 v1 Schema 使用 draft 2020-12 方言;实例信封统一为
|
|
28
40
|
`schemaVersion: 1` + 唯一 `kind` 常量 + 各层 `additionalProperties: false`。
|
|
@@ -48,7 +60,7 @@ Schema 验证完全基于 [Ajv](https://ajv.js.org/)(精确版本见 `package.
|
|
|
48
60
|
## 稳定错误码
|
|
49
61
|
|
|
50
62
|
冻结登记表:`src/error-codes.json`。`SFC1xxx` 为合同权威层错误,
|
|
51
|
-
`SFC2xxx`
|
|
63
|
+
`SFC2xxx` 为内核操作错误,`SFC3xxx` 为报告绑定错误。码只增不改、不复用。v1 冻结:
|
|
52
64
|
|
|
53
65
|
| 码 | 名称 | 含义摘要 |
|
|
54
66
|
| --- | --- | --- |
|
|
@@ -67,6 +79,9 @@ Schema 验证完全基于 [Ajv](https://ajv.js.org/)(精确版本见 `package.
|
|
|
67
79
|
| SFC2002 | UNKNOWN_OPERATION | 操作名不在冻结词汇表 |
|
|
68
80
|
| SFC2003 | INVALID_PARAMS | 参数不满足操作的冻结 params 合同 |
|
|
69
81
|
| SFC2004 | EXECUTION_FAILED | 机制运行时执行失败(仅运行时可演示) |
|
|
82
|
+
| SFC3001 | REPORT_DIGEST_MISMATCH | 报告或结果摘要与绑定不一致 |
|
|
83
|
+
| SFC3002 | REPORT_ELEMENT_MISSING | 报告缺少强制元素 |
|
|
84
|
+
| SFC3003 | REPORT_FACT_DRIFT | 报告字节偏离确定性重渲染结果 |
|
|
70
85
|
|
|
71
86
|
## 方言与验证策略(Ajv)
|
|
72
87
|
|
|
@@ -85,13 +100,14 @@ Schema 验证完全基于 [Ajv](https://ajv.js.org/)(精确版本见 `package.
|
|
|
85
100
|
`schema.ref-resolves`、`schema.dialect-declared`、`fixture.positive-passes`、
|
|
86
101
|
`fixture.negative-coded`、`error-code.registered`、`rules.budget`。
|
|
87
102
|
|
|
88
|
-
|
|
103
|
+
当前强制规则 **9 条**(CR-001、CR-006…CR-013)。其中 CR-001 对登记表内全部 Schema 做统一编译,
|
|
104
|
+
不再为每个对象重复占用一条规则;预算上限 20 条、绝对上限 30 条;
|
|
89
105
|
`rules.budget` 是机械门禁,超限即 `runChecks` 失败并报 `SFC1008`。
|
|
90
106
|
|
|
91
107
|
## Fixture
|
|
92
108
|
|
|
93
109
|
`src/fixtures/<contract>/` 为每类合同提供正例(positive)、反例(negative)
|
|
94
|
-
与方言边界(dialect-boundary)样例,共
|
|
110
|
+
与方言边界(dialect-boundary)样例,共 76 个。每个 fixture 声明目标 Schema、
|
|
95
111
|
方言、策略与期望;反例期望携带稳定失败码。`verifyAllFixtures()` 机械重放全部期望,
|
|
96
112
|
行为不符报 `SFC1010`。fixture 是完全虚构数据,不是审计 oracle。
|
|
97
113
|
|
|
@@ -125,14 +141,14 @@ import {
|
|
|
125
141
|
## 安装
|
|
126
142
|
|
|
127
143
|
```sh
|
|
128
|
-
npm install skill-family-contracts@0.
|
|
144
|
+
npm install skill-family-contracts@0.2.0
|
|
129
145
|
npm info skill-family-contracts --help
|
|
130
146
|
```
|
|
131
147
|
|
|
132
148
|
## 最小示例
|
|
133
149
|
|
|
134
150
|
```js
|
|
135
|
-
// 从空目录运行:npm install skill-family-contracts@0.
|
|
151
|
+
// 从空目录运行:npm install skill-family-contracts@0.2.0
|
|
136
152
|
import { validateDocument } from "skill-family-contracts";
|
|
137
153
|
|
|
138
154
|
const document = {
|
package/package.json
CHANGED
package/src/checker.mjs
CHANGED
|
@@ -117,22 +117,26 @@ function schemaEntries(ctx) {
|
|
|
117
117
|
|
|
118
118
|
const HANDLERS = {
|
|
119
119
|
"schema.compile": (rule, ctx) => {
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (
|
|
124
|
-
return fail(rule, "SFC1002", `no registered schema for
|
|
120
|
+
const registrations = rule.target.registry === "schemas"
|
|
121
|
+
? ctx.registry.schemas
|
|
122
|
+
: ctx.registry.schemas.filter((entry) => entry.object === rule.target.object);
|
|
123
|
+
if (registrations.length === 0) {
|
|
124
|
+
return fail(rule, "SFC1002", `no registered schema for target: ${rule.target.object ?? rule.target.registry}`);
|
|
125
125
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
126
|
+
for (const registration of registrations) {
|
|
127
|
+
try {
|
|
128
|
+
compileSchema(
|
|
129
|
+
{ schema: ctx.loadSchema(registration) },
|
|
130
|
+
{ dialect: registration.dialect, policy: "strict" },
|
|
131
|
+
);
|
|
132
|
+
} catch (cause) {
|
|
133
|
+
if (cause instanceof ContractsError) {
|
|
134
|
+
return fail(rule, cause.code, `${registration.object}: ${cause.message}`);
|
|
135
|
+
}
|
|
136
|
+
throw cause;
|
|
137
|
+
}
|
|
135
138
|
}
|
|
139
|
+
return pass(rule);
|
|
136
140
|
},
|
|
137
141
|
|
|
138
142
|
"schema.unique-id": (rule, ctx) => {
|
package/src/error-codes.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"kind": "skill-family.contracts.error-codes",
|
|
4
|
-
"contractsVersion": "1.
|
|
4
|
+
"contractsVersion": "1.4.0",
|
|
5
5
|
"policy": {
|
|
6
6
|
"format": "^SFC[0-9]{4}$",
|
|
7
7
|
"ranges": [
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
"prefix": "SFC2",
|
|
15
15
|
"category": "kernel",
|
|
16
16
|
"note": "Kernel protocol operation errors."
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"prefix": "SFC3",
|
|
20
|
+
"category": "report",
|
|
21
|
+
"note": "Report contract errors: digest binding, mandatory elements, fact drift. Style findings are never coded here; they are advisory output of the report check, not errors."
|
|
17
22
|
}
|
|
18
23
|
],
|
|
19
24
|
"stability": "Codes are append-only. A frozen code is never reused for a different meaning; a deprecated code stays reserved. New codes require a contracts change."
|
|
@@ -123,6 +128,27 @@
|
|
|
123
128
|
"category": "kernel",
|
|
124
129
|
"stableSince": "1.0.0",
|
|
125
130
|
"meaning": "The mechanism runtime failed while executing a well-formed operation; details carry the mechanism evidence. Demonstrable only by a mechanism runtime, not by static contracts checks."
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"code": "SFC3001",
|
|
134
|
+
"name": "REPORT_DIGEST_MISMATCH",
|
|
135
|
+
"category": "report",
|
|
136
|
+
"stableSince": "1.2.0",
|
|
137
|
+
"meaning": "A report binding digest (model, result, or report digest) does not match the recomputed sha256 digest, or the report is not the canonical render of its model; the binding is stale or tampered and is never trusted."
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"code": "SFC3002",
|
|
141
|
+
"name": "REPORT_ELEMENT_MISSING",
|
|
142
|
+
"category": "report",
|
|
143
|
+
"stableSince": "1.2.0",
|
|
144
|
+
"meaning": "A mandatory report element is absent, empty where it must not be, or declared in an unsupported form: the conclusion, non-empty evidence, risks/next-action sections, a supported locale, or a coded outcome for failed/blocked runs. No half report is issued for a missing element."
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"code": "SFC3003",
|
|
148
|
+
"name": "REPORT_FACT_DRIFT",
|
|
149
|
+
"category": "report",
|
|
150
|
+
"stableSince": "1.2.0",
|
|
151
|
+
"meaning": "A report model misstates the bound operation result's terminal state/errors, or rendered report bytes diverge from the deterministic re-render of the bound report model: fact fields rewritten, sections deleted, duplicated, or injected."
|
|
126
152
|
}
|
|
127
153
|
]
|
|
128
154
|
}
|
package/src/errors.mjs
CHANGED
|
@@ -17,7 +17,8 @@ function deepFreeze(obj) {
|
|
|
17
17
|
*
|
|
18
18
|
* The registry file (error-codes.json) is the single source of truth; codes are
|
|
19
19
|
* append-only and never reused. SFC1xxx covers contracts-authority failures,
|
|
20
|
-
* SFC2xxx covers kernel-operation failures
|
|
20
|
+
* SFC2xxx covers kernel-operation failures, SFC3xxx covers report-contract
|
|
21
|
+
* failures (digest binding, mandatory elements, fact drift).
|
|
21
22
|
*/
|
|
22
23
|
|
|
23
24
|
const ERROR_REGISTRY = deepFreeze(JSON.parse(
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "adapter-build-manifest.dialect-boundary.unsupported", "contract": "adapter-build-manifest", "class": "dialect-boundary",
|
|
3
|
+
"description": "Unsupported schema dialect fails before validation.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/adapter-build-manifest.json", "dialect": "draft-04", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1006" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.adapter-build-manifest" }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "adapter-build-manifest.negative.path-escape", "contract": "adapter-build-manifest", "class": "negative",
|
|
3
|
+
"description": "An escaping target is rejected.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/adapter-build-manifest.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.adapter-build-manifest", "hostId": "fixture-host", "pathCategory": { "id": "fixture-project-skills", "scope": "project", "anchor": "project-root", "relPath": ".fixture/skills" }, "sourceClosure": { "digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "members": [{ "sourcePath": "demo/SKILL.md", "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bytes": 4 }] }, "members": [{ "sourcePath": "demo/SKILL.md", "target": "../outside", "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bytes": 4 }], "digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "adapter-build-manifest.positive.single-file", "contract": "adapter-build-manifest", "class": "positive",
|
|
3
|
+
"description": "A manifest binds one source byte set to one controlled target.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/adapter-build-manifest.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": true },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.adapter-build-manifest", "hostId": "fixture-host", "pathCategory": { "id": "fixture-project-skills", "scope": "project", "anchor": "project-root", "relPath": ".fixture/skills" }, "sourceClosure": { "digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "members": [{ "sourcePath": "demo/SKILL.md", "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bytes": 4 }] }, "members": [{ "sourcePath": "demo/SKILL.md", "target": ".fixture/skills/demo/SKILL.md", "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bytes": 4 }], "digest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "adapter-source.dialect-boundary.unsupported", "contract": "adapter-source", "class": "dialect-boundary",
|
|
3
|
+
"description": "Unsupported schema dialect fails before source validation.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/adapter-source.json", "dialect": "draft-04", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1006" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.adapter-source", "skillFamilyId": "fixture-family", "skills": [{ "id": "demo-skill", "files": [{ "path": "SKILL.md", "content": "# Demo\n" }] }] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "adapter-source.negative.path-escape", "contract": "adapter-source", "class": "negative",
|
|
3
|
+
"description": "An adapter source path cannot escape its declared skill directory.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/adapter-source.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.adapter-source", "skillFamilyId": "fixture-family", "skills": [{ "id": "demo-skill", "files": [{ "path": "../outside", "content": "bad" }] }] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "adapter-source.positive.minimal", "contract": "adapter-source", "class": "positive",
|
|
3
|
+
"description": "A minimal source closure contains one skill and its required SKILL.md bytes.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/adapter-source.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": true },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.adapter-source", "skillFamilyId": "fixture-family", "skills": [{ "id": "demo-skill", "files": [{ "path": "SKILL.md", "content": "# Demo\n" }] }] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-capability-fact.dialect-boundary.unsupported", "contract": "host-capability-fact", "class": "dialect-boundary",
|
|
3
|
+
"description": "Unsupported schema dialect fails before validation.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-capability-fact.json", "dialect": "draft-04", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1006" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-capability-fact", "hostId": "fixture-host", "capability": "smoke", "state": "unknown", "evidence": ["No frozen probe."], "unknownReason": "driver-limited", "manualSteps": ["Verify manually."] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-capability-fact.negative.unknown-without-manual", "contract": "host-capability-fact", "class": "negative",
|
|
3
|
+
"description": "Unknown without a manual verification path is rejected.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-capability-fact.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-capability-fact", "hostId": "fixture-host", "capability": "smoke", "state": "unknown", "evidence": ["No frozen probe."], "unknownReason": "driver-limited" }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-capability-fact.positive.unknown", "contract": "host-capability-fact", "class": "positive",
|
|
3
|
+
"description": "An unknown fact includes a reason and manual steps.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-capability-fact.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": true },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-capability-fact", "hostId": "fixture-host", "capability": "smoke", "state": "unknown", "evidence": ["No frozen probe."], "unknownReason": "driver-limited", "manualSteps": ["Verify manually."] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-descriptor.dialect-boundary.unsupported", "contract": "host-descriptor", "class": "dialect-boundary",
|
|
3
|
+
"description": "Unsupported schema dialect fails before validation.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-descriptor.json", "dialect": "draft-04", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1006" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-descriptor", "hostId": "fixture-host", "displayName": "Fixture Host", "support": "unsupported", "unsupportedReason": "No frozen driver.", "pathCategories": [], "probeCapabilities": [] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-descriptor.negative.command-data", "contract": "host-descriptor", "class": "negative",
|
|
3
|
+
"description": "Descriptor command data is outside the closed contract.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-descriptor.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-descriptor", "hostId": "fixture-host", "displayName": "Fixture Host", "support": "unsupported", "unsupportedReason": "No frozen driver.", "pathCategories": [], "probeCapabilities": [], "executable": "dangerous" }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-descriptor.positive.unsupported", "contract": "host-descriptor", "class": "positive",
|
|
3
|
+
"description": "An unsupported host is explicit and carries neither a driver nor paths.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-descriptor.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": true },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-descriptor", "hostId": "fixture-host", "displayName": "Fixture Host", "support": "unsupported", "unsupportedReason": "No frozen driver.", "pathCategories": [], "probeCapabilities": [] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-operation-plan.dialect-boundary.unsupported", "contract": "host-operation-plan", "class": "dialect-boundary",
|
|
3
|
+
"description": "Unsupported schema dialect fails before validation.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-operation-plan.json", "dialect": "draft-04", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1006" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-operation-plan" }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-operation-plan.negative.unsupported-action", "contract": "host-operation-plan", "class": "negative",
|
|
3
|
+
"description": "Unsupported planning cannot hide an action.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-operation-plan.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-operation-plan", "hostId": "fixture-host", "status": "unsupported", "unsupportedReason": "No frozen driver.", "probeFacts": [], "actions": [{ "sequence": 1 }], "writeSet": [], "digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-operation-plan.positive.unsupported", "contract": "host-operation-plan", "class": "positive",
|
|
3
|
+
"description": "Unsupported planning is an explicit zero-action result.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-operation-plan.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": true },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-operation-plan", "hostId": "fixture-host", "status": "unsupported", "unsupportedReason": "No frozen driver.", "probeFacts": [], "actions": [], "writeSet": [], "digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-operation-receipt.dialect-boundary.unsupported", "contract": "host-operation-receipt", "class": "dialect-boundary",
|
|
3
|
+
"description": "Unsupported schema dialect fails before validation.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-operation-receipt.json", "dialect": "draft-04", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1006" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-operation-receipt" }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-operation-receipt.negative.success-without-hash", "contract": "host-operation-receipt", "class": "negative",
|
|
3
|
+
"description": "A successful write without sha256 is rejected.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-operation-receipt.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-operation-receipt", "hostId": "fixture-host", "planDigest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "overall": "succeeded", "authorizationRef": "approval-1", "writes": [{ "target": ".fixture/skills/demo/SKILL.md", "outcome": "succeeded" }], "closure": { "digestAlgorithm": "sha256", "digest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "resources": [{ "path": ".fixture/skills/demo/SKILL.md", "sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }] } }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-operation-receipt.positive.rejected", "contract": "host-operation-receipt", "class": "positive",
|
|
3
|
+
"description": "A rejected receipt has a reason and zero writes.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-operation-receipt.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": true },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-operation-receipt", "hostId": "fixture-host", "planDigest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "overall": "rejected", "reason": "Apply is unavailable.", "writes": [] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-probe-result.dialect-boundary.unsupported", "contract": "host-probe-result", "class": "dialect-boundary",
|
|
3
|
+
"description": "Unsupported schema dialect fails before probe-result validation.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-probe-result.json", "dialect": "draft-04", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1006" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-probe-result", "hostId": "fixture-host", "support": "unsupported", "reason": "No audited driver.", "facts": [] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-probe-result.negative.unsupported-with-fact", "contract": "host-probe-result", "class": "negative",
|
|
3
|
+
"description": "An unsupported host cannot claim a capability fact.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-probe-result.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-probe-result", "hostId": "fixture-host", "support": "unsupported", "reason": "No audited driver.", "facts": [{ "schemaVersion": 1, "kind": "skill-family.host-capability-fact", "hostId": "fixture-host", "capability": "cli", "state": "unavailable", "evidence": ["Not present."] }] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-probe-result.positive.unsupported", "contract": "host-probe-result", "class": "positive",
|
|
3
|
+
"description": "An unsupported host probe is explicit and contains no capability facts.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-probe-result.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": true },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-probe-result", "hostId": "fixture-host", "support": "unsupported", "reason": "No audited driver.", "facts": [] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-registry.dialect-boundary.unsupported", "contract": "host-registry", "class": "dialect-boundary",
|
|
3
|
+
"description": "Unsupported schema dialect fails before registry validation.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-registry.json", "dialect": "draft-04", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1006" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-registry", "hosts": ["fixture-host"] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-registry.negative.duplicate-host", "contract": "host-registry", "class": "negative",
|
|
3
|
+
"description": "A registry cannot declare the same fictional host twice.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-registry.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-registry", "hosts": ["fixture-host", "fixture-host"] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "host-registry.positive.reference", "contract": "host-registry", "class": "positive",
|
|
3
|
+
"description": "A registry declares fictional host identifiers without embedding Profile data.",
|
|
4
|
+
"validation": { "schemaId": "https://contracts.skill-family.example/v1/host-registry.json", "dialect": "2020-12", "policy": "strict" },
|
|
5
|
+
"expect": { "valid": true },
|
|
6
|
+
"data": { "schemaVersion": 1, "kind": "skill-family.host-registry", "hosts": ["fixture-host"] }
|
|
7
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "report-binding.dialect-boundary.unsupported-dialect",
|
|
3
|
+
"contract": "report-binding",
|
|
4
|
+
"class": "dialect-boundary",
|
|
5
|
+
"description": "Dialect boundary: a valid binding document declared under an unsupported dialect (draft-04) is rejected before any schema validation, with the stable dialect code.",
|
|
6
|
+
"validation": {
|
|
7
|
+
"schemaId": "https://contracts.skill-family.example/v1/report-binding.json",
|
|
8
|
+
"dialect": "draft-04",
|
|
9
|
+
"policy": "strict"
|
|
10
|
+
},
|
|
11
|
+
"expect": { "valid": false, "errorCode": "SFC1006" },
|
|
12
|
+
"data": {
|
|
13
|
+
"schemaVersion": 1,
|
|
14
|
+
"kind": "skill-family.report-binding",
|
|
15
|
+
"runId": "run-aurora-0001",
|
|
16
|
+
"modelDigest": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
|
17
|
+
"resultDigest": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
18
|
+
"reportDigest": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
|
|
19
|
+
"rendererVersion": "0.2.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "report-binding.negative.wrong-kind",
|
|
3
|
+
"contract": "report-binding",
|
|
4
|
+
"class": "negative",
|
|
5
|
+
"description": "A binding with a wrong kind discriminator is rejected: a report model or any other document cannot impersonate the binding envelope.",
|
|
6
|
+
"validation": {
|
|
7
|
+
"schemaId": "https://contracts.skill-family.example/v1/report-binding.json",
|
|
8
|
+
"dialect": "2020-12",
|
|
9
|
+
"policy": "strict"
|
|
10
|
+
},
|
|
11
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
12
|
+
"data": {
|
|
13
|
+
"schemaVersion": 1,
|
|
14
|
+
"kind": "skill-family.report-model",
|
|
15
|
+
"runId": "run-aurora-0001",
|
|
16
|
+
"modelDigest": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
|
17
|
+
"resultDigest": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
18
|
+
"reportDigest": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
|
|
19
|
+
"rendererVersion": "0.2.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "report-binding.negative.short-report-digest",
|
|
3
|
+
"contract": "report-binding",
|
|
4
|
+
"class": "negative",
|
|
5
|
+
"description": "A truncated reportDigest is rejected: a binding must carry the full sha256 hex of the rendered report bytes; a shortened digest never verifies.",
|
|
6
|
+
"validation": {
|
|
7
|
+
"schemaId": "https://contracts.skill-family.example/v1/report-binding.json",
|
|
8
|
+
"dialect": "2020-12",
|
|
9
|
+
"policy": "strict"
|
|
10
|
+
},
|
|
11
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
12
|
+
"data": {
|
|
13
|
+
"schemaVersion": 1,
|
|
14
|
+
"kind": "skill-family.report-binding",
|
|
15
|
+
"runId": "run-aurora-0001",
|
|
16
|
+
"modelDigest": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
|
17
|
+
"resultDigest": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
18
|
+
"reportDigest": "fedcba9876543210",
|
|
19
|
+
"rendererVersion": "0.2.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "report-binding.negative.floating-renderer-version",
|
|
3
|
+
"contract": "report-binding",
|
|
4
|
+
"class": "negative",
|
|
5
|
+
"description": "A floating renderer version is rejected: the binding must pin an exact renderer semver; ranges and tags are not bindings.",
|
|
6
|
+
"validation": {
|
|
7
|
+
"schemaId": "https://contracts.skill-family.example/v1/report-binding.json",
|
|
8
|
+
"dialect": "2020-12",
|
|
9
|
+
"policy": "strict"
|
|
10
|
+
},
|
|
11
|
+
"expect": { "valid": false, "errorCode": "SFC1001" },
|
|
12
|
+
"data": {
|
|
13
|
+
"schemaVersion": 1,
|
|
14
|
+
"kind": "skill-family.report-binding",
|
|
15
|
+
"runId": "run-aurora-0001",
|
|
16
|
+
"modelDigest": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
|
17
|
+
"resultDigest": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
18
|
+
"reportDigest": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
|
|
19
|
+
"rendererVersion": "^1.2.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "report-binding.positive.valid-binding",
|
|
3
|
+
"contract": "report-binding",
|
|
4
|
+
"class": "positive",
|
|
5
|
+
"description": "A complete binding: run identity, sha256 result digest, sha256 report digest, and an exact renderer semver.",
|
|
6
|
+
"validation": {
|
|
7
|
+
"schemaId": "https://contracts.skill-family.example/v1/report-binding.json",
|
|
8
|
+
"dialect": "2020-12",
|
|
9
|
+
"policy": "strict"
|
|
10
|
+
},
|
|
11
|
+
"expect": { "valid": true },
|
|
12
|
+
"data": {
|
|
13
|
+
"schemaVersion": 1,
|
|
14
|
+
"kind": "skill-family.report-binding",
|
|
15
|
+
"runId": "run-aurora-0001",
|
|
16
|
+
"modelDigest": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
|
17
|
+
"resultDigest": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
18
|
+
"reportDigest": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
|
|
19
|
+
"rendererVersion": "0.2.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtureId": "report-model.dialect-boundary.coerce-count-tolerant",
|
|
3
|
+
"contract": "report-model",
|
|
4
|
+
"class": "dialect-boundary",
|
|
5
|
+
"description": "Coercion policy boundary: a string-valued section count passes only because the tolerant policy enables Ajv integer coercion.",
|
|
6
|
+
"validation": {
|
|
7
|
+
"schemaId": "https://contracts.skill-family.example/v1/report-model.json",
|
|
8
|
+
"dialect": "2020-12",
|
|
9
|
+
"policy": "tolerant"
|
|
10
|
+
},
|
|
11
|
+
"expect": { "valid": true },
|
|
12
|
+
"data": {
|
|
13
|
+
"schemaVersion": 1,
|
|
14
|
+
"kind": "skill-family.report-model",
|
|
15
|
+
"identity": {
|
|
16
|
+
"runId": "run-borealis-0043",
|
|
17
|
+
"skillFamily": "borealis-index-rebuild",
|
|
18
|
+
"audience": "operator",
|
|
19
|
+
"locale": "en-US"
|
|
20
|
+
},
|
|
21
|
+
"timeRange": { "startedAt": "2026-08-09T08:00:00Z", "completedAt": "2026-08-09T08:05:00Z" },
|
|
22
|
+
"outcome": {
|
|
23
|
+
"executionStatus": "SUCCEEDED",
|
|
24
|
+
"summary": "Coercion boundary probe.",
|
|
25
|
+
"counts": {
|
|
26
|
+
"changes": "0",
|
|
27
|
+
"evidence": 1,
|
|
28
|
+
"risks": 0,
|
|
29
|
+
"unresolved": 0,
|
|
30
|
+
"nextActions": 0,
|
|
31
|
+
"appendices": 0
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"errors": [],
|
|
35
|
+
"changes": [],
|
|
36
|
+
"evidence": [
|
|
37
|
+
{ "id": "evd-1", "title": "Run log", "reference": "logs/borealis-0043.log" }
|
|
38
|
+
],
|
|
39
|
+
"risks": [],
|
|
40
|
+
"unresolved": [],
|
|
41
|
+
"nextActions": [],
|
|
42
|
+
"appendices": [],
|
|
43
|
+
"source": {
|
|
44
|
+
"resultDigest": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210",
|
|
45
|
+
"resultState": "succeeded"
|
|
46
|
+
},
|
|
47
|
+
"renderer": { "name": "skill-family-harness-node/report", "version": "0.2.0" }
|
|
48
|
+
}
|
|
49
|
+
}
|