stylegallery 0.1.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.
Files changed (346) hide show
  1. package/AGENTS.md +156 -0
  2. package/CATALOG.md +69 -0
  3. package/DOMAINS.md +65 -0
  4. package/GOVERNANCE.md +222 -0
  5. package/GUIDE.md +59 -0
  6. package/README.md +313 -0
  7. package/consumer-reference/adapters/style-dictionary.config.mjs +36 -0
  8. package/consumer-reference/agent-native/README.md +157 -0
  9. package/consumer-reference/agent-native/registry.json +640 -0
  10. package/consumer-reference/agent-native/schema/agent-native.schema.json +848 -0
  11. package/consumer-reference/agent-native/schema/epistemic.schema.json +14 -0
  12. package/consumer-reference/agent-native/schema/execution.schema.json +12 -0
  13. package/consumer-reference/agent-native/schema/identity.schema.json +10 -0
  14. package/consumer-reference/agent-native/schema/learning.schema.json +12 -0
  15. package/consumer-reference/agent-native/schema/manifest.schema.json +6 -0
  16. package/consumer-reference/agent-native/schema/operation.schema.json +12 -0
  17. package/consumer-reference/agent-native/schema/protocol-binding.schema.json +9 -0
  18. package/consumer-reference/agent-native/schema/retrieval.schema.json +10 -0
  19. package/consumer-reference/baselines/calibration.json +260 -0
  20. package/consumer-reference/baselines/manifest.json +21 -0
  21. package/consumer-reference/contract.md +83 -0
  22. package/consumer-reference/fixtures/consumer-conformance/e2e-fixture.mjs +282 -0
  23. package/consumer-reference/fixtures/consumer-conformance/manifest.json +102 -0
  24. package/consumer-reference/fixtures/consumer-conformance/runtime-proof.mjs +32 -0
  25. package/consumer-reference/fixtures/consumer-conformance/valid-migration-result.json +18 -0
  26. package/consumer-reference/fixtures/consumer-conformance/valid-migration.json +142 -0
  27. package/consumer-reference/fixtures/invalid-stable-ended-support.json +19 -0
  28. package/consumer-reference/fixtures/promotion/invalid-blocking-evidence.json +26 -0
  29. package/consumer-reference/fixtures/promotion/invalid-count-only.json +29 -0
  30. package/consumer-reference/fixtures/promotion/invalid-missing-owner-migration.json +25 -0
  31. package/consumer-reference/fixtures/promotion/invalid-normative-bypass-no-regression.json +25 -0
  32. package/consumer-reference/fixtures/promotion/invalid-related-counted-independent.json +45 -0
  33. package/consumer-reference/fixtures/promotion/invalid-stable-ended-support.json +26 -0
  34. package/consumer-reference/fixtures/promotion/manifest.json +15 -0
  35. package/consumer-reference/fixtures/promotion/valid-deferred-example.json +67 -0
  36. package/consumer-reference/fixtures/promotion/valid-normative-bypass.json +67 -0
  37. package/consumer-reference/fixtures/token-portability/invalid-cycle.json +7 -0
  38. package/consumer-reference/fixtures/token-portability/invalid-dangling-alias.json +6 -0
  39. package/consumer-reference/fixtures/token-portability/invalid-extends.json +4 -0
  40. package/consumer-reference/fixtures/token-portability/invalid-json-pointer.json +7 -0
  41. package/consumer-reference/fixtures/token-portability/invalid-resolver.json +9 -0
  42. package/consumer-reference/fixtures/token-portability/invalid-type-mismatch.json +10 -0
  43. package/consumer-reference/fixtures/token-portability/invalid-unknown-reserved.json +6 -0
  44. package/consumer-reference/fixtures/token-portability/invalid-untested-type.json +6 -0
  45. package/consumer-reference/fixtures/token-portability/valid-border.json +14 -0
  46. package/consumer-reference/fixtures/token-portability/valid-reference.json +32 -0
  47. package/consumer-reference/fixtures/token-portability/valid-whole-alias.json +7 -0
  48. package/consumer-reference/fixtures/valid-deprecated.json +21 -0
  49. package/consumer-reference/fixtures/valid-experimental.json +19 -0
  50. package/consumer-reference/generated/manifest.json +40 -0
  51. package/consumer-reference/generated/tokens.css +12 -0
  52. package/consumer-reference/index.md +32 -0
  53. package/consumer-reference/policies/shared-experimental.json +37 -0
  54. package/consumer-reference/schema/ax-evidence.schema.json +30 -0
  55. package/consumer-reference/schema/baseline-manifest.schema.json +55 -0
  56. package/consumer-reference/schema/calibration-record.schema.json +190 -0
  57. package/consumer-reference/schema/capture-session.schema.json +161 -0
  58. package/consumer-reference/schema/component-state.schema.json +150 -0
  59. package/consumer-reference/schema/consumer-conformance-record.schema.json +365 -0
  60. package/consumer-reference/schema/dom-evidence.schema.json +38 -0
  61. package/consumer-reference/schema/evidence-record.schema.json +81 -0
  62. package/consumer-reference/schema/fixture-manifest.schema.json +32 -0
  63. package/consumer-reference/schema/item.schema.json +188 -0
  64. package/consumer-reference/schema/page-evidence-manifest.schema.json +216 -0
  65. package/consumer-reference/schema/page-evidence-session.schema.json +119 -0
  66. package/consumer-reference/schema/portable-tokens.schema.json +104 -0
  67. package/consumer-reference/schema/promotion-rfc.schema.json +219 -0
  68. package/consumer-reference/schema/runtime-evidence-manifest.schema.json +33 -0
  69. package/consumer-reference/schema/visual-evidence.schema.json +31 -0
  70. package/design-engineering/consumer-migration-readiness.md +124 -0
  71. package/design-engineering/index.md +28 -0
  72. package/design-engineering/interface-craft.md +107 -0
  73. package/design-engineering/reference-profiles/external-adaptation/index.md +12 -0
  74. package/design-engineering/reference-profiles/governed-local/editorial/components/button.component.json +125 -0
  75. package/design-engineering/reference-profiles/governed-local/editorial/evidence/button.evidence.json +3504 -0
  76. package/design-engineering/reference-profiles/governed-local/editorial/fixtures/button.fixture.json +65 -0
  77. package/design-engineering/reference-profiles/governed-local/editorial/generated/evidence-coverage.md +23 -0
  78. package/design-engineering/reference-profiles/governed-local/editorial/generated/keyboard-matrix.md +19 -0
  79. package/design-engineering/reference-profiles/governed-local/editorial/generated/state-matrix.md +21 -0
  80. package/design-engineering/reference-profiles/governed-local/editorial/local-foundations.json +12 -0
  81. package/design-engineering/reference-profiles/governed-local/editorial/profile.json +43 -0
  82. package/design-engineering/reference-profiles/governed-local/editorial/states/button.states.json +195 -0
  83. package/design-engineering/reference-profiles/governed-local/editorial/tokens.dtcg.json +17 -0
  84. package/design-engineering/reference-profiles/governed-local/index.md +26 -0
  85. package/design-engineering/reference-profiles/governed-local/terminal/components/button.component.json +125 -0
  86. package/design-engineering/reference-profiles/governed-local/terminal/evidence/button.evidence.json +3504 -0
  87. package/design-engineering/reference-profiles/governed-local/terminal/fixtures/button.fixture.json +65 -0
  88. package/design-engineering/reference-profiles/governed-local/terminal/generated/evidence-coverage.md +23 -0
  89. package/design-engineering/reference-profiles/governed-local/terminal/generated/keyboard-matrix.md +19 -0
  90. package/design-engineering/reference-profiles/governed-local/terminal/generated/state-matrix.md +21 -0
  91. package/design-engineering/reference-profiles/governed-local/terminal/local-foundations.json +12 -0
  92. package/design-engineering/reference-profiles/governed-local/terminal/profile.json +43 -0
  93. package/design-engineering/reference-profiles/governed-local/terminal/states/button.states.json +195 -0
  94. package/design-engineering/reference-profiles/governed-local/terminal/tokens.dtcg.json +17 -0
  95. package/design-engineering/reference-profiles/index.md +19 -0
  96. package/game-ui/classification.md +82 -0
  97. package/game-ui/index.md +35 -0
  98. package/game-ui/reference-record.md +62 -0
  99. package/game-ui/screen-hierarchy.md +107 -0
  100. package/game-ui/unity/architecture.md +166 -0
  101. package/game-ui/unity/cli-loop.md +84 -0
  102. package/game-ui/unity/data/unity-technologies-public-repositories.json +26654 -0
  103. package/game-ui/unity/org-wiki.md +146 -0
  104. package/game-ui/unity/repository-map.md +102 -0
  105. package/game-ui/unity/ui-systems.md +85 -0
  106. package/guides/decision-tree.md +149 -0
  107. package/guides/documentation-mode-taxonomy.md +157 -0
  108. package/guides/layout-brief.md +220 -0
  109. package/guides/vocabulary.md +148 -0
  110. package/guides/webpage-generation-workflow.md +185 -0
  111. package/index.md +36 -0
  112. package/layout/index.md +26 -0
  113. package/motion/index.md +24 -0
  114. package/motion/practice-reference.md +145 -0
  115. package/motion/review-workflow.md +86 -0
  116. package/motion/vocabulary.md +82 -0
  117. package/package.json +78 -0
  118. package/patterns/centering/center.md +87 -0
  119. package/patterns/centering/index.md +6 -0
  120. package/patterns/centering/super-center.md +89 -0
  121. package/patterns/containment/box.md +87 -0
  122. package/patterns/containment/clamped-card.md +86 -0
  123. package/patterns/containment/content-limiter.md +87 -0
  124. package/patterns/containment/fluid-styles.md +86 -0
  125. package/patterns/containment/index.md +8 -0
  126. package/patterns/grid-repetition/card-grid.md +88 -0
  127. package/patterns/grid-repetition/columns.md +87 -0
  128. package/patterns/grid-repetition/dense-grid.md +88 -0
  129. package/patterns/grid-repetition/grid-wrapper.md +89 -0
  130. package/patterns/grid-repetition/index.md +12 -0
  131. package/patterns/grid-repetition/masonry-approx.md +87 -0
  132. package/patterns/grid-repetition/page-grid.md +90 -0
  133. package/patterns/grid-repetition/ram-grid.md +88 -0
  134. package/patterns/grid-repetition/twelve-span-grid.md +92 -0
  135. package/patterns/in-line-grouping/badge-list.md +94 -0
  136. package/patterns/in-line-grouping/breadcrumb.md +89 -0
  137. package/patterns/in-line-grouping/cluster.md +89 -0
  138. package/patterns/in-line-grouping/deconstructed-pancake.md +92 -0
  139. package/patterns/in-line-grouping/index.md +13 -0
  140. package/patterns/in-line-grouping/pagination.md +89 -0
  141. package/patterns/in-line-grouping/reel.md +90 -0
  142. package/patterns/in-line-grouping/split-nav.md +97 -0
  143. package/patterns/in-line-grouping/tab-strip.md +88 -0
  144. package/patterns/in-line-grouping/wrap-row.md +89 -0
  145. package/patterns/index.md +13 -0
  146. package/patterns/media-fit/frame.md +95 -0
  147. package/patterns/media-fit/icon-frame.md +87 -0
  148. package/patterns/media-fit/index.md +6 -0
  149. package/patterns/overlay-exception/imposter.md +95 -0
  150. package/patterns/overlay-exception/index.md +6 -0
  151. package/patterns/overlay-exception/overlay-stack.md +89 -0
  152. package/patterns/split-sidebar/index.md +12 -0
  153. package/patterns/split-sidebar/list-detail.md +95 -0
  154. package/patterns/split-sidebar/main-with-rail.md +95 -0
  155. package/patterns/split-sidebar/media-object.md +102 -0
  156. package/patterns/split-sidebar/sidebar.md +101 -0
  157. package/patterns/split-sidebar/split-screen.md +92 -0
  158. package/patterns/split-sidebar/sticky-aside.md +97 -0
  159. package/patterns/split-sidebar/supporting-pane.md +95 -0
  160. package/patterns/split-sidebar/switcher.md +93 -0
  161. package/patterns/stacking/feed.md +88 -0
  162. package/patterns/stacking/index.md +8 -0
  163. package/patterns/stacking/line-up.md +95 -0
  164. package/patterns/stacking/stack.md +87 -0
  165. package/patterns/stacking/step-nav.md +88 -0
  166. package/patterns/viewport-shell/cover.md +90 -0
  167. package/patterns/viewport-shell/fixed-sidenav-shell.md +97 -0
  168. package/patterns/viewport-shell/holy-grail.md +112 -0
  169. package/patterns/viewport-shell/index.md +11 -0
  170. package/patterns/viewport-shell/panel-layout.md +95 -0
  171. package/patterns/viewport-shell/scroll-body-shell.md +93 -0
  172. package/patterns/viewport-shell/sticky-footer.md +92 -0
  173. package/patterns/viewport-shell/sticky-header.md +86 -0
  174. package/platform-guides/apple-interaction.md +89 -0
  175. package/platform-guides/index.md +26 -0
  176. package/quality/claim-records/index.md +3 -0
  177. package/quality/claim-records/samples.md +92 -0
  178. package/quality/claim-records/stylegallery-multidomain-scope.md +42 -0
  179. package/quality/claims.md +77 -0
  180. package/quality/evidence/accessibility.md +58 -0
  181. package/quality/evidence/consumer-migration.md +42 -0
  182. package/quality/evidence/design-rationale.md +34 -0
  183. package/quality/evidence/executable-evidence.md +79 -0
  184. package/quality/evidence/families.md +56 -0
  185. package/quality/evidence/hci-evaluation.md +36 -0
  186. package/quality/evidence/index.md +16 -0
  187. package/quality/evidence/pattern-contract-audit.md +96 -0
  188. package/quality/evidence/search-metadata-polyhierarchy.md +86 -0
  189. package/quality/evidence/sources.md +43 -0
  190. package/quality/evidence/tokens.md +33 -0
  191. package/quality/evidence/visual-qa.md +41 -0
  192. package/quality/gates/accessibility-evidence.md +60 -0
  193. package/quality/gates/consumer-migration-evidence.md +53 -0
  194. package/quality/gates/design-claim.md +56 -0
  195. package/quality/gates/harmony-evaluation.md +78 -0
  196. package/quality/gates/index.md +13 -0
  197. package/quality/gates/layout.md +52 -0
  198. package/quality/gates/rationale.md +53 -0
  199. package/quality/gates/visual-evidence.md +47 -0
  200. package/quality/index.md +55 -0
  201. package/quality/principles.md +58 -0
  202. package/recipes/article-page.md +52 -0
  203. package/recipes/command-surface.md +55 -0
  204. package/recipes/dashboard.md +56 -0
  205. package/recipes/form-flow.md +55 -0
  206. package/recipes/homepage.md +89 -0
  207. package/recipes/index.md +13 -0
  208. package/recipes/list-detail.md +55 -0
  209. package/recipes/primitive-to-recipe-matrix.md +83 -0
  210. package/recipes/saas-settings.md +52 -0
  211. package/scripts/agent-native/a2a-projection.mjs +248 -0
  212. package/scripts/agent-native/agui-projection.mjs +178 -0
  213. package/scripts/agent-native/canonical-json.mjs +109 -0
  214. package/scripts/agent-native/cli-adapter.mjs +68 -0
  215. package/scripts/agent-native/events.mjs +113 -0
  216. package/scripts/agent-native/execution.mjs +227 -0
  217. package/scripts/agent-native/fixture.mjs +159 -0
  218. package/scripts/agent-native/identity.mjs +184 -0
  219. package/scripts/agent-native/immutable-store.mjs +102 -0
  220. package/scripts/agent-native/knowledge.mjs +168 -0
  221. package/scripts/agent-native/learning-records.mjs +244 -0
  222. package/scripts/agent-native/learning.mjs +247 -0
  223. package/scripts/agent-native/mcp-adapter.mjs +173 -0
  224. package/scripts/agent-native/queries.mjs +173 -0
  225. package/scripts/agent-native/registry.mjs +154 -0
  226. package/scripts/agent-native/retrieval.mjs +171 -0
  227. package/scripts/agent-native/self-description.mjs +160 -0
  228. package/scripts/artifact-metadata.mjs +20 -0
  229. package/scripts/audit-evidence-freshness.mjs +308 -0
  230. package/scripts/baseline-contract.mjs +189 -0
  231. package/scripts/baseline-schema-parity.mjs +40 -0
  232. package/scripts/build-reference-artifacts.mjs +127 -0
  233. package/scripts/calibration-raw-contract.mjs +172 -0
  234. package/scripts/capture-session-contract.mjs +187 -0
  235. package/scripts/component-state-artifact-fixture.mjs +44 -0
  236. package/scripts/component-state-contract.mjs +99 -0
  237. package/scripts/component-state-semantics.mjs +128 -0
  238. package/scripts/component-state-workflow-contract.mjs +67 -0
  239. package/scripts/component-state-workflow-negative-cases.mjs +64 -0
  240. package/scripts/consumer-conformance-contract.mjs +198 -0
  241. package/scripts/consumer-evidence-governance-contract.mjs +210 -0
  242. package/scripts/consumer-reference-case-runner.mjs +93 -0
  243. package/scripts/consumer-reference-schema.mjs +155 -0
  244. package/scripts/create-component-state-session.mjs +100 -0
  245. package/scripts/create-page-evidence-session.mjs +139 -0
  246. package/scripts/domain-document-boundaries.mjs +40 -0
  247. package/scripts/domain-validation-checks.mjs +141 -0
  248. package/scripts/evidence-artifact-contract.mjs +191 -0
  249. package/scripts/finalize-component-state-evidence.mjs +165 -0
  250. package/scripts/finalize-page-evidence.mjs +197 -0
  251. package/scripts/generate-consumer-reference-evidence.mjs +154 -0
  252. package/scripts/generate-patterns.mjs +218 -0
  253. package/scripts/governance-matrix-contract.mjs +73 -0
  254. package/scripts/governance-matrix-negative-cases.mjs +114 -0
  255. package/scripts/governance-policy-contract.mjs +49 -0
  256. package/scripts/governance-test-fixture.mjs +321 -0
  257. package/scripts/governance-workflow-negative-cases.mjs +241 -0
  258. package/scripts/governed-profile-registry.mjs +125 -0
  259. package/scripts/json-schema-formats.mjs +31 -0
  260. package/scripts/markdown-structure.mjs +45 -0
  261. package/scripts/page-artifact-metadata.mjs +124 -0
  262. package/scripts/page-evidence-contract.mjs +297 -0
  263. package/scripts/page-evidence-fixture.mjs +271 -0
  264. package/scripts/pattern-data.mjs +325 -0
  265. package/scripts/profile-record-contract.mjs +140 -0
  266. package/scripts/promotion-attestation-contract.mjs +91 -0
  267. package/scripts/promotion-boundary-test-contract.mjs +92 -0
  268. package/scripts/promotion-fixture-inventory.mjs +109 -0
  269. package/scripts/promotion-governance-contract.mjs +28 -0
  270. package/scripts/reference-artifact-path-contract.mjs +28 -0
  271. package/scripts/reference-profile-contract.mjs +114 -0
  272. package/scripts/reference-token-contract.mjs +156 -0
  273. package/scripts/run-consumer-page-evidence-ci.mjs +170 -0
  274. package/scripts/sg-mcp.mjs +16 -0
  275. package/scripts/sg.mjs +27 -0
  276. package/scripts/strict-json.mjs +72 -0
  277. package/scripts/summarize-sentinel-calibration.mjs +98 -0
  278. package/scripts/test-agent-adapter-conformance.mjs +250 -0
  279. package/scripts/test-agent-conformance-receipt.mjs +106 -0
  280. package/scripts/test-agent-events.mjs +81 -0
  281. package/scripts/test-agent-execution-effects.mjs +114 -0
  282. package/scripts/test-agent-execution-fixtures.mjs +140 -0
  283. package/scripts/test-agent-execution-kernel.mjs +39 -0
  284. package/scripts/test-agent-execution-learning.mjs +130 -0
  285. package/scripts/test-agent-execution-lifecycle.mjs +143 -0
  286. package/scripts/test-agent-execution-safety.mjs +158 -0
  287. package/scripts/test-agent-execution-views.mjs +117 -0
  288. package/scripts/test-agent-identity-integrity-cases.mjs +160 -0
  289. package/scripts/test-agent-knowledge-kernel.mjs +183 -0
  290. package/scripts/test-agent-learning.mjs +246 -0
  291. package/scripts/test-agent-mcp.mjs +246 -0
  292. package/scripts/test-agent-native-schemas.mjs +215 -0
  293. package/scripts/test-agent-projections.mjs +249 -0
  294. package/scripts/test-agent-registry-mcp-integrity.mjs +215 -0
  295. package/scripts/test-agent-registry-mutations.mjs +110 -0
  296. package/scripts/test-audit-evidence-freshness.mjs +177 -0
  297. package/scripts/test-component-state-sentinel.mjs +35 -0
  298. package/scripts/test-component-state-source-contract.mjs +83 -0
  299. package/scripts/test-consumer-conformance-sentinel.mjs +165 -0
  300. package/scripts/test-consumer-reference-sentinel.mjs +31 -0
  301. package/scripts/test-generate-consumer-reference-evidence.mjs +124 -0
  302. package/scripts/test-json-cli-output.mjs +151 -0
  303. package/scripts/test-json-schema-formats.mjs +40 -0
  304. package/scripts/test-reference-adapters.mjs +199 -0
  305. package/scripts/test-renderer-purity.mjs +34 -0
  306. package/scripts/test-sg-cli.mjs +129 -0
  307. package/scripts/test-summarize-sentinel-calibration.mjs +226 -0
  308. package/scripts/test-validate-baseline-manifest.mjs +234 -0
  309. package/scripts/test-validate-component-state-artifacts.mjs +243 -0
  310. package/scripts/test-validate-component-state.mjs +106 -0
  311. package/scripts/test-validate-consumer-conformance.mjs +427 -0
  312. package/scripts/test-validate-consumer-reference-cli.mjs +69 -0
  313. package/scripts/test-validate-consumer-reference.mjs +263 -0
  314. package/scripts/test-validate-domains.mjs +357 -0
  315. package/scripts/test-validate-governance.mjs +292 -0
  316. package/scripts/test-validate-ia.mjs +262 -0
  317. package/scripts/test-validate-okf.mjs +73 -0
  318. package/scripts/test-validate-page-evidence.mjs +302 -0
  319. package/scripts/test-validate-patterns.mjs +157 -0
  320. package/scripts/test-validate-promotion-rfc.mjs +250 -0
  321. package/scripts/test-validate-reference-profiles.mjs +170 -0
  322. package/scripts/test-validate-unity-org-wiki.mjs +57 -0
  323. package/scripts/test-validate-unity-source-contracts.mjs +67 -0
  324. package/scripts/test-validate-vocabulary.mjs +174 -0
  325. package/scripts/test-validate-webpage-workflow.mjs +293 -0
  326. package/scripts/validate-baseline-manifest.mjs +44 -0
  327. package/scripts/validate-catalog.mjs +65 -0
  328. package/scripts/validate-component-state.mjs +141 -0
  329. package/scripts/validate-consumer-conformance.mjs +477 -0
  330. package/scripts/validate-consumer-reference.mjs +288 -0
  331. package/scripts/validate-domains.mjs +237 -0
  332. package/scripts/validate-governance.mjs +248 -0
  333. package/scripts/validate-ia.mjs +136 -0
  334. package/scripts/validate-links.mjs +66 -0
  335. package/scripts/validate-okf.mjs +104 -0
  336. package/scripts/validate-page-evidence.mjs +191 -0
  337. package/scripts/validate-patterns.mjs +246 -0
  338. package/scripts/validate-promotion-rfc.mjs +224 -0
  339. package/scripts/validate-reference-artifacts.mjs +125 -0
  340. package/scripts/validate-renderer-purity.mjs +56 -0
  341. package/scripts/validate-unity-org-wiki.mjs +146 -0
  342. package/scripts/validate-unity-source-contracts.mjs +107 -0
  343. package/scripts/validate-vocabulary.mjs +115 -0
  344. package/scripts/validate-webpage-workflow.mjs +254 -0
  345. package/scripts/visual-expectation-contract.mjs +20 -0
  346. package/scripts/workflow-action-contract.mjs +163 -0
