stylegallery 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -1
- package/DOMAINS.md +2 -6
- package/GOVERNANCE.md +10 -9
- package/README.md +23 -127
- package/consumer-reference/agent-native/v2/admission-policy.json +646 -0
- package/consumer-reference/agent-native/v2/material-registry.json +1 -0
- package/consumer-reference/agent-native/v2/schema/admission-policy.schema.json +50 -0
- package/consumer-reference/agent-native/v2/schema/material-manifest.schema.json +17 -0
- package/consumer-reference/agent-native/v2/schema/material-record.schema.json +20 -0
- package/consumer-reference/contract.md +1 -1
- package/consumer-reference/index.md +5 -3
- package/layout/index.md +124 -0
- package/log.md +51 -0
- package/package.json +181 -22
- package/scripts/agent-native/v2/experimental-extension-registry.mjs +143 -0
- package/scripts/agent-native/v2/extensions/a2a-projection.mjs +264 -0
- package/scripts/agent-native/v2/extensions/agui-projection.mjs +191 -0
- package/scripts/agent-native/v2/material-admission.mjs +295 -0
- package/scripts/agent-native/v2/material-cli-adapter.mjs +134 -0
- package/scripts/agent-native/v2/material-context.mjs +251 -0
- package/scripts/agent-native/v2/material-identity.mjs +71 -0
- package/scripts/agent-native/v2/material-mcp-adapter.mjs +253 -0
- package/scripts/agent-native/v2/material-operation-registry.mjs +123 -0
- package/scripts/agent-native/v2/material-queries.mjs +398 -0
- package/scripts/agent-native/v2/material-registry.mjs +319 -0
- package/scripts/sg-material-mcp.mjs +98 -0
- package/scripts/sg-material.mjs +27 -0
- package/consumer-reference/adapters/style-dictionary.config.mjs +0 -36
- package/consumer-reference/baselines/calibration.json +0 -260
- package/consumer-reference/baselines/manifest.json +0 -21
- package/consumer-reference/fixtures/consumer-conformance/e2e-fixture.mjs +0 -282
- package/consumer-reference/fixtures/consumer-conformance/manifest.json +0 -102
- package/consumer-reference/fixtures/consumer-conformance/runtime-proof.mjs +0 -32
- package/consumer-reference/fixtures/consumer-conformance/valid-migration-result.json +0 -18
- package/consumer-reference/fixtures/consumer-conformance/valid-migration.json +0 -142
- package/consumer-reference/fixtures/invalid-stable-ended-support.json +0 -19
- package/consumer-reference/fixtures/promotion/invalid-blocking-evidence.json +0 -26
- package/consumer-reference/fixtures/promotion/invalid-count-only.json +0 -29
- package/consumer-reference/fixtures/promotion/invalid-missing-owner-migration.json +0 -25
- package/consumer-reference/fixtures/promotion/invalid-normative-bypass-no-regression.json +0 -25
- package/consumer-reference/fixtures/promotion/invalid-related-counted-independent.json +0 -45
- package/consumer-reference/fixtures/promotion/invalid-stable-ended-support.json +0 -26
- package/consumer-reference/fixtures/promotion/manifest.json +0 -15
- package/consumer-reference/fixtures/promotion/valid-deferred-example.json +0 -67
- package/consumer-reference/fixtures/promotion/valid-normative-bypass.json +0 -67
- package/consumer-reference/fixtures/token-portability/invalid-cycle.json +0 -7
- package/consumer-reference/fixtures/token-portability/invalid-dangling-alias.json +0 -6
- package/consumer-reference/fixtures/token-portability/invalid-extends.json +0 -4
- package/consumer-reference/fixtures/token-portability/invalid-json-pointer.json +0 -7
- package/consumer-reference/fixtures/token-portability/invalid-resolver.json +0 -9
- package/consumer-reference/fixtures/token-portability/invalid-type-mismatch.json +0 -10
- package/consumer-reference/fixtures/token-portability/invalid-unknown-reserved.json +0 -6
- package/consumer-reference/fixtures/token-portability/invalid-untested-type.json +0 -6
- package/consumer-reference/fixtures/token-portability/valid-border.json +0 -14
- package/consumer-reference/fixtures/token-portability/valid-reference.json +0 -32
- package/consumer-reference/fixtures/token-portability/valid-whole-alias.json +0 -7
- package/consumer-reference/fixtures/valid-deprecated.json +0 -21
- package/consumer-reference/fixtures/valid-experimental.json +0 -19
- package/consumer-reference/generated/manifest.json +0 -40
- package/consumer-reference/generated/tokens.css +0 -12
- package/consumer-reference/policies/shared-experimental.json +0 -37
- package/consumer-reference/schema/ax-evidence.schema.json +0 -30
- package/consumer-reference/schema/baseline-manifest.schema.json +0 -55
- package/consumer-reference/schema/calibration-record.schema.json +0 -190
- package/consumer-reference/schema/capture-session.schema.json +0 -161
- package/consumer-reference/schema/component-state.schema.json +0 -150
- package/consumer-reference/schema/consumer-conformance-record.schema.json +0 -365
- package/consumer-reference/schema/dom-evidence.schema.json +0 -38
- package/consumer-reference/schema/evidence-record.schema.json +0 -81
- package/consumer-reference/schema/fixture-manifest.schema.json +0 -32
- package/consumer-reference/schema/item.schema.json +0 -188
- package/consumer-reference/schema/page-evidence-manifest.schema.json +0 -216
- package/consumer-reference/schema/page-evidence-session.schema.json +0 -119
- package/consumer-reference/schema/portable-tokens.schema.json +0 -104
- package/consumer-reference/schema/promotion-rfc.schema.json +0 -219
- package/consumer-reference/schema/runtime-evidence-manifest.schema.json +0 -33
- package/consumer-reference/schema/visual-evidence.schema.json +0 -31
- package/design-engineering/consumer-migration-readiness.md +0 -124
- package/design-engineering/interface-craft.md +0 -107
- package/design-engineering/reference-profiles/external-adaptation/index.md +0 -12
- package/design-engineering/reference-profiles/governed-local/editorial/components/button.component.json +0 -125
- package/design-engineering/reference-profiles/governed-local/editorial/evidence/button.evidence.json +0 -3504
- package/design-engineering/reference-profiles/governed-local/editorial/fixtures/button.fixture.json +0 -65
- package/design-engineering/reference-profiles/governed-local/editorial/generated/evidence-coverage.md +0 -23
- package/design-engineering/reference-profiles/governed-local/editorial/generated/keyboard-matrix.md +0 -19
- package/design-engineering/reference-profiles/governed-local/editorial/generated/state-matrix.md +0 -21
- package/design-engineering/reference-profiles/governed-local/editorial/local-foundations.json +0 -12
- package/design-engineering/reference-profiles/governed-local/editorial/states/button.states.json +0 -195
- package/design-engineering/reference-profiles/governed-local/editorial/tokens.dtcg.json +0 -17
- package/design-engineering/reference-profiles/governed-local/terminal/components/button.component.json +0 -125
- package/design-engineering/reference-profiles/governed-local/terminal/evidence/button.evidence.json +0 -3504
- package/design-engineering/reference-profiles/governed-local/terminal/fixtures/button.fixture.json +0 -65
- package/design-engineering/reference-profiles/governed-local/terminal/generated/evidence-coverage.md +0 -23
- package/design-engineering/reference-profiles/governed-local/terminal/generated/keyboard-matrix.md +0 -19
- package/design-engineering/reference-profiles/governed-local/terminal/generated/state-matrix.md +0 -21
- package/design-engineering/reference-profiles/governed-local/terminal/local-foundations.json +0 -12
- package/design-engineering/reference-profiles/governed-local/terminal/profile.json +0 -43
- package/design-engineering/reference-profiles/governed-local/terminal/states/button.states.json +0 -195
- package/design-engineering/reference-profiles/governed-local/terminal/tokens.dtcg.json +0 -17
- package/game-ui/classification.md +0 -82
- package/game-ui/reference-record.md +0 -62
- package/game-ui/screen-hierarchy.md +0 -107
- package/game-ui/unity/architecture.md +0 -166
- package/game-ui/unity/cli-loop.md +0 -84
- package/game-ui/unity/data/unity-technologies-public-repositories.json +0 -26654
- package/game-ui/unity/org-wiki.md +0 -146
- package/game-ui/unity/repository-map.md +0 -102
- package/game-ui/unity/ui-systems.md +0 -85
- package/motion/practice-reference.md +0 -145
- package/motion/review-workflow.md +0 -86
- package/motion/vocabulary.md +0 -82
- package/platform-guides/apple-interaction.md +0 -89
- package/scripts/agent-native/events.mjs +0 -113
- package/scripts/agent-native/immutable-store.mjs +0 -102
- package/scripts/artifact-metadata.mjs +0 -20
- package/scripts/audit-evidence-freshness.mjs +0 -308
- package/scripts/baseline-contract.mjs +0 -189
- package/scripts/baseline-schema-parity.mjs +0 -40
- package/scripts/build-reference-artifacts.mjs +0 -127
- package/scripts/calibration-raw-contract.mjs +0 -172
- package/scripts/capture-session-contract.mjs +0 -187
- package/scripts/component-state-artifact-fixture.mjs +0 -44
- package/scripts/component-state-contract.mjs +0 -99
- package/scripts/component-state-semantics.mjs +0 -128
- package/scripts/component-state-workflow-contract.mjs +0 -67
- package/scripts/component-state-workflow-negative-cases.mjs +0 -64
- package/scripts/consumer-conformance-contract.mjs +0 -198
- package/scripts/consumer-evidence-governance-contract.mjs +0 -210
- package/scripts/consumer-reference-case-runner.mjs +0 -93
- package/scripts/consumer-reference-schema.mjs +0 -155
- package/scripts/create-component-state-session.mjs +0 -100
- package/scripts/create-page-evidence-session.mjs +0 -139
- package/scripts/domain-document-boundaries.mjs +0 -40
- package/scripts/domain-validation-checks.mjs +0 -141
- package/scripts/evidence-artifact-contract.mjs +0 -191
- package/scripts/finalize-component-state-evidence.mjs +0 -165
- package/scripts/finalize-page-evidence.mjs +0 -197
- package/scripts/generate-consumer-reference-evidence.mjs +0 -154
- package/scripts/generate-patterns.mjs +0 -218
- package/scripts/governance-matrix-contract.mjs +0 -73
- package/scripts/governance-matrix-negative-cases.mjs +0 -114
- package/scripts/governance-policy-contract.mjs +0 -49
- package/scripts/governance-test-fixture.mjs +0 -321
- package/scripts/governance-workflow-negative-cases.mjs +0 -241
- package/scripts/governed-profile-registry.mjs +0 -125
- package/scripts/json-schema-formats.mjs +0 -31
- package/scripts/markdown-structure.mjs +0 -45
- package/scripts/page-artifact-metadata.mjs +0 -124
- package/scripts/page-evidence-contract.mjs +0 -297
- package/scripts/page-evidence-fixture.mjs +0 -271
- package/scripts/pattern-data.mjs +0 -325
- package/scripts/profile-record-contract.mjs +0 -140
- package/scripts/promotion-attestation-contract.mjs +0 -91
- package/scripts/promotion-boundary-test-contract.mjs +0 -92
- package/scripts/promotion-fixture-inventory.mjs +0 -109
- package/scripts/promotion-governance-contract.mjs +0 -28
- package/scripts/reference-artifact-path-contract.mjs +0 -28
- package/scripts/reference-profile-contract.mjs +0 -114
- package/scripts/reference-token-contract.mjs +0 -156
- package/scripts/run-consumer-page-evidence-ci.mjs +0 -170
- package/scripts/summarize-sentinel-calibration.mjs +0 -98
- package/scripts/test-agent-adapter-conformance.mjs +0 -250
- package/scripts/test-agent-conformance-receipt.mjs +0 -106
- package/scripts/test-agent-events.mjs +0 -81
- package/scripts/test-agent-execution-effects.mjs +0 -114
- package/scripts/test-agent-execution-fixtures.mjs +0 -140
- package/scripts/test-agent-execution-kernel.mjs +0 -39
- package/scripts/test-agent-execution-learning.mjs +0 -130
- package/scripts/test-agent-execution-lifecycle.mjs +0 -143
- package/scripts/test-agent-execution-safety.mjs +0 -158
- package/scripts/test-agent-execution-views.mjs +0 -117
- package/scripts/test-agent-identity-integrity-cases.mjs +0 -160
- package/scripts/test-agent-knowledge-kernel.mjs +0 -183
- package/scripts/test-agent-learning.mjs +0 -246
- package/scripts/test-agent-mcp.mjs +0 -246
- package/scripts/test-agent-native-schemas.mjs +0 -215
- package/scripts/test-agent-projections.mjs +0 -249
- package/scripts/test-agent-registry-mcp-integrity.mjs +0 -215
- package/scripts/test-agent-registry-mutations.mjs +0 -110
- package/scripts/test-audit-evidence-freshness.mjs +0 -177
- package/scripts/test-component-state-sentinel.mjs +0 -35
- package/scripts/test-component-state-source-contract.mjs +0 -83
- package/scripts/test-consumer-conformance-sentinel.mjs +0 -165
- package/scripts/test-consumer-reference-sentinel.mjs +0 -31
- package/scripts/test-generate-consumer-reference-evidence.mjs +0 -124
- package/scripts/test-json-cli-output.mjs +0 -151
- package/scripts/test-json-schema-formats.mjs +0 -40
- package/scripts/test-reference-adapters.mjs +0 -199
- package/scripts/test-renderer-purity.mjs +0 -34
- package/scripts/test-sg-cli.mjs +0 -129
- package/scripts/test-summarize-sentinel-calibration.mjs +0 -226
- package/scripts/test-validate-baseline-manifest.mjs +0 -234
- package/scripts/test-validate-component-state-artifacts.mjs +0 -243
- package/scripts/test-validate-component-state.mjs +0 -106
- package/scripts/test-validate-consumer-conformance.mjs +0 -427
- package/scripts/test-validate-consumer-reference-cli.mjs +0 -69
- package/scripts/test-validate-consumer-reference.mjs +0 -263
- package/scripts/test-validate-domains.mjs +0 -357
- package/scripts/test-validate-governance.mjs +0 -292
- package/scripts/test-validate-ia.mjs +0 -262
- package/scripts/test-validate-okf.mjs +0 -73
- package/scripts/test-validate-page-evidence.mjs +0 -302
- package/scripts/test-validate-patterns.mjs +0 -157
- package/scripts/test-validate-promotion-rfc.mjs +0 -250
- package/scripts/test-validate-reference-profiles.mjs +0 -170
- package/scripts/test-validate-unity-org-wiki.mjs +0 -57
- package/scripts/test-validate-unity-source-contracts.mjs +0 -67
- package/scripts/test-validate-vocabulary.mjs +0 -174
- package/scripts/test-validate-webpage-workflow.mjs +0 -293
- package/scripts/validate-baseline-manifest.mjs +0 -44
- package/scripts/validate-catalog.mjs +0 -65
- package/scripts/validate-component-state.mjs +0 -141
- package/scripts/validate-consumer-conformance.mjs +0 -477
- package/scripts/validate-consumer-reference.mjs +0 -288
- package/scripts/validate-domains.mjs +0 -237
- package/scripts/validate-governance.mjs +0 -248
- package/scripts/validate-ia.mjs +0 -136
- package/scripts/validate-links.mjs +0 -66
- package/scripts/validate-okf.mjs +0 -104
- package/scripts/validate-page-evidence.mjs +0 -191
- package/scripts/validate-patterns.mjs +0 -246
- package/scripts/validate-promotion-rfc.mjs +0 -224
- package/scripts/validate-reference-artifacts.mjs +0 -125
- package/scripts/validate-renderer-purity.mjs +0 -56
- package/scripts/validate-unity-org-wiki.mjs +0 -146
- package/scripts/validate-unity-source-contracts.mjs +0 -107
- package/scripts/validate-vocabulary.mjs +0 -115
- package/scripts/validate-webpage-workflow.mjs +0 -254
- package/scripts/visual-expectation-contract.mjs +0 -20
- package/scripts/workflow-action-contract.mjs +0 -163
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Cross-surface conformance test.
|
|
5
|
-
*
|
|
6
|
-
* A CLI JSON-RPC-ish envelope and an MCP envelope are transport projections;
|
|
7
|
-
* this harness removes only those envelopes and compares the canonical domain
|
|
8
|
-
* payload (or the stable failure codes). It therefore catches an adapter
|
|
9
|
-
* that returns a plausible wrapper while silently changing domain semantics.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { spawnSync } from "node:child_process";
|
|
13
|
-
import path from "node:path";
|
|
14
|
-
import { fileURLToPath } from "node:url";
|
|
15
|
-
|
|
16
|
-
const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
17
|
-
const cliPath = path.join(repositoryRoot, "scripts", "sg.mjs");
|
|
18
|
-
const profileRef = "sg:profile/editorial-reference-profile";
|
|
19
|
-
|
|
20
|
-
function stable(value) {
|
|
21
|
-
if (Array.isArray(value)) return value.map(stable);
|
|
22
|
-
if (value && typeof value === "object") {
|
|
23
|
-
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stable(value[key])]));
|
|
24
|
-
}
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function equal(left, right) {
|
|
29
|
-
return JSON.stringify(stable(left)) === JSON.stringify(stable(right));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function parseJson(text) {
|
|
33
|
-
if (typeof text !== "string" || text.length === 0) return null;
|
|
34
|
-
try { return JSON.parse(text); } catch { return null; }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function codes(envelope) {
|
|
38
|
-
return Array.isArray(envelope?.failures)
|
|
39
|
-
? envelope.failures.map((failure) => failure?.code).filter((code) => typeof code === "string").sort()
|
|
40
|
-
: [];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function unwrap(value, operation) {
|
|
44
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
45
|
-
if (typeof value.ok === "boolean") {
|
|
46
|
-
if (value.ok === true) return { ok: true, operation: value.operation ?? operation, result: value.result ?? null };
|
|
47
|
-
return { ok: false, operation: value.operation ?? operation, failures: codes(value) };
|
|
48
|
-
}
|
|
49
|
-
if (value.result && typeof value.result === "object" && typeof value.result.ok === "boolean") {
|
|
50
|
-
return unwrap(value.result, operation);
|
|
51
|
-
}
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function cliInvocation(args) {
|
|
56
|
-
const child = spawnSync(process.execPath, [cliPath, ...args, "--format", "json"], {
|
|
57
|
-
cwd: repositoryRoot,
|
|
58
|
-
encoding: "utf8",
|
|
59
|
-
});
|
|
60
|
-
const parsed = parseJson(child.stdout);
|
|
61
|
-
return {
|
|
62
|
-
child,
|
|
63
|
-
envelope: unwrap(parsed, args[0]),
|
|
64
|
-
parsed,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function mcpEnvelope(response, operation) {
|
|
69
|
-
const structured = response?.structuredContent;
|
|
70
|
-
const text = response?.content?.find((item) => item?.type === "text")?.text;
|
|
71
|
-
const parsed = structured && typeof structured === "object" ? structured : parseJson(text);
|
|
72
|
-
return unwrap(parsed, operation);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function result(name, expected, actual, ok) {
|
|
76
|
-
return { actual, expected, name, ok };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function compare(name, cliRun, mcpRun) {
|
|
80
|
-
const cliEnvelope = cliRun.envelope;
|
|
81
|
-
const mcpEnvelopeValue = mcpRun.envelope;
|
|
82
|
-
if (!cliEnvelope || !mcpEnvelopeValue) {
|
|
83
|
-
return result(
|
|
84
|
-
name,
|
|
85
|
-
"both adapters produce a parseable {ok,operation,result|failures} envelope",
|
|
86
|
-
{
|
|
87
|
-
cli: { status: cliRun.child.status, stderr: cliRun.child.stderr, envelope: cliEnvelope, stdout: cliRun.child.stdout },
|
|
88
|
-
mcp: { response: mcpRun.response, envelope: mcpEnvelopeValue },
|
|
89
|
-
},
|
|
90
|
-
false,
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
if (cliEnvelope.ok !== mcpEnvelopeValue.ok) {
|
|
94
|
-
return result(
|
|
95
|
-
name,
|
|
96
|
-
"CLI and MCP agree on success versus failure",
|
|
97
|
-
{ cli: cliEnvelope, mcp: mcpEnvelopeValue },
|
|
98
|
-
false,
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
if (cliEnvelope.ok === false) {
|
|
102
|
-
const cliCodes = cliEnvelope.failures;
|
|
103
|
-
const mcpCodes = mcpEnvelopeValue.failures;
|
|
104
|
-
return result(
|
|
105
|
-
name,
|
|
106
|
-
"CLI and MCP expose identical stable error codes",
|
|
107
|
-
{ cliCodes, mcpCodes, cliStatus: cliRun.child.status, mcpResponse: mcpRun.response },
|
|
108
|
-
cliRun.child.status !== 0 && cliRun.child.stderr.length === 0 && equal(cliCodes, mcpCodes),
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
return result(
|
|
112
|
-
name,
|
|
113
|
-
"CLI and MCP expose identical operation and canonical domain result",
|
|
114
|
-
{ cli: cliEnvelope, mcp: mcpEnvelopeValue },
|
|
115
|
-
cliRun.child.status === 0
|
|
116
|
-
&& cliRun.child.stderr.length === 0
|
|
117
|
-
&& cliEnvelope.operation === mcpEnvelopeValue.operation
|
|
118
|
-
&& equal(cliEnvelope.result, mcpEnvelopeValue.result),
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async function loadSdk(results) {
|
|
123
|
-
try {
|
|
124
|
-
const sdk = {
|
|
125
|
-
...(await import("@modelcontextprotocol/sdk/server/mcp.js")),
|
|
126
|
-
...(await import("@modelcontextprotocol/sdk/client/index.js")),
|
|
127
|
-
...(await import("@modelcontextprotocol/sdk/inMemory.js")),
|
|
128
|
-
};
|
|
129
|
-
const available = typeof sdk.McpServer === "function"
|
|
130
|
-
&& typeof sdk.Client === "function"
|
|
131
|
-
&& typeof sdk.InMemoryTransport?.createLinkedPair === "function";
|
|
132
|
-
results.push(result(
|
|
133
|
-
"conformance_sdk_available",
|
|
134
|
-
"official stable MCP SDK is available",
|
|
135
|
-
{ available },
|
|
136
|
-
available,
|
|
137
|
-
));
|
|
138
|
-
return available ? sdk : null;
|
|
139
|
-
} catch (error) {
|
|
140
|
-
results.push(result(
|
|
141
|
-
"conformance_sdk_available",
|
|
142
|
-
"official stable MCP SDK is available",
|
|
143
|
-
{ code: "mcp_sdk_unavailable", error: error instanceof Error ? error.message : String(error) },
|
|
144
|
-
false,
|
|
145
|
-
));
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async function loadAdapter(results) {
|
|
151
|
-
try {
|
|
152
|
-
const adapter = await import("./agent-native/mcp-adapter.mjs");
|
|
153
|
-
const factory = adapter.createStyleGalleryMcpServer ?? adapter.createMcpServer;
|
|
154
|
-
results.push(result(
|
|
155
|
-
"conformance_adapter_available",
|
|
156
|
-
"mcp-adapter exports createStyleGalleryMcpServer",
|
|
157
|
-
{ exports: Object.keys(adapter).sort() },
|
|
158
|
-
typeof factory === "function",
|
|
159
|
-
));
|
|
160
|
-
return factory;
|
|
161
|
-
} catch (error) {
|
|
162
|
-
results.push(result(
|
|
163
|
-
"conformance_adapter_available",
|
|
164
|
-
"mcp-adapter exports createStyleGalleryMcpServer",
|
|
165
|
-
{ code: "mcp_adapter_unavailable", error: error instanceof Error ? error.message : String(error) },
|
|
166
|
-
false,
|
|
167
|
-
));
|
|
168
|
-
return null;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
async function main() {
|
|
173
|
-
const results = [];
|
|
174
|
-
const sdk = await loadSdk(results);
|
|
175
|
-
const createServer = await loadAdapter(results);
|
|
176
|
-
if (!sdk || !createServer) {
|
|
177
|
-
const report = { ok: false, results };
|
|
178
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
179
|
-
process.exitCode = 1;
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const server = await createServer();
|
|
184
|
-
const [clientTransport, serverTransport] = sdk.InMemoryTransport.createLinkedPair();
|
|
185
|
-
const client = new sdk.Client({ name: "stylegallery-adapter-conformance", version: "1.0.0" });
|
|
186
|
-
try {
|
|
187
|
-
await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
|
|
188
|
-
const cases = [
|
|
189
|
-
{ name: "discover", cli: ["discover"], mcp: { name: "discover", arguments: {} } },
|
|
190
|
-
{ name: "ops", cli: ["ops"], mcp: { name: "ops", arguments: {} } },
|
|
191
|
-
{ name: "resolve", cli: ["resolve", profileRef], mcp: { name: "resolve", arguments: { stable_ref: profileRef } } },
|
|
192
|
-
{ name: "claims", cli: ["claims", profileRef], mcp: { name: "claims", arguments: { stable_ref: profileRef } } },
|
|
193
|
-
{ name: "context", cli: ["context", profileRef], mcp: { name: "context", arguments: { stable_ref: profileRef } } },
|
|
194
|
-
{ name: "resolve_malformed", cli: ["resolve", "not-a-stable-ref"], mcp: { name: "resolve", arguments: { stable_ref: "not-a-stable-ref" } } },
|
|
195
|
-
];
|
|
196
|
-
for (const testCase of cases) {
|
|
197
|
-
const cliRun = cliInvocation(testCase.cli);
|
|
198
|
-
let response;
|
|
199
|
-
let mcpError = null;
|
|
200
|
-
try {
|
|
201
|
-
response = await client.callTool(testCase.mcp);
|
|
202
|
-
} catch (error) {
|
|
203
|
-
mcpError = error;
|
|
204
|
-
}
|
|
205
|
-
const mcpRun = {
|
|
206
|
-
envelope: mcpError ? null : mcpEnvelope(response, testCase.name.split("_")[0]),
|
|
207
|
-
response: mcpError ? { error: mcpError instanceof Error ? mcpError.message : String(mcpError) } : response,
|
|
208
|
-
};
|
|
209
|
-
if (mcpError && cliRun.envelope?.ok === false) {
|
|
210
|
-
results.push(result(
|
|
211
|
-
`adapter_equivalence_${testCase.name}`,
|
|
212
|
-
"both adapters preserve the same stable failure code",
|
|
213
|
-
{ cli: cliRun.envelope, mcpError: mcpRun.response },
|
|
214
|
-
false,
|
|
215
|
-
));
|
|
216
|
-
} else {
|
|
217
|
-
results.push(compare(`adapter_equivalence_${testCase.name}`, cliRun, mcpRun));
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
} catch (error) {
|
|
221
|
-
results.push(result(
|
|
222
|
-
"adapter_conformance_round_trip",
|
|
223
|
-
"CLI and MCP conformance fixture executes over an initialized in-memory transport",
|
|
224
|
-
{ code: "conformance_round_trip_failed", error: error instanceof Error ? error.message : String(error) },
|
|
225
|
-
false,
|
|
226
|
-
));
|
|
227
|
-
} finally {
|
|
228
|
-
await client.close().catch(() => {});
|
|
229
|
-
const closed = server.close?.();
|
|
230
|
-
if (closed && typeof closed.catch === "function") await closed.catch(() => {});
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const report = { ok: results.every((item) => item.ok), results };
|
|
234
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
235
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
await main().catch((error) => {
|
|
239
|
-
const report = {
|
|
240
|
-
ok: false,
|
|
241
|
-
results: [result(
|
|
242
|
-
"conformance_harness_runtime",
|
|
243
|
-
"harness emits structured JSON instead of crashing",
|
|
244
|
-
{ code: "conformance_harness_runtime", error: error instanceof Error ? error.message : String(error) },
|
|
245
|
-
false,
|
|
246
|
-
)],
|
|
247
|
-
};
|
|
248
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
249
|
-
process.exitCode = 1;
|
|
250
|
-
});
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { spawnSync } from "node:child_process";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { agentNativeFixture } from "./agent-native/fixture.mjs";
|
|
7
|
-
import { createVersionId } from "./agent-native/identity.mjs";
|
|
8
|
-
import { createSelfDescription } from "./agent-native/self-description.mjs";
|
|
9
|
-
|
|
10
|
-
const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
-
const operations = agentNativeFixture.records.filter((record) => record.record_kind === "operation");
|
|
12
|
-
|
|
13
|
-
function check(name, expected, actual, ok) {
|
|
14
|
-
return { actual, expected, name, ok };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function selfDescriptionFor(records) {
|
|
18
|
-
return createSelfDescription({
|
|
19
|
-
fixture: {
|
|
20
|
-
fixture_ref: agentNativeFixture.fixture_ref,
|
|
21
|
-
manifest: agentNativeFixture.manifest,
|
|
22
|
-
records,
|
|
23
|
-
},
|
|
24
|
-
operations,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function tamperedRecords(mutator) {
|
|
29
|
-
const records = structuredClone(agentNativeFixture.records);
|
|
30
|
-
mutator(records);
|
|
31
|
-
return records;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function expectedFailure(name, code, mutator) {
|
|
35
|
-
try {
|
|
36
|
-
selfDescriptionFor(tamperedRecords(mutator));
|
|
37
|
-
return check(name, code, { code: "no_failure" }, false);
|
|
38
|
-
} catch (error) {
|
|
39
|
-
return check(name, code, { code: error?.code ?? "unknown", message: error?.message }, error?.code === code);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function runDiscover() {
|
|
44
|
-
const child = spawnSync(process.execPath, [path.join(repositoryRoot, "scripts", "sg.mjs"), "discover", "--format", "json"], {
|
|
45
|
-
cwd: repositoryRoot,
|
|
46
|
-
encoding: "utf8",
|
|
47
|
-
});
|
|
48
|
-
let report;
|
|
49
|
-
try { report = JSON.parse(child.stdout); } catch { report = null; }
|
|
50
|
-
const claims = report?.result?.conformance?.claims ?? [];
|
|
51
|
-
const receipt = claims[0]?.execution_receipts?.[0];
|
|
52
|
-
return check(
|
|
53
|
-
"discover_exposes_verified_execution_receipt",
|
|
54
|
-
"discover is successful only with fixture_verified status and a bound PASS receipt",
|
|
55
|
-
{
|
|
56
|
-
status: child.status,
|
|
57
|
-
stderr: child.stderr,
|
|
58
|
-
conformance_status: report?.result?.conformance?.status,
|
|
59
|
-
receipt_ref: receipt?.receipt?.stable_ref,
|
|
60
|
-
fixture_version_id: receipt?.receipt?.fixture_version_id,
|
|
61
|
-
verifier_status: receipt?.receipt?.verification?.status,
|
|
62
|
-
},
|
|
63
|
-
child.status === 0
|
|
64
|
-
&& child.signal === null
|
|
65
|
-
&& child.stderr === ""
|
|
66
|
-
&& report?.ok === true
|
|
67
|
-
&& report?.result?.conformance?.status === "fixture_verified"
|
|
68
|
-
&& receipt?.receipt?.record_kind === "execution_receipt"
|
|
69
|
-
&& receipt?.receipt?.verification?.status === "PASS"
|
|
70
|
-
&& receipt?.receipt?.fixture_version_id === receipt?.source?.version_id,
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const results = [
|
|
75
|
-
check(
|
|
76
|
-
"default_fixture_receipt_verifies",
|
|
77
|
-
"the immutable fixture has one content-bound execution receipt",
|
|
78
|
-
{
|
|
79
|
-
status: createSelfDescription({ fixture: agentNativeFixture, operations }).conformance.status,
|
|
80
|
-
receipts: agentNativeFixture.records.filter((record) => record.record_kind === "execution_receipt").length,
|
|
81
|
-
},
|
|
82
|
-
agentNativeFixture.records.filter((record) => record.record_kind === "execution_receipt").length === 1,
|
|
83
|
-
),
|
|
84
|
-
expectedFailure("missing_receipt_cannot_claim_fixture_verified", "self_description_execution_receipt_missing", (records) => {
|
|
85
|
-
const index = records.findIndex((record) => record.record_kind === "execution_receipt");
|
|
86
|
-
records.splice(index, 1);
|
|
87
|
-
}),
|
|
88
|
-
expectedFailure("wrong_fixture_version_is_rejected", "self_description_receipt_version_mismatch", (records) => {
|
|
89
|
-
records.find((record) => record.record_kind === "execution_receipt").fixture_version_id = "sg:artifact/sg-cli-conformance-test@sha256:0000000000000000000000000000000000000000000000000000000000000000";
|
|
90
|
-
}),
|
|
91
|
-
expectedFailure("tampered_result_digest_is_rejected", "self_description_receipt_result_digest_mismatch", (records) => {
|
|
92
|
-
records.find((record) => record.record_kind === "execution_receipt").result_sha256 = "sha256:0000000000000000000000000000000000000000000000000000000000000000";
|
|
93
|
-
}),
|
|
94
|
-
expectedFailure("unverified_receipt_is_rejected", "self_description_receipt_unverified", (records) => {
|
|
95
|
-
const receipt = records.find((record) => record.record_kind === "execution_receipt");
|
|
96
|
-
receipt.verification.status = "PASS_WITH_WARNINGS";
|
|
97
|
-
const payload = { ...receipt };
|
|
98
|
-
delete payload.version_id;
|
|
99
|
-
receipt.version_id = createVersionId({ stableRef: receipt.stable_ref, payload });
|
|
100
|
-
}),
|
|
101
|
-
runDiscover(),
|
|
102
|
-
];
|
|
103
|
-
|
|
104
|
-
const report = { ok: results.every((result) => result.ok), results };
|
|
105
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
106
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { appendEvent, eventHeads } from "./agent-native/events.mjs";
|
|
4
|
-
|
|
5
|
-
const cases = [];
|
|
6
|
-
|
|
7
|
-
function test(name, scenario) {
|
|
8
|
-
try {
|
|
9
|
-
scenario();
|
|
10
|
-
cases.push({ name, ok: true });
|
|
11
|
-
} catch (error) {
|
|
12
|
-
cases.push({
|
|
13
|
-
error: error instanceof Error ? error.message : String(error),
|
|
14
|
-
name,
|
|
15
|
-
ok: false,
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function equal(actual, expected, label) {
|
|
21
|
-
if (actual !== expected) throw new Error(`${label}: expected ${expected}, received ${actual}`);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function rejectsCycle(events, event) {
|
|
25
|
-
try {
|
|
26
|
-
appendEvent({ event, events });
|
|
27
|
-
} catch (error) {
|
|
28
|
-
if (error instanceof TypeError && error.message.includes("cycle")) return;
|
|
29
|
-
throw error;
|
|
30
|
-
}
|
|
31
|
-
throw new Error("expected appendEvent to reject a causal cycle");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
test("append_rejects_two_node_cycle_completed_by_new_event", () => {
|
|
35
|
-
// Given A references a parent B that is not present yet.
|
|
36
|
-
const events = [{ event_id: "sg:event/a", parents: ["sg:event/b"], type: "a" }];
|
|
37
|
-
// When B is appended with A as its parent.
|
|
38
|
-
// Then combined-graph validation rejects the newly completed cycle.
|
|
39
|
-
rejectsCycle(events, { event_id: "sg:event/b", parents: ["sg:event/a"], type: "b" });
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("append_rejects_long_cycle_completed_by_new_event", () => {
|
|
43
|
-
// Given A -> B -> C with C unresolved.
|
|
44
|
-
const events = [
|
|
45
|
-
{ event_id: "sg:event/a", parents: ["sg:event/b"], type: "a" },
|
|
46
|
-
{ event_id: "sg:event/b", parents: ["sg:event/c"], type: "b" },
|
|
47
|
-
];
|
|
48
|
-
// When C is appended pointing back to A.
|
|
49
|
-
// Then combined-graph validation rejects the three-node cycle.
|
|
50
|
-
rejectsCycle(events, { event_id: "sg:event/c", parents: ["sg:event/a"], type: "c" });
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test("append_allows_unresolved_parent_to_close_acyclically", () => {
|
|
54
|
-
// Given a child references a future parent.
|
|
55
|
-
const events = [{ event_id: "sg:event/child", parents: ["sg:event/parent"], type: "child" }];
|
|
56
|
-
// When the future parent is appended as a root.
|
|
57
|
-
const combined = appendEvent({
|
|
58
|
-
event: { event_id: "sg:event/parent", parents: [], type: "parent" },
|
|
59
|
-
events,
|
|
60
|
-
});
|
|
61
|
-
// Then both immutable events remain and the child is the sole head.
|
|
62
|
-
equal(combined.length, 2, "event count");
|
|
63
|
-
equal(eventHeads({ events: combined }).join(","), "sg:event/child", "heads");
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test("append_of_identical_event_is_idempotent", () => {
|
|
67
|
-
// Given one immutable event already exists.
|
|
68
|
-
const event = { event_id: "sg:event/root", parents: [], type: "root" };
|
|
69
|
-
// When the same canonical event is appended again.
|
|
70
|
-
const combined = appendEvent({ event, events: [event] });
|
|
71
|
-
// Then no duplicate is created.
|
|
72
|
-
equal(combined.length, 1, "event count");
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const report = {
|
|
76
|
-
contract: "agent-native-causal-events",
|
|
77
|
-
ok: cases.every((item) => item.ok),
|
|
78
|
-
results: cases,
|
|
79
|
-
};
|
|
80
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
81
|
-
process.exitCode = report.ok ? 0 : 1;
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
callExport,
|
|
3
|
-
failFromCall,
|
|
4
|
-
hasAnyText,
|
|
5
|
-
isObject,
|
|
6
|
-
payload,
|
|
7
|
-
pick,
|
|
8
|
-
result,
|
|
9
|
-
} from "./test-agent-execution-fixtures.mjs";
|
|
10
|
-
|
|
11
|
-
export async function exerciseExecutionEffects(modules, state) {
|
|
12
|
-
const rows = [];
|
|
13
|
-
const effectCall = await callExport(modules.execution, "execution", "recordEffectAttempt", {
|
|
14
|
-
attempt: "external-call",
|
|
15
|
-
connector: "fixture-connector",
|
|
16
|
-
connectorReceipt: null,
|
|
17
|
-
effect: "sg:effect/execution-fixture",
|
|
18
|
-
effectClass: "EXTERNAL",
|
|
19
|
-
effectId: "sg:effect/execution-fixture",
|
|
20
|
-
idempotencyKey: "idem:execution-fixture",
|
|
21
|
-
operation: state.operation,
|
|
22
|
-
run: state.run,
|
|
23
|
-
state: "UNCERTAIN",
|
|
24
|
-
task: state.task,
|
|
25
|
-
});
|
|
26
|
-
const uncertain = effectCall.ok ? payload(effectCall.value) : null;
|
|
27
|
-
rows.push(effectCall.ok
|
|
28
|
-
? result(
|
|
29
|
-
"external_effect_without_receipt_is_uncertain",
|
|
30
|
-
"an external attempt without durable connector receipt is UNCERTAIN",
|
|
31
|
-
uncertain,
|
|
32
|
-
isObject(uncertain) && hasAnyText(uncertain, ["state", "status", "effectState", "effect_state"], ["UNCERTAIN", "uncertain"]),
|
|
33
|
-
)
|
|
34
|
-
: failFromCall("external_effect_without_receipt_is_uncertain", "an external attempt without durable connector receipt is UNCERTAIN", effectCall));
|
|
35
|
-
|
|
36
|
-
const recoveredCall = await callExport(modules.execution, "execution", "reconcileEffect", {
|
|
37
|
-
effect: uncertain,
|
|
38
|
-
observation: { connectorReceipt: "sg:connector-receipt/recovered", status: "COMMITTED" },
|
|
39
|
-
observations: [{ connectorReceipt: "sg:connector-receipt/recovered", status: "COMMITTED" }],
|
|
40
|
-
strategy: "reconcile",
|
|
41
|
-
});
|
|
42
|
-
const recovered = recoveredCall.ok ? payload(recoveredCall.value) : null;
|
|
43
|
-
rows.push(recoveredCall.ok
|
|
44
|
-
? result(
|
|
45
|
-
"uncertain_effect_reconciles_from_positive_observation",
|
|
46
|
-
"positive connector observation yields COMMITTED and preserves receipt",
|
|
47
|
-
recovered,
|
|
48
|
-
isObject(recovered)
|
|
49
|
-
&& hasAnyText(recovered, ["state", "status", "effectState", "effect_state"], ["COMMITTED", "committed"])
|
|
50
|
-
&& typeof pick(recovered, ["connectorReceipt", "connector_receipt", "receiptId", "receipt_id"]) === "string",
|
|
51
|
-
)
|
|
52
|
-
: failFromCall("uncertain_effect_reconciles_from_positive_observation", "positive connector observation yields COMMITTED and preserves receipt", recoveredCall));
|
|
53
|
-
|
|
54
|
-
const compensatedCall = await callExport(modules.execution, "execution", "reconcileEffect", {
|
|
55
|
-
effect: uncertain,
|
|
56
|
-
observation: { status: "ABSENT" },
|
|
57
|
-
observations: [{ status: "ABSENT" }],
|
|
58
|
-
strategy: "compensate",
|
|
59
|
-
});
|
|
60
|
-
const compensated = compensatedCall.ok ? payload(compensatedCall.value) : null;
|
|
61
|
-
rows.push(compensatedCall.ok
|
|
62
|
-
? result(
|
|
63
|
-
"uncertain_effect_can_be_compensated",
|
|
64
|
-
"negative connector observation with explicit compensation yields COMPENSATED",
|
|
65
|
-
compensated,
|
|
66
|
-
isObject(compensated) && hasAnyText(compensated, ["state", "status", "effectState", "effect_state"], ["COMPENSATED", "compensated"]),
|
|
67
|
-
)
|
|
68
|
-
: failFromCall("uncertain_effect_can_be_compensated", "negative connector observation with explicit compensation yields COMPENSATED", compensatedCall));
|
|
69
|
-
|
|
70
|
-
const conflictCall = await callExport(modules.execution, "execution", "reconcileEffect", {
|
|
71
|
-
effect: uncertain,
|
|
72
|
-
observation: { status: "COMMITTED" },
|
|
73
|
-
observations: [{ status: "COMMITTED" }, { status: "ABSENT" }],
|
|
74
|
-
strategy: "reconcile",
|
|
75
|
-
});
|
|
76
|
-
const conflict = conflictCall.ok ? payload(conflictCall.value) : null;
|
|
77
|
-
rows.push(conflictCall.ok
|
|
78
|
-
? result(
|
|
79
|
-
"conflicting_reconciliation_stays_uncertain",
|
|
80
|
-
"conflicting observations never silently commit or compensate",
|
|
81
|
-
conflict,
|
|
82
|
-
isObject(conflict) && hasAnyText(conflict, ["state", "status", "effectState", "effect_state"], ["UNCERTAIN", "uncertain"]),
|
|
83
|
-
)
|
|
84
|
-
: failFromCall("conflicting_reconciliation_stays_uncertain", "conflicting observations never silently commit or compensate", conflictCall));
|
|
85
|
-
|
|
86
|
-
const receiptCall = await callExport(modules.execution, "execution", "createReceipt", {
|
|
87
|
-
causalParents: ["sg:event/effect-reconciled"],
|
|
88
|
-
effect: recovered,
|
|
89
|
-
effects: [recovered],
|
|
90
|
-
input: { stableRef: "sg:profile/editorial-reference-profile" },
|
|
91
|
-
operation: state.operation,
|
|
92
|
-
output: { stableRef: "sg:profile/editorial-reference-profile", resolved: true },
|
|
93
|
-
policyDecision: pick(state.authorized, ["decision", "policyDecision", "policy_decision"]) ?? state.authorized,
|
|
94
|
-
run: state.run,
|
|
95
|
-
task: state.task,
|
|
96
|
-
});
|
|
97
|
-
const receipt = receiptCall.ok ? payload(receiptCall.value) : null;
|
|
98
|
-
rows.push(receiptCall.ok
|
|
99
|
-
? result(
|
|
100
|
-
"invocation_receipt_binds_operation_task_run_and_effect",
|
|
101
|
-
"receipt records operation, task/run IDs, normalized input/output digests, policy, effects, and causal parents",
|
|
102
|
-
receipt,
|
|
103
|
-
isObject(receipt)
|
|
104
|
-
&& typeof pick(receipt, ["inputDigest", "input_digest", "normalizedInputDigest", "normalized_input_digest"]) === "string"
|
|
105
|
-
&& typeof pick(receipt, ["outputDigest", "output_digest", "normalizedOutputDigest", "normalized_output_digest"]) === "string"
|
|
106
|
-
&& typeof pick(receipt, ["taskId", "task_id"]) === "string"
|
|
107
|
-
&& typeof pick(receipt, ["runId", "run_id"]) === "string"
|
|
108
|
-
&& Array.isArray(pick(receipt, ["effects", "effectIds", "effect_ids"]))
|
|
109
|
-
&& Array.isArray(pick(receipt, ["causalParents", "causal_parents", "parents"])),
|
|
110
|
-
)
|
|
111
|
-
: failFromCall("invocation_receipt_binds_operation_task_run_and_effect", "receipt records operation, task/run IDs, normalized input/output digests, policy, effects, and causal parents", receiptCall));
|
|
112
|
-
|
|
113
|
-
return { rows, uncertain, recovered, receipt };
|
|
114
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
|
-
|
|
4
|
-
const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
5
|
-
export const modulePaths = {
|
|
6
|
-
execution: path.join(repositoryRoot, "scripts", "agent-native", "execution.mjs"),
|
|
7
|
-
events: path.join(repositoryRoot, "scripts", "agent-native", "events.mjs"),
|
|
8
|
-
retrieval: path.join(repositoryRoot, "scripts", "agent-native", "retrieval.mjs"),
|
|
9
|
-
learning: path.join(repositoryRoot, "scripts", "agent-native", "learning.mjs"),
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const fixedNow = "2026-01-02T03:04:05.000Z";
|
|
13
|
-
export const fixedExpiry = "2030-01-01T00:00:00.000Z";
|
|
14
|
-
|
|
15
|
-
function sorted(value) {
|
|
16
|
-
if (Array.isArray(value)) return value.map(sorted);
|
|
17
|
-
if (!value || typeof value !== "object") return value;
|
|
18
|
-
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sorted(value[key])]));
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function bytes(value) {
|
|
22
|
-
return JSON.stringify(sorted(value));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function pick(value, keys) {
|
|
26
|
-
if (!value || typeof value !== "object") return undefined;
|
|
27
|
-
for (const key of keys) {
|
|
28
|
-
if (Object.prototype.hasOwnProperty.call(value, key) && value[key] !== undefined) return value[key];
|
|
29
|
-
}
|
|
30
|
-
return undefined;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function hasText(value, keys, expected) {
|
|
34
|
-
const actual = pick(value, keys);
|
|
35
|
-
return typeof actual === "string" && actual === expected;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function hasAnyText(value, keys, expectedValues) {
|
|
39
|
-
const actual = pick(value, keys);
|
|
40
|
-
return expectedValues.includes(actual);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function isObject(value) {
|
|
44
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function payload(value) {
|
|
48
|
-
if (isObject(value) && value.ok === true && Object.prototype.hasOwnProperty.call(value, "result")) {
|
|
49
|
-
return value.result;
|
|
50
|
-
}
|
|
51
|
-
return value;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export async function loadKernelModule(name) {
|
|
55
|
-
try {
|
|
56
|
-
const module = await import(pathToFileURL(modulePaths[name]).href);
|
|
57
|
-
return { ok: true, module };
|
|
58
|
-
} catch (error) {
|
|
59
|
-
return {
|
|
60
|
-
ok: false,
|
|
61
|
-
error: {
|
|
62
|
-
code: "kernel_unavailable",
|
|
63
|
-
module: name,
|
|
64
|
-
message: error instanceof Error ? error.message : String(error),
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export async function callExport(loaded, moduleName, exportName, input) {
|
|
71
|
-
if (!loaded?.ok) return { ok: false, error: loaded?.error ?? { code: "kernel_unavailable", module: moduleName } };
|
|
72
|
-
const fn = loaded.module?.[exportName];
|
|
73
|
-
if (typeof fn !== "function") {
|
|
74
|
-
return {
|
|
75
|
-
ok: false,
|
|
76
|
-
error: { code: "kernel_unavailable", module: moduleName, export: exportName, message: "missing export" },
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
return { ok: true, value: await fn(input) };
|
|
81
|
-
} catch (error) {
|
|
82
|
-
return {
|
|
83
|
-
ok: false,
|
|
84
|
-
error: { code: "contract_error", module: moduleName, export: exportName, message: error instanceof Error ? error.message : String(error) },
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function result(name, expected, actual, ok, details = undefined) {
|
|
90
|
-
const record = { actual, expected, name, ok };
|
|
91
|
-
if (details !== undefined) record.details = details;
|
|
92
|
-
return record;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function failFromCall(name, expected, call) {
|
|
96
|
-
return result(name, expected, call.error, false);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function idOf(value, fallback = undefined) {
|
|
100
|
-
return pick(value, ["versionId", "version_id", "stableRef", "stable_ref", "taskId", "task_id", "runId", "run_id", "effectId", "effect_id", "id"]) ?? fallback;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function stateOf(value) {
|
|
104
|
-
return pick(value, ["state", "status", "effectState", "effect_state", "disposition"]);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function operationInput() {
|
|
108
|
-
return {
|
|
109
|
-
adapters: ["cli", "mcp"],
|
|
110
|
-
effect: "NONE",
|
|
111
|
-
effectClass: "NONE",
|
|
112
|
-
idempotent: true,
|
|
113
|
-
inputSchema: {
|
|
114
|
-
additionalProperties: false,
|
|
115
|
-
properties: { stableRef: { type: "string" } },
|
|
116
|
-
required: ["stableRef"],
|
|
117
|
-
type: "object",
|
|
118
|
-
},
|
|
119
|
-
name: "resolve",
|
|
120
|
-
operation: "resolve",
|
|
121
|
-
outputSchema: { type: "object" },
|
|
122
|
-
requiredCapability: "wiki.read",
|
|
123
|
-
stableRef: "sg:operation/resolve",
|
|
124
|
-
version: "v1",
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function grantInput() {
|
|
129
|
-
return {
|
|
130
|
-
capability: "wiki.read",
|
|
131
|
-
expiresAt: fixedExpiry,
|
|
132
|
-
limits: { calls: 3, maxCalls: 3 },
|
|
133
|
-
operation: "resolve",
|
|
134
|
-
operations: ["resolve", "sg:operation/resolve"],
|
|
135
|
-
resourceScope: ["sg:profile/*", "sg:claim/*"],
|
|
136
|
-
resources: ["sg:profile/*", "sg:claim/*"],
|
|
137
|
-
stableRef: "sg:capability/wiki-read",
|
|
138
|
-
subject: "agent:test",
|
|
139
|
-
};
|
|
140
|
-
}
|