@@ -0,0 +1,160 @@
1
+ import { createHash } from "node:crypto";
2
+ import { canonicalize, hashCanonical } from "./agent-native/canonical-json.mjs";
3
+ import {
4
+ createManifest,
5
+ createStableRef,
6
+ createVersionId,
7
+ parseStableRef,
8
+ parseVersionId,
9
+ verifyManifest,
10
+ } from "./agent-native/identity.mjs";
11
+ import { createImmutableStore } from "./agent-native/immutable-store.mjs";
12
+
13
+ class IntegrityAssertionError extends Error {
14
+ constructor(message) {
15
+ super(message);
16
+ this.code = "assertion_failed";
17
+ }
18
+ }
19
+
20
+ function assert(condition, message) {
21
+ if (!condition) throw new IntegrityAssertionError(message);
22
+ }
23
+
24
+ function expectCode(execute, code, message) {
25
+ try {
26
+ execute();
27
+ } catch (error) {
28
+ assert(error?.code === code, `${message}: expected ${code}, got ${error?.code}`);
29
+ return error.code;
30
+ }
31
+ throw new IntegrityAssertionError(`${message}: operation succeeded`);
32
+ }
33
+
34
+ async function runCase(name, expected, execute) {
35
+ try {
36
+ return { actual: await execute(), expected, name, ok: true };
37
+ } catch (error) {
38
+ return {
39
+ actual: {
40
+ code: error?.code ?? "integrity_case_exception",
41
+ message: error instanceof Error ? error.message : String(error),
42
+ ...(error?.path ? { path: error.path } : {}),
43
+ },
44
+ expected,
45
+ name,
46
+ ok: false,
47
+ };
48
+ }
49
+ }
50
+
51
+ function versioned(stable_ref, content) {
52
+ return { ...content, stable_ref, version_id: createVersionId({ stable_ref, payload: content }) };
53
+ }
54
+
55
+ export async function runIdentityIntegrityCases() {
56
+ const results = [];
57
+ results.push(await runCase("canonical_json_is_recursive_and_deterministic", "keys sorted recursively", () => {
58
+ const bytes = canonicalize({ z: 2, a: { z: false, b: 1 }, m: [3, { y: 1, x: 0 }] });
59
+ assert(bytes === '{"a":{"b":1,"z":false},"m":[3,{"x":0,"y":1}],"z":2}', `unexpected canonical bytes: ${bytes}`);
60
+ const hashBytes = canonicalize({ b: 2, a: 1 });
61
+ const digest = hashCanonical({ b: 2, a: 1 }).slice("sha256:".length);
62
+ assert(digest === createHash("sha256").update(hashBytes).digest("hex"), "canonical hash does not match canonical UTF-8 bytes");
63
+ return { bytes, digest };
64
+ }));
65
+ results.push(await runCase("stable_ref_grammar_and_round_trip", "governed StableRef round-trips", () => {
66
+ const stable_ref = createStableRef({ kind: "claim", id: "editorial-layout" });
67
+ assert(parseStableRef(stable_ref).id === "editorial-layout", "opaque id was not parsed");
68
+ expectCode(() => parseStableRef("claim/editorial layout"), "stable_ref_invalid", "malformed StableRef accepted");
69
+ return { stable_ref };
70
+ }));
71
+ results.push(await runCase("version_id_binds_domain_identity_and_all_content", "StableRef and domain id alter digest", () => {
72
+ const first = createVersionId({ stable_ref: "sg:claim/shared", id: "alpha", statement: "same" });
73
+ const reordered = createVersionId({ statement: "same", id: "alpha", stable_ref: "sg:claim/shared" });
74
+ const second = createVersionId({ stable_ref: "sg:claim/shared", id: "beta", statement: "same" });
75
+ const otherRef = createVersionId({ stable_ref: "sg:claim/other", id: "alpha", statement: "same" });
76
+ assert(first === reordered, "VersionID depends on object key order");
77
+ assert(first !== second, "records differing only by domain id collided");
78
+ assert(first.split("@sha256:")[1] !== otherRef.split("@sha256:")[1], "StableRef was absent from digest input");
79
+ const parsed = parseVersionId({ version_id: first, stable_ref: "sg:claim/shared", payload: { id: "alpha", statement: "same" } });
80
+ assert(parsed.stable_ref === "sg:claim/shared", "VersionID lost its StableRef");
81
+ const parsedString = parseVersionId(first);
82
+ assert(parsedString.version_id === first && parsedString.stable_ref === "sg:claim/shared", "raw VersionID string did not round-trip");
83
+ expectCode(
84
+ () => parseVersionId({ version_id: first, payload: { id: "beta", statement: "same" } }),
85
+ "version_digest_mismatch",
86
+ "changed domain id verified",
87
+ );
88
+ return { first, second, other_ref: otherRef };
89
+ }));
90
+ results.push(await runCase("immutable_store_rehashes_every_append", "forged and altered records are rejected", () => {
91
+ const store = createImmutableStore();
92
+ const valid = versioned("sg:claim/store-fixture", { id: "alpha", nested: { value: "original" } });
93
+ const inserted = store.append(valid);
94
+ assert(Object.isFrozen(inserted) && Object.isFrozen(inserted.nested), "stored record is not deeply frozen");
95
+ try { inserted.nested.value = "tampered"; } catch { /* frozen ESM records throw */ }
96
+ assert(inserted.nested.value === "original", "stored nested bytes were mutable");
97
+ expectCode(
98
+ () => store.append({ ...valid, stable_ref: "sg:claim/forged", version_id: `sg:claim/forged@sha256:${"0".repeat(64)}` }),
99
+ "version_digest_mismatch",
100
+ "forged VersionID accepted",
101
+ );
102
+ expectCode(
103
+ () => store.append({ ...valid, nested: { value: "tampered" } }),
104
+ "version_digest_mismatch",
105
+ "altered bytes accepted under an existing VersionID",
106
+ );
107
+ return { size: store.size, version_id: valid.version_id };
108
+ }));
109
+ results.push(await runCase("manifest_binds_version_digest_content_digest_and_content", "inline content is checked three ways", () => {
110
+ const alphaContent = { id: "alpha", statement: "A" };
111
+ const zetaContent = { id: "zeta", statement: "Z" };
112
+ const entry = (stable_ref, content) => ({
113
+ stable_ref,
114
+ content,
115
+ content_sha256: hashCanonical(content).slice("sha256:".length),
116
+ version_id: createVersionId({ stable_ref, payload: content }),
117
+ });
118
+ const manifest = createManifest({
119
+ manifest_ref: "sg:manifest/identity-fixture",
120
+ entries: [entry("sg:claim/zeta", zetaContent), entry("sg:claim/alpha", alphaContent)],
121
+ });
122
+ assert(manifest.entries[0].stable_ref === "sg:claim/alpha", "entries were not sorted");
123
+ assert(new Set(manifest.entries.map(({ stable_ref }) => stable_ref)).size === manifest.entries.length, "entries were not unique");
124
+ assert(verifyManifest(manifest).ok, "fresh content-backed manifest failed verification");
125
+ expectCode(
126
+ () => createManifest({ manifest_ref: "sg:manifest/identity-fixture", entries: [entry("sg:claim/alpha", alphaContent), entry("sg:claim/alpha", alphaContent)] }),
127
+ "manifest_entry_duplicate",
128
+ "duplicate StableRefs accepted",
129
+ );
130
+ expectCode(
131
+ () => createManifest({ manifest_ref: "sg:manifest/identity-fixture", entries: [{ ...entry("sg:claim/alpha", alphaContent), content: { id: "beta", statement: "A" } }] }),
132
+ "version_digest_mismatch",
133
+ "VersionID unrelated to inline content accepted",
134
+ );
135
+ expectCode(
136
+ () => createManifest({ manifest_ref: "sg:manifest/identity-fixture", entries: [{ ...entry("sg:claim/alpha", alphaContent), content_sha256: "1".repeat(64) }] }),
137
+ "manifest_content_digest_mismatch",
138
+ "content digest unrelated to inline content accepted",
139
+ );
140
+ expectCode(
141
+ () => createManifest({ manifest_ref: "sg:manifest/identity-fixture", entries: [{ ...entry("sg:claim/alpha", alphaContent), content: { ...alphaContent, stable_ref: "sg:claim/zeta" } }] }),
142
+ "manifest_content_ref_mismatch",
143
+ "content carrying a different StableRef accepted",
144
+ );
145
+ expectCode(
146
+ () => createManifest({ manifest_ref: "sg:manifest/identity-fixture", entries: [{ ...entry("sg:claim/alpha", alphaContent), content: { ...alphaContent, version_id: `sg:claim/alpha@sha256:${"0".repeat(64)}` } }] }),
147
+ "manifest_content_version_mismatch",
148
+ "content carrying a different VersionID accepted",
149
+ );
150
+ const tampered = structuredClone(manifest);
151
+ tampered.entries[0].content.statement = "tampered";
152
+ const verification = verifyManifest(tampered);
153
+ assert(!verification.ok && verification.failures.some(({ code }) => code === "version_digest_mismatch"), "tampered inline content verified");
154
+ const digestTampered = structuredClone(manifest);
155
+ digestTampered.sha256 = "0".repeat(64);
156
+ assert(!verifyManifest(digestTampered).ok, "tampered manifest digest verified");
157
+ return { entries: manifest.entries.length, version_id: manifest.version_id };
158
+ }));
159
+ return results;
160
+ }
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { runIdentityIntegrityCases } from "./test-agent-identity-integrity-cases.mjs";
6
+
7
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
8
+ const moduleFiles = Object.freeze({
9
+ canonical: "scripts/agent-native/canonical-json.mjs",
10
+ identity: "scripts/agent-native/identity.mjs",
11
+ store: "scripts/agent-native/immutable-store.mjs",
12
+ knowledge: "scripts/agent-native/knowledge.mjs",
13
+ });
14
+
15
+ function failure(code, message, recordPath) {
16
+ return { code, message, ...(recordPath ? { path: recordPath } : {}) };
17
+ }
18
+
19
+ function valueAt(record, ...keys) {
20
+ for (const key of keys) {
21
+ if (record && Object.hasOwn(record, key)) return record[key];
22
+ }
23
+ return undefined;
24
+ }
25
+
26
+ class ContractError extends Error {
27
+ constructor(code, message, recordPath) {
28
+ super(message);
29
+ this.code = code;
30
+ this.path = recordPath;
31
+ }
32
+ }
33
+
34
+ function requireExport(modules, moduleName, names) {
35
+ const moduleRecord = modules[moduleName];
36
+ if (!moduleRecord || moduleRecord.error) {
37
+ const detail = moduleRecord?.error?.message ?? "module was not loaded";
38
+ throw new ContractError("kernel_module_missing", `${moduleFiles[moduleName]} is unavailable: ${detail}`, moduleFiles[moduleName]);
39
+ }
40
+ for (const name of names) {
41
+ if (typeof moduleRecord.value?.[name] === "function") return moduleRecord.value[name];
42
+ }
43
+ throw new ContractError("kernel_export_missing", `${moduleFiles[moduleName]} must export one of ${names.join(", ")}`, moduleFiles[moduleName]);
44
+ }
45
+
46
+ function assert(condition, message, recordPath) {
47
+ if (!condition) throw new ContractError("assertion_failed", message, recordPath);
48
+ }
49
+
50
+ function resultState(result) {
51
+ const state = valueAt(result, "state", "evidence_state", "aggregation", "status");
52
+ return typeof state === "string" ? state.toUpperCase() : state;
53
+ }
54
+
55
+ function makeFixture(modules) {
56
+ const claimFactory = requireExport(modules, "knowledge", ["createClaim", "makeClaim"]);
57
+ const evidenceFactory = requireExport(modules, "knowledge", ["createEvidenceLink", "makeEvidenceLink"]);
58
+ const validationFactory = requireExport(modules, "knowledge", ["createValidationReport", "makeValidationReport"]);
59
+ const governanceFactory = requireExport(modules, "knowledge", ["createGovernanceDecision", "makeGovernanceDecision"]);
60
+ const claim = claimFactory({
61
+ stable_ref: "sg:claim/editorial-layout",
62
+ statement: "Editorial layout keeps reading order stable.",
63
+ subject: "sg:profile/editorial-reference-profile",
64
+ actor: "sg:agent/fixture",
65
+ });
66
+ const evidence = (polarity, suffix) => evidenceFactory({
67
+ stable_ref: `sg:evidence/editorial-layout-${suffix}`,
68
+ claim_ref: valueAt(claim, "stable_ref", "stableRef") ?? "sg:claim/editorial-layout",
69
+ claim_version: valueAt(claim, "version_id", "versionId"),
70
+ source_ref: "sg:artifact/editorial-layout-fixture",
71
+ source_version: "sg:artifact/editorial-layout-fixture@sha256:" + "1".repeat(64),
72
+ polarity,
73
+ independence_group: `fixture-${suffix}`,
74
+ actor: `sg:observer/${suffix}`,
75
+ });
76
+ const validation = validationFactory({
77
+ stable_ref: "sg:validation/editorial-layout-pass",
78
+ claim_ref: valueAt(claim, "stable_ref", "stableRef"),
79
+ claim_version: valueAt(claim, "version_id", "versionId"),
80
+ validator: "sg:validator/fixture",
81
+ validator_version: "sg:validator/fixture@sha256:" + "2".repeat(64),
82
+ status: "PASSED",
83
+ inputs: [valueAt(claim, "version_id", "versionId")],
84
+ });
85
+ const governance = governanceFactory({
86
+ stable_ref: "sg:governance/editorial-layout-accept",
87
+ claim_ref: valueAt(claim, "stable_ref", "stableRef"),
88
+ claim_version: valueAt(claim, "version_id", "versionId"),
89
+ actor: "sg:governor/fixture",
90
+ decision: "ACCEPTED",
91
+ scope: "fixture",
92
+ policy_version: "sg:governance-policy/fixture@sha256:" + "3".repeat(64),
93
+ });
94
+ return { claim, evidence, evidence_sample: evidence("SUPPORT", "fixture"), validation, governance };
95
+ }
96
+
97
+ async function loadModules() {
98
+ const modules = {};
99
+ for (const [name, relative] of Object.entries(moduleFiles)) {
100
+ try {
101
+ modules[name] = { value: await import(path.join(root, relative)) };
102
+ } catch (error) {
103
+ modules[name] = { error: error instanceof Error ? error : new Error(String(error)) };
104
+ }
105
+ }
106
+ return modules;
107
+ }
108
+
109
+ async function runCase(name, expected, execute) {
110
+ try {
111
+ const actual = await execute();
112
+ return { actual, expected, name, ok: true };
113
+ } catch (error) {
114
+ return {
115
+ actual: {
116
+ code: error instanceof ContractError ? error.code : "kernel_case_exception",
117
+ message: error instanceof Error ? error.message : String(error),
118
+ ...(error?.path ? { path: error.path } : {}),
119
+ },
120
+ expected,
121
+ name,
122
+ ok: false,
123
+ };
124
+ }
125
+ }
126
+
127
+ async function main() {
128
+ const unsupported = process.argv.slice(2).filter((argument) => argument !== "--json");
129
+ if (unsupported.length > 0) {
130
+ const report = { ok: false, status: "RED", failures: [failure("argument_unknown", `unknown argument ${unsupported[0]}`)], results: [] };
131
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
132
+ process.exitCode = 1;
133
+ return;
134
+ }
135
+
136
+ const modules = await loadModules();
137
+ const aggregate = () => requireExport(modules, "knowledge", ["aggregateEvidence", "aggregateEvidenceState"]);
138
+
139
+ const results = await runIdentityIntegrityCases();
140
+ results.push(await runCase("claim_evidence_validation_governance_are_distinct_frozen_objects", "each epistemic object has its own immutable identity and lifecycle", () => {
141
+ const fixture = makeFixture(modules);
142
+ for (const [name, value] of Object.entries(fixture)) {
143
+ if (name === "evidence") continue;
144
+ assert(value && typeof value === "object" && Object.isFrozen(value), `${name} is not deeply frozen`);
145
+ assert(typeof valueAt(value, "stable_ref", "stableRef") === "string", `${name} has no StableRef`);
146
+ assert(typeof valueAt(value, "version_id", "versionId") === "string", `${name} has no VersionID`);
147
+ }
148
+ assert(fixture.claim !== fixture.validation && fixture.claim !== fixture.governance, "knowledge layers were conflated");
149
+ return { refs: Object.fromEntries(Object.entries(fixture).map(([name, value]) => [name, valueAt(value, "stable_ref", "stableRef")])) };
150
+ }));
151
+ for (const [name, expectedState, links] of [["supported", "SUPPORTED", ["SUPPORT"]], ["refuted", "REFUTED", ["REFUTE"]], ["both", "BOTH", ["SUPPORT", "REFUTE"]], ["neither", "NEITHER", []]]) {
152
+ results.push(await runCase(`evidence_aggregation_${name}`, `aggregation is ${expectedState}`, () => {
153
+ const fixture = makeFixture(modules);
154
+ const evidence = links.map((polarity, index) => fixture.evidence(polarity, `${name}-${index}`));
155
+ const value = aggregate()({ claim: fixture.claim, evidence_links: evidence, evidenceLinks: evidence });
156
+ assert(resultState(value) === expectedState, `expected ${expectedState}, got ${resultState(value)}`);
157
+ return { state: resultState(value) };
158
+ }));
159
+ }
160
+ results.push(await runCase("validation_and_governance_do_not_erase_contradiction", "validation approval and governance acceptance remain separate from BOTH evidence", () => {
161
+ const fixture = makeFixture(modules);
162
+ const evidence = [fixture.evidence("SUPPORT", "contradiction-support"), fixture.evidence("REFUTE", "contradiction-refute")];
163
+ const before = resultState(aggregate()({ claim: fixture.claim, evidence_links: evidence, evidenceLinks: evidence }));
164
+ assert(before === "BOTH", `contradiction fixture did not aggregate BOTH: ${before}`);
165
+ assert(valueAt(fixture.validation, "status") === "PASSED", "validation fixture is not passed");
166
+ assert(valueAt(fixture.governance, "decision", "status") === "ACCEPTED", "governance fixture is not accepted");
167
+ const after = resultState(aggregate()({ claim: fixture.claim, evidence_links: evidence, evidenceLinks: evidence }));
168
+ assert(after === "BOTH", `validation/governance erased contradiction: ${after}`);
169
+ return { before, after, validation: valueAt(fixture.validation, "status"), governance: valueAt(fixture.governance, "decision", "status") };
170
+ }));
171
+
172
+ const ok = results.every((result) => result.ok);
173
+ const report = {
174
+ ok,
175
+ status: ok ? "GREEN" : "RED",
176
+ modules: Object.fromEntries(Object.entries(modules).map(([name, loaded]) => [name, loaded.error ? { ok: false, error: loaded.error.message } : { ok: true }])),
177
+ results,
178
+ };
179
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
180
+ process.exitCode = ok ? 0 : 1;
181
+ }
182
+
183
+ await main();
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env node
2
+ import { createVersionId, parseVersionId } from "./agent-native/identity.mjs";
3
+ import {
4
+ createProposal,
5
+ decideProposal,
6
+ promoteProposal,
7
+ verifyProposal,
8
+ } from "./agent-native/learning.mjs";
9
+
10
+ function omitVersion(record) {
11
+ const payload = structuredClone(record);
12
+ delete payload.version_id;
13
+ delete payload.versionId;
14
+ return payload;
15
+ }
16
+
17
+ function reversion(record, changes) {
18
+ const payload = { ...omitVersion(record), ...changes };
19
+ return {
20
+ ...payload,
21
+ version_id: createVersionId({ stable_ref: payload.stable_ref, payload }),
22
+ };
23
+ }
24
+
25
+ function isVersioned(record, kind) {
26
+ if (!record || record.record_kind !== kind || typeof record.version_id !== "string") return false;
27
+ try {
28
+ parseVersionId({
29
+ payload: omitVersion(record),
30
+ stable_ref: record.stable_ref,
31
+ version_id: record.version_id,
32
+ });
33
+ return Object.isFrozen(record);
34
+ } catch {
35
+ return false;
36
+ }
37
+ }
38
+
39
+ function rejected(call) {
40
+ try {
41
+ const value = call();
42
+ return value?.promoted !== true && (value?.ok === false || value?.status === "BLOCKED");
43
+ } catch (error) {
44
+ return typeof error?.code === "string" && error.code.startsWith("learning_");
45
+ }
46
+ }
47
+
48
+ function result(id, ok, detail) {
49
+ return { id, ok, detail };
50
+ }
51
+
52
+ const proposalInput = {
53
+ claim: {
54
+ stable_ref: "sg:claim/retrieval-improvement",
55
+ text: "The retriever preserves citation coverage.",
56
+ },
57
+ changes: [{ path: "retriever.strategy", value: "hybrid" }],
58
+ evidence: [{
59
+ independence_group: "capture-a",
60
+ source_ref: "sg:source/execution-fixture",
61
+ stable_ref: "sg:evidence/retrieval-proposal",
62
+ }],
63
+ proposer: "agent:proposer",
64
+ proposal_id: "sg:proposal/retrieval-improvement",
65
+ source_task: "sg:task/execution-fixture",
66
+ validation: {
67
+ status: "PASS",
68
+ validator: "agent:proposal-validator",
69
+ validator_version: "validator@v1",
70
+ },
71
+ };
72
+
73
+ const proposal = createProposal(proposalInput);
74
+ const verification = verifyProposal({
75
+ evidence: [{
76
+ independence_group: "capture-b",
77
+ source_ref: "sg:source/independent-fixture",
78
+ stable_ref: "sg:evidence/retrieval-verification",
79
+ }],
80
+ independent_of: "agent:proposer",
81
+ proposal,
82
+ validation: {
83
+ status: "PASS",
84
+ validator: "agent:independent-validator",
85
+ validator_version: "validator@v2",
86
+ },
87
+ verifier: "agent:verifier",
88
+ });
89
+ const decision = decideProposal({
90
+ decision: "ACCEPT",
91
+ governance_decision: {
92
+ actor: "governor:review-board",
93
+ decided_at: "2026-07-23T00:00:00.000Z",
94
+ },
95
+ proposal,
96
+ verification,
97
+ });
98
+
99
+ const validPromotion = promoteProposal({
100
+ governance_decision: decision,
101
+ proposal,
102
+ verification,
103
+ });
104
+ const proposalV2 = createProposal({
105
+ ...proposalInput,
106
+ changes: [{ path: "retriever.strategy", value: "semantic" }],
107
+ });
108
+ const forgedProposal = {
109
+ ...structuredClone(proposal),
110
+ changes: [{ path: "retriever.strategy", value: "forged" }],
111
+ };
112
+ const forgedVerification = {
113
+ ...structuredClone(verification),
114
+ verifier: "agent:forger",
115
+ verifier_actor: "agent:forger",
116
+ };
117
+ const wrongKindVerification = reversion(verification, {
118
+ record_kind: "evidence_link",
119
+ });
120
+ const wrongLinkDecision = reversion(decision, {
121
+ verification_ref: "sg:validation/unrelated-verification",
122
+ });
123
+ const wrongKindDecision = reversion(decision, {
124
+ record_kind: "learning_verification",
125
+ });
126
+ const forgedDecision = {
127
+ ...structuredClone(decision),
128
+ actor: "governor:forger",
129
+ };
130
+ const aliasInjectedDecision = {
131
+ ...structuredClone(decision),
132
+ versionId: `sg:governance/alias@sha256:${"0".repeat(64)}`,
133
+ };
134
+ const tamperedEvidence = structuredClone(verification.evidence);
135
+ tamperedEvidence[0].source_ref = "sg:source/tampered-fixture";
136
+ const verificationWithTamperedEvidence = reversion(verification, {
137
+ evidence: tamperedEvidence,
138
+ });
139
+
140
+ const rows = [
141
+ result(
142
+ "immutable_chain_is_fully_versioned",
143
+ isVersioned(proposal, "learning_proposal")
144
+ && proposal.evidence.every((item) => isVersioned(item, "evidence_link"))
145
+ && isVersioned(proposal.validation, "validation_report")
146
+ && isVersioned(verification, "learning_verification")
147
+ && verification.evidence.every((item) => isVersioned(item, "evidence_link"))
148
+ && isVersioned(verification.validation, "validation_report")
149
+ && isVersioned(decision, "governance_decision")
150
+ && decision.proposal_version_id === proposal.version_id
151
+ && decision.verification_version_id === verification.version_id,
152
+ "proposal, evidence, validation, verification, and decision have content-bound VersionIDs",
153
+ ),
154
+ result(
155
+ "valid_independent_chain_promotes",
156
+ validPromotion.promoted === true
157
+ && isVersioned(validPromotion.version, "governed_version")
158
+ && validPromotion.version.proposal_version_id === proposal.version_id
159
+ && validPromotion.version.verification_version_id === verification.version_id
160
+ && validPromotion.version.governance_decision_version_id === decision.version_id,
161
+ "a correctly linked independent chain produces one governed version",
162
+ ),
163
+ result(
164
+ "self_verification_is_rejected",
165
+ rejected(() => verifyProposal({
166
+ evidence: proposalInput.evidence,
167
+ proposal,
168
+ validation: proposalInput.validation,
169
+ verifier: "agent:proposer",
170
+ })),
171
+ "the proposer cannot verify its own proposal",
172
+ ),
173
+ result(
174
+ "whitespace_cannot_bypass_self_verification",
175
+ rejected(() => verifyProposal({
176
+ evidence: proposalInput.evidence,
177
+ proposal,
178
+ validation: proposalInput.validation,
179
+ verifier: " agent:proposer ",
180
+ })),
181
+ "actor identity is canonicalized before the independence comparison",
182
+ ),
183
+ result(
184
+ "forged_proposal_bytes_are_rejected",
185
+ rejected(() => promoteProposal({ governance_decision: decision, proposal: forgedProposal, verification })),
186
+ "changing proposal bytes without minting a matching VersionID is rejected",
187
+ ),
188
+ result(
189
+ "forged_verification_bytes_are_rejected",
190
+ rejected(() => promoteProposal({ governance_decision: decision, proposal, verification: forgedVerification })),
191
+ "changing verification bytes without minting a matching VersionID is rejected",
192
+ ),
193
+ result(
194
+ "stale_verification_is_rejected",
195
+ rejected(() => promoteProposal({ governance_decision: decision, proposal: proposalV2, verification })),
196
+ "verification and governance for an older proposal version cannot promote a newer proposal",
197
+ ),
198
+ result(
199
+ "wrong_kind_verification_is_rejected",
200
+ rejected(() => promoteProposal({ governance_decision: decision, proposal, verification: wrongKindVerification })),
201
+ "a content-valid record with the wrong semantic kind cannot stand in for verification",
202
+ ),
203
+ result(
204
+ "wrong_governance_link_is_rejected",
205
+ rejected(() => promoteProposal({ governance_decision: wrongLinkDecision, proposal, verification })),
206
+ "governance must bind the exact verification StableRef and VersionID",
207
+ ),
208
+ result(
209
+ "wrong_kind_governance_is_rejected",
210
+ rejected(() => promoteProposal({ governance_decision: wrongKindDecision, proposal, verification })),
211
+ "a content-valid record with the wrong semantic kind cannot stand in for governance",
212
+ ),
213
+ result(
214
+ "forged_governance_bytes_are_rejected",
215
+ rejected(() => promoteProposal({ governance_decision: forgedDecision, proposal, verification })),
216
+ "changing governance bytes without minting a matching VersionID is rejected",
217
+ ),
218
+ result(
219
+ "nested_evidence_bytes_are_rejected",
220
+ rejected(() => promoteProposal({ governance_decision: decision, proposal, verification: verificationWithTamperedEvidence })),
221
+ "an outer-valid verification cannot hide evidence whose bytes no longer match its VersionID",
222
+ ),
223
+ result(
224
+ "unbound_identity_alias_is_rejected",
225
+ rejected(() => promoteProposal({ governance_decision: aliasInjectedDecision, proposal, verification })),
226
+ "canonical learning records reject alternate identity fields that are not part of their VersionID",
227
+ ),
228
+ result(
229
+ "verification_actor_cannot_govern_same_proposal",
230
+ rejected(() => decideProposal({
231
+ decision: "ACCEPT",
232
+ governance_decision: { actor: "agent:verifier" },
233
+ proposal,
234
+ verification,
235
+ })),
236
+ "independent verification and governance remain separate actors",
237
+ ),
238
+ ];
239
+
240
+ const report = {
241
+ contract: "agent-native-governed-learning-integrity",
242
+ ok: rows.every((row) => row.ok),
243
+ results: rows,
244
+ };
245
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
246
+ process.exitCode = report.ok ? 0 : 1;