@dailephd/my-frontend-observer 0.8.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.
Files changed (316) hide show
  1. package/CHANGELOG.md +397 -0
  2. package/LICENSE +21 -0
  3. package/README.md +255 -0
  4. package/dist/application/browserCaptureService.d.ts +11 -0
  5. package/dist/application/browserCaptureService.js +12 -0
  6. package/dist/application/browserCaptureService.js.map +1 -0
  7. package/dist/application/comparisonService.d.ts +56 -0
  8. package/dist/application/comparisonService.js +77 -0
  9. package/dist/application/comparisonService.js.map +1 -0
  10. package/dist/application/externalReferencePersistenceService.d.ts +75 -0
  11. package/dist/application/externalReferencePersistenceService.js +182 -0
  12. package/dist/application/externalReferencePersistenceService.js.map +1 -0
  13. package/dist/application/frontendContractEvaluationService.d.ts +49 -0
  14. package/dist/application/frontendContractEvaluationService.js +112 -0
  15. package/dist/application/frontendContractEvaluationService.js.map +1 -0
  16. package/dist/application/frontendContractPersistenceService.d.ts +56 -0
  17. package/dist/application/frontendContractPersistenceService.js +91 -0
  18. package/dist/application/frontendContractPersistenceService.js.map +1 -0
  19. package/dist/application/observationPersistence.d.ts +59 -0
  20. package/dist/application/observationPersistence.js +79 -0
  21. package/dist/application/observationPersistence.js.map +1 -0
  22. package/dist/application/projectCheckService.d.ts +3 -0
  23. package/dist/application/projectCheckService.js +169 -0
  24. package/dist/application/projectCheckService.js.map +1 -0
  25. package/dist/application/projectWorkflowService.d.ts +46 -0
  26. package/dist/application/projectWorkflowService.js +92 -0
  27. package/dist/application/projectWorkflowService.js.map +1 -0
  28. package/dist/application/referenceFidelityEvaluationService.d.ts +28 -0
  29. package/dist/application/referenceFidelityEvaluationService.js +45 -0
  30. package/dist/application/referenceFidelityEvaluationService.js.map +1 -0
  31. package/dist/artifacts/artifactReader.d.ts +19 -0
  32. package/dist/artifacts/artifactReader.js +36 -0
  33. package/dist/artifacts/artifactReader.js.map +1 -0
  34. package/dist/artifacts/artifactWriter.d.ts +25 -0
  35. package/dist/artifacts/artifactWriter.js +68 -0
  36. package/dist/artifacts/artifactWriter.js.map +1 -0
  37. package/dist/artifacts/comparisonArtifactReader.d.ts +18 -0
  38. package/dist/artifacts/comparisonArtifactReader.js +35 -0
  39. package/dist/artifacts/comparisonArtifactReader.js.map +1 -0
  40. package/dist/artifacts/comparisonArtifactWriter.d.ts +41 -0
  41. package/dist/artifacts/comparisonArtifactWriter.js +67 -0
  42. package/dist/artifacts/comparisonArtifactWriter.js.map +1 -0
  43. package/dist/artifacts/externalReferenceArtifactReader.d.ts +18 -0
  44. package/dist/artifacts/externalReferenceArtifactReader.js +35 -0
  45. package/dist/artifacts/externalReferenceArtifactReader.js.map +1 -0
  46. package/dist/artifacts/externalReferenceArtifactWriter.d.ts +44 -0
  47. package/dist/artifacts/externalReferenceArtifactWriter.js +77 -0
  48. package/dist/artifacts/externalReferenceArtifactWriter.js.map +1 -0
  49. package/dist/artifacts/frontendContractArtifactReader.d.ts +24 -0
  50. package/dist/artifacts/frontendContractArtifactReader.js +47 -0
  51. package/dist/artifacts/frontendContractArtifactReader.js.map +1 -0
  52. package/dist/artifacts/frontendContractArtifactWriter.d.ts +34 -0
  53. package/dist/artifacts/frontendContractArtifactWriter.js +70 -0
  54. package/dist/artifacts/frontendContractArtifactWriter.js.map +1 -0
  55. package/dist/artifacts/frontendContractEvaluationArtifactReader.d.ts +17 -0
  56. package/dist/artifacts/frontendContractEvaluationArtifactReader.js +34 -0
  57. package/dist/artifacts/frontendContractEvaluationArtifactReader.js.map +1 -0
  58. package/dist/artifacts/frontendContractEvaluationArtifactWriter.d.ts +32 -0
  59. package/dist/artifacts/frontendContractEvaluationArtifactWriter.js +58 -0
  60. package/dist/artifacts/frontendContractEvaluationArtifactWriter.js.map +1 -0
  61. package/dist/artifacts/types.d.ts +17 -0
  62. package/dist/artifacts/types.js +2 -0
  63. package/dist/artifacts/types.js.map +1 -0
  64. package/dist/browser/chromiumAdapter.d.ts +21 -0
  65. package/dist/browser/chromiumAdapter.js +204 -0
  66. package/dist/browser/chromiumAdapter.js.map +1 -0
  67. package/dist/browser/evidenceCapture.d.ts +62 -0
  68. package/dist/browser/evidenceCapture.js +500 -0
  69. package/dist/browser/evidenceCapture.js.map +1 -0
  70. package/dist/browser/scrollCapture.d.ts +32 -0
  71. package/dist/browser/scrollCapture.js +163 -0
  72. package/dist/browser/scrollCapture.js.map +1 -0
  73. package/dist/browser/types.d.ts +24 -0
  74. package/dist/browser/types.js +2 -0
  75. package/dist/browser/types.js.map +1 -0
  76. package/dist/cli.d.ts +8 -0
  77. package/dist/cli.js +2411 -0
  78. package/dist/cli.js.map +1 -0
  79. package/dist/domain/boundedAgentContext.d.ts +226 -0
  80. package/dist/domain/boundedAgentContext.js +355 -0
  81. package/dist/domain/boundedAgentContext.js.map +1 -0
  82. package/dist/domain/boundedAgentContextCorrelation.d.ts +74 -0
  83. package/dist/domain/boundedAgentContextCorrelation.js +441 -0
  84. package/dist/domain/boundedAgentContextCorrelation.js.map +1 -0
  85. package/dist/domain/boundedAgentContextIdentity.d.ts +26 -0
  86. package/dist/domain/boundedAgentContextIdentity.js +69 -0
  87. package/dist/domain/boundedAgentContextIdentity.js.map +1 -0
  88. package/dist/domain/boundedAgentContextProjection.d.ts +71 -0
  89. package/dist/domain/boundedAgentContextProjection.js +477 -0
  90. package/dist/domain/boundedAgentContextProjection.js.map +1 -0
  91. package/dist/domain/comparison.d.ts +220 -0
  92. package/dist/domain/comparison.js +350 -0
  93. package/dist/domain/comparison.js.map +1 -0
  94. package/dist/domain/comparisonEngine.d.ts +76 -0
  95. package/dist/domain/comparisonEngine.js +734 -0
  96. package/dist/domain/comparisonEngine.js.map +1 -0
  97. package/dist/domain/comparisonIdentity.d.ts +13 -0
  98. package/dist/domain/comparisonIdentity.js +46 -0
  99. package/dist/domain/comparisonIdentity.js.map +1 -0
  100. package/dist/domain/completion.d.ts +30 -0
  101. package/dist/domain/completion.js +22 -0
  102. package/dist/domain/completion.js.map +1 -0
  103. package/dist/domain/diagnostics.d.ts +17 -0
  104. package/dist/domain/diagnostics.js +77 -0
  105. package/dist/domain/diagnostics.js.map +1 -0
  106. package/dist/domain/evidence.d.ts +29 -0
  107. package/dist/domain/evidence.js +59 -0
  108. package/dist/domain/evidence.js.map +1 -0
  109. package/dist/domain/explicitState.d.ts +40 -0
  110. package/dist/domain/explicitState.js +54 -0
  111. package/dist/domain/explicitState.js.map +1 -0
  112. package/dist/domain/externalReference.d.ts +158 -0
  113. package/dist/domain/externalReference.js +167 -0
  114. package/dist/domain/externalReference.js.map +1 -0
  115. package/dist/domain/externalReferenceApplicability.d.ts +43 -0
  116. package/dist/domain/externalReferenceApplicability.js +52 -0
  117. package/dist/domain/externalReferenceApplicability.js.map +1 -0
  118. package/dist/domain/externalReferenceCompatibility.d.ts +40 -0
  119. package/dist/domain/externalReferenceCompatibility.js +48 -0
  120. package/dist/domain/externalReferenceCompatibility.js.map +1 -0
  121. package/dist/domain/externalReferenceFidelity.d.ts +171 -0
  122. package/dist/domain/externalReferenceFidelity.js +419 -0
  123. package/dist/domain/externalReferenceFidelity.js.map +1 -0
  124. package/dist/domain/externalReferenceIdentity.d.ts +38 -0
  125. package/dist/domain/externalReferenceIdentity.js +70 -0
  126. package/dist/domain/externalReferenceIdentity.js.map +1 -0
  127. package/dist/domain/externalReferenceImage.d.ts +35 -0
  128. package/dist/domain/externalReferenceImage.js +160 -0
  129. package/dist/domain/externalReferenceImage.js.map +1 -0
  130. package/dist/domain/externalReferenceRegionRelationships.d.ts +63 -0
  131. package/dist/domain/externalReferenceRegionRelationships.js +98 -0
  132. package/dist/domain/externalReferenceRegionRelationships.js.map +1 -0
  133. package/dist/domain/externalReferenceRegions.d.ts +65 -0
  134. package/dist/domain/externalReferenceRegions.js +105 -0
  135. package/dist/domain/externalReferenceRegions.js.map +1 -0
  136. package/dist/domain/externalReferenceRequirementIdentity.d.ts +12 -0
  137. package/dist/domain/externalReferenceRequirementIdentity.js +35 -0
  138. package/dist/domain/externalReferenceRequirementIdentity.js.map +1 -0
  139. package/dist/domain/externalReferenceRequirements.d.ts +215 -0
  140. package/dist/domain/externalReferenceRequirements.js +401 -0
  141. package/dist/domain/externalReferenceRequirements.js.map +1 -0
  142. package/dist/domain/externalReferenceRuntimeBinding.d.ts +146 -0
  143. package/dist/domain/externalReferenceRuntimeBinding.js +183 -0
  144. package/dist/domain/externalReferenceRuntimeBinding.js.map +1 -0
  145. package/dist/domain/frontendContractEvaluation.d.ts +57 -0
  146. package/dist/domain/frontendContractEvaluation.js +454 -0
  147. package/dist/domain/frontendContractEvaluation.js.map +1 -0
  148. package/dist/domain/frontendContractEvaluationArtifact.d.ts +65 -0
  149. package/dist/domain/frontendContractEvaluationArtifact.js +108 -0
  150. package/dist/domain/frontendContractEvaluationArtifact.js.map +1 -0
  151. package/dist/domain/frontendContractIdentity.d.ts +39 -0
  152. package/dist/domain/frontendContractIdentity.js +70 -0
  153. package/dist/domain/frontendContractIdentity.js.map +1 -0
  154. package/dist/domain/frontendContracts.d.ts +188 -0
  155. package/dist/domain/frontendContracts.js +260 -0
  156. package/dist/domain/frontendContracts.js.map +1 -0
  157. package/dist/domain/identity.d.ts +21 -0
  158. package/dist/domain/identity.js +47 -0
  159. package/dist/domain/identity.js.map +1 -0
  160. package/dist/domain/referenceCorrectionIdentity.d.ts +40 -0
  161. package/dist/domain/referenceCorrectionIdentity.js +77 -0
  162. package/dist/domain/referenceCorrectionIdentity.js.map +1 -0
  163. package/dist/domain/referenceCorrectionWorkflow.d.ts +160 -0
  164. package/dist/domain/referenceCorrectionWorkflow.js +165 -0
  165. package/dist/domain/referenceCorrectionWorkflow.js.map +1 -0
  166. package/dist/domain/referenceFidelityProjection.d.ts +65 -0
  167. package/dist/domain/referenceFidelityProjection.js +135 -0
  168. package/dist/domain/referenceFidelityProjection.js.map +1 -0
  169. package/dist/domain/relationships.d.ts +210 -0
  170. package/dist/domain/relationships.js +352 -0
  171. package/dist/domain/relationships.js.map +1 -0
  172. package/dist/domain/schema.d.ts +269 -0
  173. package/dist/domain/schema.js +442 -0
  174. package/dist/domain/schema.js.map +1 -0
  175. package/dist/domain/scrollEvidence.d.ts +51 -0
  176. package/dist/domain/scrollEvidence.js +134 -0
  177. package/dist/domain/scrollEvidence.js.map +1 -0
  178. package/dist/index.d.ts +114 -0
  179. package/dist/index.js +64 -0
  180. package/dist/index.js.map +1 -0
  181. package/dist/projectWorkflow/aliasCatalog.d.ts +21 -0
  182. package/dist/projectWorkflow/aliasCatalog.js +67 -0
  183. package/dist/projectWorkflow/aliasCatalog.js.map +1 -0
  184. package/dist/projectWorkflow/checkAcceptance.d.ts +25 -0
  185. package/dist/projectWorkflow/checkAcceptance.js +55 -0
  186. package/dist/projectWorkflow/checkAcceptance.js.map +1 -0
  187. package/dist/projectWorkflow/checkResult.d.ts +85 -0
  188. package/dist/projectWorkflow/checkResult.js +101 -0
  189. package/dist/projectWorkflow/checkResult.js.map +1 -0
  190. package/dist/projectWorkflow/projectConfig.d.ts +43 -0
  191. package/dist/projectWorkflow/projectConfig.js +84 -0
  192. package/dist/projectWorkflow/projectConfig.js.map +1 -0
  193. package/dist/projectWorkflow/projectDiscovery.d.ts +9 -0
  194. package/dist/projectWorkflow/projectDiscovery.js +20 -0
  195. package/dist/projectWorkflow/projectDiscovery.js.map +1 -0
  196. package/dist/projectWorkflow/projectPaths.d.ts +8 -0
  197. package/dist/projectWorkflow/projectPaths.js +23 -0
  198. package/dist/projectWorkflow/projectPaths.js.map +1 -0
  199. package/dist/request/paths.d.ts +14 -0
  200. package/dist/request/paths.js +33 -0
  201. package/dist/request/paths.js.map +1 -0
  202. package/dist/request/request.d.ts +111 -0
  203. package/dist/request/request.js +464 -0
  204. package/dist/request/request.js.map +1 -0
  205. package/dist/safety/policy.d.ts +14 -0
  206. package/dist/safety/policy.js +81 -0
  207. package/dist/safety/policy.js.map +1 -0
  208. package/dist/viewer/assets/index-CN_yb9Uf.css +1 -0
  209. package/dist/viewer/assets/index-D98S1_2d.js +9 -0
  210. package/dist/viewer/icons/icon-192.png +0 -0
  211. package/dist/viewer/icons/icon-512.png +0 -0
  212. package/dist/viewer/index.html +15 -0
  213. package/dist/viewer/manifest.webmanifest +1 -0
  214. package/dist/viewer/registerSW.js +1 -0
  215. package/dist/viewer/sw.js +1 -0
  216. package/dist/viewer/workbox-9c191d2f.js +1 -0
  217. package/dist/viewerServer/context.d.ts +48 -0
  218. package/dist/viewerServer/context.js +60 -0
  219. package/dist/viewerServer/context.js.map +1 -0
  220. package/dist/viewerServer/evidence/classify.d.ts +59 -0
  221. package/dist/viewerServer/evidence/classify.js +124 -0
  222. package/dist/viewerServer/evidence/classify.js.map +1 -0
  223. package/dist/viewerServer/evidence/comparisonView.d.ts +28 -0
  224. package/dist/viewerServer/evidence/comparisonView.js +43 -0
  225. package/dist/viewerServer/evidence/comparisonView.js.map +1 -0
  226. package/dist/viewerServer/evidence/contextSourceView.d.ts +25 -0
  227. package/dist/viewerServer/evidence/contextSourceView.js +20 -0
  228. package/dist/viewerServer/evidence/contextSourceView.js.map +1 -0
  229. package/dist/viewerServer/evidence/discovery.d.ts +31 -0
  230. package/dist/viewerServer/evidence/discovery.js +78 -0
  231. package/dist/viewerServer/evidence/discovery.js.map +1 -0
  232. package/dist/viewerServer/evidence/evaluationView.d.ts +32 -0
  233. package/dist/viewerServer/evidence/evaluationView.js +50 -0
  234. package/dist/viewerServer/evidence/evaluationView.js.map +1 -0
  235. package/dist/viewerServer/evidence/handles.d.ts +21 -0
  236. package/dist/viewerServer/evidence/handles.js +43 -0
  237. package/dist/viewerServer/evidence/handles.js.map +1 -0
  238. package/dist/viewerServer/evidence/index.d.ts +41 -0
  239. package/dist/viewerServer/evidence/index.js +82 -0
  240. package/dist/viewerServer/evidence/index.js.map +1 -0
  241. package/dist/viewerServer/evidence/limits.d.ts +27 -0
  242. package/dist/viewerServer/evidence/limits.js +28 -0
  243. package/dist/viewerServer/evidence/limits.js.map +1 -0
  244. package/dist/viewerServer/evidence/linkedEvidence.d.ts +43 -0
  245. package/dist/viewerServer/evidence/linkedEvidence.js +151 -0
  246. package/dist/viewerServer/evidence/linkedEvidence.js.map +1 -0
  247. package/dist/viewerServer/evidence/mediaResolver.d.ts +16 -0
  248. package/dist/viewerServer/evidence/mediaResolver.js +85 -0
  249. package/dist/viewerServer/evidence/mediaResolver.js.map +1 -0
  250. package/dist/viewerServer/evidence/observationView.d.ts +29 -0
  251. package/dist/viewerServer/evidence/observationView.js +46 -0
  252. package/dist/viewerServer/evidence/observationView.js.map +1 -0
  253. package/dist/viewerServer/evidence/pathSafety.d.ts +11 -0
  254. package/dist/viewerServer/evidence/pathSafety.js +31 -0
  255. package/dist/viewerServer/evidence/pathSafety.js.map +1 -0
  256. package/dist/viewerServer/evidence/projection.d.ts +55 -0
  257. package/dist/viewerServer/evidence/projection.js +152 -0
  258. package/dist/viewerServer/evidence/projection.js.map +1 -0
  259. package/dist/viewerServer/evidence/referenceView.d.ts +133 -0
  260. package/dist/viewerServer/evidence/referenceView.js +169 -0
  261. package/dist/viewerServer/evidence/referenceView.js.map +1 -0
  262. package/dist/viewerServer/httpServer.d.ts +27 -0
  263. package/dist/viewerServer/httpServer.js +381 -0
  264. package/dist/viewerServer/httpServer.js.map +1 -0
  265. package/dist/viewerServer/openBrowser.d.ts +7 -0
  266. package/dist/viewerServer/openBrowser.js +32 -0
  267. package/dist/viewerServer/openBrowser.js.map +1 -0
  268. package/dist/viewerServer/port.d.ts +16 -0
  269. package/dist/viewerServer/port.js +19 -0
  270. package/dist/viewerServer/port.js.map +1 -0
  271. package/dist/viewerServer/viewerService.d.ts +62 -0
  272. package/dist/viewerServer/viewerService.js +88 -0
  273. package/dist/viewerServer/viewerService.js.map +1 -0
  274. package/docs/ARCHITECTURE.md +1286 -0
  275. package/docs/CI_CD.md +250 -0
  276. package/docs/COMMANDS.md +972 -0
  277. package/docs/CONTRACTS.md +1856 -0
  278. package/docs/CURRENT_STATE.md +1049 -0
  279. package/docs/DEVELOPMENT.md +202 -0
  280. package/docs/DOCUMENTATION_PRESERVATION_POLICY.md +50 -0
  281. package/docs/PROJECT_DESCRIPTION.md +2221 -0
  282. package/docs/PROJECT_MILESTONES.md +2526 -0
  283. package/docs/PROJECT_OVERVIEW.md +150 -0
  284. package/docs/QUICKSTART.md +83 -0
  285. package/docs/RELEASE.md +27 -0
  286. package/docs/ROADMAP.md +641 -0
  287. package/docs/SECURITY.md +218 -0
  288. package/docs/WORKFLOWS.md +642 -0
  289. package/docs/plans/v0.8-implementation-plan.md +655 -0
  290. package/docs/plans/v0.8.1-cli-usability-patch-plan.md +505 -0
  291. package/docs/reports/v0.7-bounded-fidelity-context-prompt7.md +243 -0
  292. package/docs/reports/v0.7-implementation-completeness-documentation-reconciliation.md +497 -0
  293. package/docs/reports/v0.7-pre-release-readiness.md +337 -0
  294. package/docs/reports/v0.7-reference-binding-prompt5.md +223 -0
  295. package/docs/reports/v0.7-reference-compatibility-prompt4.md +234 -0
  296. package/docs/reports/v0.7-reference-correction-workflow-prompt8.md +222 -0
  297. package/docs/reports/v0.7-reference-fidelity-prompt6.md +216 -0
  298. package/docs/reports/v0.7-reference-foundation-prompt1.md +151 -0
  299. package/docs/reports/v0.7-reference-regions-prompt2.md +195 -0
  300. package/docs/reports/v0.7-reference-requirements-prompt3.md +217 -0
  301. package/docs/reports/v0.7-release-prep.md +423 -0
  302. package/docs/reports/v0.8-binding-fidelity-interaction-batch6.md +279 -0
  303. package/docs/reports/v0.8-bounded-context-correlation-batch7.md +233 -0
  304. package/docs/reports/v0.8-comparison-contract-inspection-batch4.md +279 -0
  305. package/docs/reports/v0.8-evidence-index-readers-batch2.md +247 -0
  306. package/docs/reports/v0.8-implementation-completeness-documentation-reconciliation.md +741 -0
  307. package/docs/reports/v0.8-integrated-viewer-acceptance-batch8.md +128 -0
  308. package/docs/reports/v0.8-observation-svg-inspection-batch3.md +223 -0
  309. package/docs/reports/v0.8-prerelease-readiness-cross-platform-security-code-rot.md +687 -0
  310. package/docs/reports/v0.8-reference-candidate-inspection-batch5.md +232 -0
  311. package/docs/reports/v0.8-viewer-runtime-pwa-batch1.md +278 -0
  312. package/docs/reports/v0.8.1-check-orchestration-prompt2.md +69 -0
  313. package/docs/reports/v0.8.1-implementation-completeness-documentation-reconciliation.md +114 -0
  314. package/docs/reports/v0.8.1-prerelease-readiness-cross-platform-security-code-rot.md +170 -0
  315. package/docs/reports/v0.8.1-project-workflow-foundation-prompt1.md +66 -0
  316. package/package.json +58 -0
@@ -0,0 +1,260 @@
1
+ import { isValidEvidenceReference, PAIRWISE_RELATIONSHIP_KINDS, PAGE_LEVEL_RELATIONSHIP_KINDS } from './relationships.js';
2
+ import { DEPENDENCY_PROPERTIES } from './comparison.js';
3
+ import { PRODUCER_NAME, SCHEMA_VERSION as OBSERVATION_SCHEMA_VERSION } from './schema.js';
4
+ function isPlainObject(value) {
5
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
6
+ }
7
+ function isNonEmptyString(value) {
8
+ return typeof value === 'string' && value.length > 0;
9
+ }
10
+ function isEvidenceReferenceArray(value) {
11
+ return Array.isArray(value) && value.every((entry) => isValidEvidenceReference(entry));
12
+ }
13
+ export const CONTRACT_ARTIFACT_KIND = 'my-frontend-observer/frontend-contract';
14
+ export const CONTRACT_SCHEMA_VERSION = '1.0.0';
15
+ // --- Change-scope vocabulary --------------------------------------------------
16
+ /** The authored per-change contract has exactly these 4 intent categories - `'unexpected'` is never a member. */
17
+ export const AUTHORED_CHANGE_SCOPE_CATEGORIES = ['requested', 'expected-dependent', 'protected', 'preserved'];
18
+ export function isAuthoredChangeScopeCategory(value) {
19
+ return typeof value === 'string' && AUTHORED_CHANGE_SCOPE_CATEGORIES.includes(value);
20
+ }
21
+ /**
22
+ * Full derived classification vocabulary, kept structurally separate from
23
+ * AUTHORED_CHANGE_SCOPE_CATEGORIES - `'unexpected'` is a classification a
24
+ * future evaluator produces, never an authored permission. No function in
25
+ * this module converts between the two vocabularies.
26
+ */
27
+ export const CHANGE_SCOPE_CLASSIFICATIONS = [...AUTHORED_CHANGE_SCOPE_CATEGORIES, 'unexpected'];
28
+ export const EXPECTED_DEPENDENT_MODES = ['required', 'permitted'];
29
+ export function isValidExpectedDependentMode(value) {
30
+ return typeof value === 'string' && EXPECTED_DEPENDENT_MODES.includes(value);
31
+ }
32
+ // --- Contract tolerance (bounded, closed - never a generic expression) -------
33
+ /** Independently declared from GEOMETRY_TOLERANCE_*_PX (src/domain/relationships.ts): comparison tolerance suppresses insignificant geometry noise and is never contract authorization. */
34
+ export const CONTRACT_TOLERANCE_ABSOLUTE_PX_MIN = 0;
35
+ export const CONTRACT_TOLERANCE_ABSOLUTE_PX_MAX = 100;
36
+ export const CONTRACT_TOLERANCE_PERCENT_MIN = 0;
37
+ export const CONTRACT_TOLERANCE_PERCENT_MAX = 100;
38
+ export function isValidContractTolerance(value) {
39
+ if (!isPlainObject(value))
40
+ return false;
41
+ if (value.kind === 'exact')
42
+ return Object.keys(value).length === 1;
43
+ if (value.kind === 'absolute-px') {
44
+ return (typeof value.amount === 'number' &&
45
+ Number.isFinite(value.amount) &&
46
+ value.amount >= CONTRACT_TOLERANCE_ABSOLUTE_PX_MIN &&
47
+ value.amount <= CONTRACT_TOLERANCE_ABSOLUTE_PX_MAX);
48
+ }
49
+ if (value.kind === 'percent') {
50
+ return (typeof value.amount === 'number' &&
51
+ Number.isFinite(value.amount) &&
52
+ value.amount >= CONTRACT_TOLERANCE_PERCENT_MIN &&
53
+ value.amount <= CONTRACT_TOLERANCE_PERCENT_MAX);
54
+ }
55
+ return false;
56
+ }
57
+ // --- Contract primitive vocabulary (bounded, closed) --------------------------
58
+ /** Every contract primitive kind this batch freezes - deliberately bounded, never a generic rule/expression language. */
59
+ export const CONTRACT_PRIMITIVE_KINDS = [
60
+ 'target-visible',
61
+ 'target-not-clipped',
62
+ 'target-width-within-bound',
63
+ 'targets-do-not-overlap',
64
+ 'target-wider-than',
65
+ 'target-follows-vertically',
66
+ 'target-fits-inside',
67
+ 'document-width-fits-viewport',
68
+ 'scroll-owner-is-document',
69
+ 'target-does-not-own-scroll',
70
+ 'target-begins-below-initial-viewport',
71
+ 'relationship-unchanged',
72
+ 'property-unchanged-within-tolerance',
73
+ 'property-increases',
74
+ 'property-decreases',
75
+ ];
76
+ const ALL_RELATIONSHIP_KINDS = [...PAIRWISE_RELATIONSHIP_KINDS, ...PAGE_LEVEL_RELATIONSHIP_KINDS];
77
+ function isOptionalFiniteNumber(value) {
78
+ return value === undefined || (typeof value === 'number' && Number.isFinite(value));
79
+ }
80
+ function isOptionalNonNegativeFiniteNumber(value) {
81
+ return value === undefined || (typeof value === 'number' && Number.isFinite(value) && value >= 0);
82
+ }
83
+ /** Rejects extra keys beyond the given allowlist, keeping every ContractPrimitive variant a closed shape rather than an open bag of fields. */
84
+ function hasOnlyKeys(value, allowedKeys) {
85
+ return Object.keys(value).every((key) => allowedKeys.includes(key));
86
+ }
87
+ export function isValidContractPrimitive(value) {
88
+ if (!isPlainObject(value) || typeof value.kind !== 'string')
89
+ return false;
90
+ switch (value.kind) {
91
+ case 'target-visible':
92
+ return hasOnlyKeys(value, ['kind', 'target']) && isNonEmptyString(value.target);
93
+ case 'target-not-clipped':
94
+ return (hasOnlyKeys(value, ['kind', 'target', 'axis']) &&
95
+ isNonEmptyString(value.target) &&
96
+ (value.axis === undefined || value.axis === 'horizontal' || value.axis === 'vertical' || value.axis === 'both'));
97
+ case 'target-width-within-bound': {
98
+ if (!hasOnlyKeys(value, ['kind', 'target', 'minPx', 'maxPx']))
99
+ return false;
100
+ if (!isNonEmptyString(value.target))
101
+ return false;
102
+ if (!isOptionalFiniteNumber(value.minPx) || !isOptionalFiniteNumber(value.maxPx))
103
+ return false;
104
+ if (value.minPx === undefined && value.maxPx === undefined)
105
+ return false;
106
+ if (typeof value.minPx === 'number' && typeof value.maxPx === 'number' && value.minPx > value.maxPx)
107
+ return false;
108
+ return true;
109
+ }
110
+ case 'targets-do-not-overlap':
111
+ case 'target-wider-than':
112
+ case 'target-follows-vertically':
113
+ return (hasOnlyKeys(value, ['kind', 'targetA', 'targetB']) &&
114
+ isNonEmptyString(value.targetA) &&
115
+ isNonEmptyString(value.targetB) &&
116
+ value.targetA !== value.targetB);
117
+ case 'target-fits-inside':
118
+ return (hasOnlyKeys(value, ['kind', 'target', 'container']) &&
119
+ isNonEmptyString(value.target) &&
120
+ isNonEmptyString(value.container) &&
121
+ value.target !== value.container);
122
+ case 'document-width-fits-viewport':
123
+ case 'scroll-owner-is-document':
124
+ return hasOnlyKeys(value, ['kind']) && Object.keys(value).length === 1;
125
+ case 'target-does-not-own-scroll':
126
+ case 'target-begins-below-initial-viewport':
127
+ return hasOnlyKeys(value, ['kind', 'target']) && isNonEmptyString(value.target);
128
+ case 'relationship-unchanged':
129
+ return (hasOnlyKeys(value, ['kind', 'relationshipKind', 'subjectTarget', 'relatedTarget']) &&
130
+ typeof value.relationshipKind === 'string' &&
131
+ ALL_RELATIONSHIP_KINDS.includes(value.relationshipKind) &&
132
+ (value.subjectTarget === undefined || typeof value.subjectTarget === 'string') &&
133
+ (value.relatedTarget === undefined || typeof value.relatedTarget === 'string'));
134
+ case 'property-unchanged-within-tolerance':
135
+ return (hasOnlyKeys(value, ['kind', 'target', 'property', 'tolerance']) &&
136
+ isNonEmptyString(value.target) &&
137
+ typeof value.property === 'string' &&
138
+ DEPENDENCY_PROPERTIES.includes(value.property) &&
139
+ isValidContractTolerance(value.tolerance));
140
+ case 'property-increases':
141
+ case 'property-decreases':
142
+ return (hasOnlyKeys(value, ['kind', 'target', 'property', 'minimumDeltaPx']) &&
143
+ isNonEmptyString(value.target) &&
144
+ typeof value.property === 'string' &&
145
+ DEPENDENCY_PROPERTIES.includes(value.property) &&
146
+ isOptionalNonNegativeFiniteNumber(value.minimumDeltaPx));
147
+ default:
148
+ return false;
149
+ }
150
+ }
151
+ export function isValidBaselineClause(value) {
152
+ if (!isPlainObject(value))
153
+ return false;
154
+ return isNonEmptyString(value.clauseId) && isValidContractPrimitive(value.primitive) && isEvidenceReferenceArray(value.supportingEvidence);
155
+ }
156
+ export function isValidPerChangeClause(value) {
157
+ if (!isPlainObject(value))
158
+ return false;
159
+ if (!isValidBaselineClause(value))
160
+ return false;
161
+ const record = value;
162
+ if (!isAuthoredChangeScopeCategory(record.category))
163
+ return false;
164
+ const hasMode = 'expectedDependentMode' in record && record.expectedDependentMode !== undefined;
165
+ if (record.category === 'expected-dependent') {
166
+ if (!hasMode || !isValidExpectedDependentMode(record.expectedDependentMode))
167
+ return false;
168
+ }
169
+ else if (hasMode) {
170
+ return false;
171
+ }
172
+ if ('supersedesBaselineClauseIds' in record && record.supersedesBaselineClauseIds !== undefined) {
173
+ const ids = record.supersedesBaselineClauseIds;
174
+ if (!Array.isArray(ids) || ids.length === 0)
175
+ return false;
176
+ if (!ids.every((id) => isNonEmptyString(id)))
177
+ return false;
178
+ }
179
+ return true;
180
+ }
181
+ export function isValidFrontendContractObservationReference(value) {
182
+ if (!isPlainObject(value))
183
+ return false;
184
+ if (!isNonEmptyString(value.observationId) || !isNonEmptyString(value.requestId))
185
+ return false;
186
+ if (!isPlainObject(value.producer) || value.producer.name !== PRODUCER_NAME || !isNonEmptyString(value.producer.version))
187
+ return false;
188
+ return value.observationSchemaVersion === OBSERVATION_SCHEMA_VERSION;
189
+ }
190
+ export function isValidPersistentBaselineContract(value) {
191
+ if (!isPlainObject(value))
192
+ return { valid: false, reason: 'contract must be an object' };
193
+ if (value.artifactKind !== CONTRACT_ARTIFACT_KIND)
194
+ return { valid: false, reason: 'artifactKind mismatch' };
195
+ if (value.schemaVersion !== CONTRACT_SCHEMA_VERSION)
196
+ return { valid: false, reason: 'schemaVersion mismatch' };
197
+ if (value.contractClass !== 'baseline')
198
+ return { valid: false, reason: 'contractClass must be "baseline"' };
199
+ if (!isNonEmptyString(value.baselineId))
200
+ return { valid: false, reason: 'baselineId must be a non-empty string' };
201
+ if ('supersedesBaselineId' in value && value.supersedesBaselineId !== undefined && !isNonEmptyString(value.supersedesBaselineId)) {
202
+ return { valid: false, reason: 'supersedesBaselineId must be a non-empty string when present' };
203
+ }
204
+ if (!isValidFrontendContractObservationReference(value.sourceObservation))
205
+ return { valid: false, reason: 'sourceObservation is invalid' };
206
+ if (!Array.isArray(value.clauses) || !value.clauses.every((c) => isValidBaselineClause(c))) {
207
+ return { valid: false, reason: 'clauses must be an array of valid BaselineClause values' };
208
+ }
209
+ if (!isPlainObject(value.provenance) || !isNonEmptyString(value.provenance.approvedAt)) {
210
+ return { valid: false, reason: 'provenance.approvedAt must be a non-empty string' };
211
+ }
212
+ return { valid: true };
213
+ }
214
+ export function isValidPerChangeContract(value) {
215
+ if (!isPlainObject(value))
216
+ return { valid: false, reason: 'contract must be an object' };
217
+ if (value.artifactKind !== CONTRACT_ARTIFACT_KIND)
218
+ return { valid: false, reason: 'artifactKind mismatch' };
219
+ if (value.schemaVersion !== CONTRACT_SCHEMA_VERSION)
220
+ return { valid: false, reason: 'schemaVersion mismatch' };
221
+ if (value.contractClass !== 'change')
222
+ return { valid: false, reason: 'contractClass must be "change"' };
223
+ if (!isNonEmptyString(value.contractId))
224
+ return { valid: false, reason: 'contractId must be a non-empty string' };
225
+ if (!isNonEmptyString(value.contractRequestId))
226
+ return { valid: false, reason: 'contractRequestId must be a non-empty string' };
227
+ if (!Array.isArray(value.activeBaselineIds) || !value.activeBaselineIds.every((id) => isNonEmptyString(id))) {
228
+ return { valid: false, reason: 'activeBaselineIds must be an array of non-empty strings' };
229
+ }
230
+ if (!Array.isArray(value.clauses) || !value.clauses.every((c) => isValidPerChangeClause(c))) {
231
+ return { valid: false, reason: 'clauses must be an array of valid PerChangeClause values' };
232
+ }
233
+ return { valid: true };
234
+ }
235
+ // --- Per-clause evaluation result vocabulary (frozen vocabulary only; no producer in this batch) --
236
+ export const CLAUSE_RESULT_STATUSES = ['pass', 'fail', 'unavailable', 'conflict'];
237
+ /** Honest per-clause result vocabulary: `'unavailable'` requires a non-empty reason (never fabricated pass/fail); `'conflict'` requires at least 2 conflicting clause ids. */
238
+ export function isValidClauseEvaluationResult(value) {
239
+ if (!isPlainObject(value) || !isNonEmptyString(value.clauseId))
240
+ return false;
241
+ if (!isEvidenceReferenceArray(value.supportingEvidence))
242
+ return false;
243
+ switch (value.status) {
244
+ case 'pass':
245
+ case 'fail':
246
+ return !('reason' in value) && !('conflictingClauseIds' in value);
247
+ case 'unavailable':
248
+ return isNonEmptyString(value.reason) && !('conflictingClauseIds' in value);
249
+ case 'conflict':
250
+ return (isNonEmptyString(value.reason) &&
251
+ Array.isArray(value.conflictingClauseIds) &&
252
+ value.conflictingClauseIds.length >= 2 &&
253
+ value.conflictingClauseIds.every((id) => isNonEmptyString(id)));
254
+ default:
255
+ return false;
256
+ }
257
+ }
258
+ // --- Overall verdict vocabulary (type only; no producer in this batch) -----------
259
+ export const OVERALL_VERDICTS = ['PASS', 'FAIL'];
260
+ //# sourceMappingURL=frontendContracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontendContracts.js","sourceRoot":"","sources":["../../src/domain/frontendContracts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { NormalizedObservationRequest } from '../request/request.js';
2
+ /**
3
+ * Pure function of {targetUrl, viewport, targets (order preserved -
4
+ * semantic), readiness.condition, scrollScenario, explicitState} only.
5
+ * timeoutMs, readiness.timeoutMs, and outputLocation never affect the
6
+ * result - this is the frozen definition of "same configuration" for this
7
+ * batch. A request with no `scrollScenario`/`explicitState` omits the key
8
+ * entirely (rather than setting it to `undefined`) so the identity for a
9
+ * request missing either is unchanged by the batch that introduced it (v0.3
10
+ * for scrollScenario, v0.7 Prompt 4 for explicitState). Only the requested
11
+ * action configuration participates - never runtime scroll results,
12
+ * movement success/failure, or scroll-owner interpretation, which are
13
+ * runtime evidence, not identity; likewise `explicitState` is the
14
+ * caller-declared state identity only, never browser-observed evidence.
15
+ */
16
+ export declare function buildRequestIdentity(request: NormalizedObservationRequest): string;
17
+ /**
18
+ * Fresh, opaque per-call identity - never derived from capturedAt/Date.now(),
19
+ * never collides even when called twice within the same millisecond.
20
+ */
21
+ export declare function buildObservationIdentity(requestIdentity: string): string;
@@ -0,0 +1,47 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ function canonicalize(value) {
3
+ if (Array.isArray(value))
4
+ return value.map(canonicalize);
5
+ if (value !== null && typeof value === 'object') {
6
+ const entries = Object.entries(value)
7
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
8
+ .map(([key, entryValue]) => [key, canonicalize(entryValue)]);
9
+ return Object.fromEntries(entries);
10
+ }
11
+ return value;
12
+ }
13
+ /**
14
+ * Pure function of {targetUrl, viewport, targets (order preserved -
15
+ * semantic), readiness.condition, scrollScenario, explicitState} only.
16
+ * timeoutMs, readiness.timeoutMs, and outputLocation never affect the
17
+ * result - this is the frozen definition of "same configuration" for this
18
+ * batch. A request with no `scrollScenario`/`explicitState` omits the key
19
+ * entirely (rather than setting it to `undefined`) so the identity for a
20
+ * request missing either is unchanged by the batch that introduced it (v0.3
21
+ * for scrollScenario, v0.7 Prompt 4 for explicitState). Only the requested
22
+ * action configuration participates - never runtime scroll results,
23
+ * movement success/failure, or scroll-owner interpretation, which are
24
+ * runtime evidence, not identity; likewise `explicitState` is the
25
+ * caller-declared state identity only, never browser-observed evidence.
26
+ */
27
+ export function buildRequestIdentity(request) {
28
+ const semanticView = {
29
+ targetUrl: request.targetUrl,
30
+ viewport: { width: request.viewport.width, height: request.viewport.height },
31
+ targets: request.targets.map((target) => ({ name: target.name.toLowerCase(), locators: target.locators })),
32
+ readinessCondition: request.readiness.condition,
33
+ ...(request.scrollScenario ? { scrollScenario: request.scrollScenario } : {}),
34
+ ...(request.explicitState ? { explicitState: request.explicitState } : {}),
35
+ };
36
+ const serialized = JSON.stringify(canonicalize(semanticView));
37
+ return createHash('sha256').update(serialized).digest('hex');
38
+ }
39
+ /**
40
+ * Fresh, opaque per-call identity - never derived from capturedAt/Date.now(),
41
+ * never collides even when called twice within the same millisecond.
42
+ */
43
+ export function buildObservationIdentity(requestIdentity) {
44
+ const nonce = randomBytes(16).toString('hex');
45
+ return `${requestIdentity}-${nonce}`;
46
+ }
47
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/domain/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGtD,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC;aAC7D,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAChD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,UAAU,CAAC,CAAU,CAAC,CAAC;QACxE,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAqC;IACxE,MAAM,YAAY,GAAG;QACnB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE;QAC5E,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC1G,kBAAkB,EAAE,OAAO,CAAC,SAAS,CAAC,SAAS;QAC/C,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3E,CAAC;IACF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9D,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,eAAuB;IAC9D,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,OAAO,GAAG,eAAe,IAAI,KAAK,EAAE,CAAC;AACvC,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { ReferenceRuntimeBindingDeclaration } from './externalReferenceRuntimeBinding.js';
2
+ import type { BaselineClause, PerChangeClause } from './frontendContracts.js';
3
+ /**
4
+ * Pure function of {referenceRequestId, baselineObservationId,
5
+ * baselineContractId, baselineContractClauses, changeContractId,
6
+ * changeContractClauses, bindingDeclarations} only - never a timestamp,
7
+ * never an operational file path.
8
+ *
9
+ * Includes each contract's own authored `clauses` content, not merely its
10
+ * caller-authored `baselineId`/`contractId` label: unlike this repository's
11
+ * content-derived identities elsewhere (e.g. `ObservationArtifact.observationId`),
12
+ * `PersistentBaselineContract.baselineId`/`PerChangeContract.contractId` are
13
+ * plain author-supplied strings (see `frontendContractPersistenceService.ts`
14
+ * - `approveAndPersistBaseline` persists `contract.baselineId` verbatim,
15
+ * never recomputing it from `clauses`), so two structurally valid contracts
16
+ * could in principle share the same id while authoring different clauses.
17
+ * Hashing clause content directly closes that gap: a caller cannot silently
18
+ * swap in a same-id baseline/per-change contract with different clauses
19
+ * between attempts of the same logical review without `reviewRequestId`
20
+ * changing, which `reviewReferenceCorrectionAttempt`'s own coherence check
21
+ * (recomputing this same hash and rejecting a mismatch) then catches.
22
+ *
23
+ * Two preparation calls over the same approved reference, the same approved
24
+ * baseline observation, the same active baseline/per-change contracts
25
+ * (id *and* clause content), and the same binding declarations always
26
+ * identify the same logical correction review, regardless of which
27
+ * filesystem locations those artifacts were read from.
28
+ */
29
+ export declare function buildReferenceCorrectionReviewIdentity(referenceRequestId: string, baselineObservationId: string, baselineContractId: string, baselineContractClauses: readonly BaselineClause[], changeContractId: string, changeContractClauses: readonly PerChangeClause[], bindingDeclarations: readonly ReferenceRuntimeBindingDeclaration[]): string;
30
+ /**
31
+ * Pure, deterministic function of {reviewRequestId, candidateObservationId}
32
+ * only - deliberately never a fresh random nonce. Every candidate
33
+ * observation already carries its own fresh, collision-resistant instance
34
+ * identity (see domain/identity.ts#buildObservationIdentity), so hashing it
35
+ * together with the review it was captured for gives an attempt identity
36
+ * that is both stable/reproducible (the same review+candidate pair always
37
+ * yields the same attemptId) and guaranteed distinct per real capture
38
+ * (never a timestamp, never reused across two different candidates).
39
+ */
40
+ export declare function buildReferenceCorrectionAttemptIdentity(reviewRequestId: string, candidateObservationId: string): string;
@@ -0,0 +1,77 @@
1
+ import { createHash } from 'node:crypto';
2
+ /**
3
+ * Deliberately duplicated from domain/identity.ts#canonicalize (and its
4
+ * other per-module duplicates) rather than imported - each identity module
5
+ * owns its own private canonicalize per existing repository convention.
6
+ * Same algorithm (sorted object keys, order-preserving arrays).
7
+ */
8
+ function canonicalize(value) {
9
+ if (Array.isArray(value))
10
+ return value.map(canonicalize);
11
+ if (value !== null && typeof value === 'object') {
12
+ const entries = Object.entries(value)
13
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
14
+ .map(([key, entryValue]) => [key, canonicalize(entryValue)]);
15
+ return Object.fromEntries(entries);
16
+ }
17
+ return value;
18
+ }
19
+ /** Authored binding order is semantic (mirrors every other identity function in this repository's treatment of authored collections) - never sorted away. */
20
+ function bindingSemanticView(declarations) {
21
+ return declarations.map((d) => ({ referenceRegion: d.referenceRegion, runtimeTarget: d.runtimeTarget }));
22
+ }
23
+ /**
24
+ * Pure function of {referenceRequestId, baselineObservationId,
25
+ * baselineContractId, baselineContractClauses, changeContractId,
26
+ * changeContractClauses, bindingDeclarations} only - never a timestamp,
27
+ * never an operational file path.
28
+ *
29
+ * Includes each contract's own authored `clauses` content, not merely its
30
+ * caller-authored `baselineId`/`contractId` label: unlike this repository's
31
+ * content-derived identities elsewhere (e.g. `ObservationArtifact.observationId`),
32
+ * `PersistentBaselineContract.baselineId`/`PerChangeContract.contractId` are
33
+ * plain author-supplied strings (see `frontendContractPersistenceService.ts`
34
+ * - `approveAndPersistBaseline` persists `contract.baselineId` verbatim,
35
+ * never recomputing it from `clauses`), so two structurally valid contracts
36
+ * could in principle share the same id while authoring different clauses.
37
+ * Hashing clause content directly closes that gap: a caller cannot silently
38
+ * swap in a same-id baseline/per-change contract with different clauses
39
+ * between attempts of the same logical review without `reviewRequestId`
40
+ * changing, which `reviewReferenceCorrectionAttempt`'s own coherence check
41
+ * (recomputing this same hash and rejecting a mismatch) then catches.
42
+ *
43
+ * Two preparation calls over the same approved reference, the same approved
44
+ * baseline observation, the same active baseline/per-change contracts
45
+ * (id *and* clause content), and the same binding declarations always
46
+ * identify the same logical correction review, regardless of which
47
+ * filesystem locations those artifacts were read from.
48
+ */
49
+ export function buildReferenceCorrectionReviewIdentity(referenceRequestId, baselineObservationId, baselineContractId, baselineContractClauses, changeContractId, changeContractClauses, bindingDeclarations) {
50
+ const semanticView = {
51
+ referenceRequestId,
52
+ baselineObservationId,
53
+ baselineContractId,
54
+ baselineContractClauses,
55
+ changeContractId,
56
+ changeContractClauses,
57
+ bindings: bindingSemanticView(bindingDeclarations),
58
+ };
59
+ const serialized = JSON.stringify(canonicalize(semanticView));
60
+ return createHash('sha256').update(serialized).digest('hex');
61
+ }
62
+ /**
63
+ * Pure, deterministic function of {reviewRequestId, candidateObservationId}
64
+ * only - deliberately never a fresh random nonce. Every candidate
65
+ * observation already carries its own fresh, collision-resistant instance
66
+ * identity (see domain/identity.ts#buildObservationIdentity), so hashing it
67
+ * together with the review it was captured for gives an attempt identity
68
+ * that is both stable/reproducible (the same review+candidate pair always
69
+ * yields the same attemptId) and guaranteed distinct per real capture
70
+ * (never a timestamp, never reused across two different candidates).
71
+ */
72
+ export function buildReferenceCorrectionAttemptIdentity(reviewRequestId, candidateObservationId) {
73
+ const semanticView = { reviewRequestId, candidateObservationId };
74
+ const serialized = JSON.stringify(canonicalize(semanticView));
75
+ return createHash('sha256').update(serialized).digest('hex');
76
+ }
77
+ //# sourceMappingURL=referenceCorrectionIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"referenceCorrectionIdentity.js","sourceRoot":"","sources":["../../src/domain/referenceCorrectionIdentity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC;aAC7D,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAChD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,UAAU,CAAC,CAAU,CAAC,CAAC;QACxE,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,6JAA6J;AAC7J,SAAS,mBAAmB,CAAC,YAA2D;IACtF,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,eAAe,EAAE,aAAa,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;AAC3G,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,sCAAsC,CACpD,kBAA0B,EAC1B,qBAA6B,EAC7B,kBAA0B,EAC1B,uBAAkD,EAClD,gBAAwB,EACxB,qBAAiD,EACjD,mBAAkE;IAElE,MAAM,YAAY,GAAG;QACnB,kBAAkB;QAClB,qBAAqB;QACrB,kBAAkB;QAClB,uBAAuB;QACvB,gBAAgB;QAChB,qBAAqB;QACrB,QAAQ,EAAE,mBAAmB,CAAC,mBAAmB,CAAC;KACnD,CAAC;IACF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9D,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uCAAuC,CAAC,eAAuB,EAAE,sBAA8B;IAC7G,MAAM,YAAY,GAAG,EAAE,eAAe,EAAE,sBAAsB,EAAE,CAAC;IACjE,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9D,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * v0.7 Prompt 8 controlled end-to-end external-reference coding-agent
3
+ * correction workflow coordinator. This module composes the already-
4
+ * existing, independently-owned Prompt 1-7 and v0.1/v0.4/v0.5/v0.6 engines
5
+ * into two pure operations - `prepareReferenceCorrection` (produce a
6
+ * bounded coding-agent handoff from the current, pre-change state) and
7
+ * `reviewReferenceCorrectionAttempt` (compose one candidate's overall PASS/
8
+ * FAIL after an external actor has edited target source) - without
9
+ * reimplementing, recomputing, or duplicating any of them:
10
+ *
11
+ * - reference structural/lifecycle rules: `domain/externalReference.ts` (Prompt 1)
12
+ * - reference regions/relationships: `domain/externalReferenceRegions*.ts` (Prompt 2)
13
+ * - selected requirements/tolerances/adequacy: `domain/externalReferenceRequirements.ts` (Prompt 3)
14
+ * - reference/candidate compatibility: `domain/externalReferenceCompatibility.ts` (Prompt 4)
15
+ * - reference-region <-> runtime-target binding: `domain/externalReferenceRuntimeBinding.ts` (Prompt 5)
16
+ * - reference fidelity evaluation: `domain/externalReferenceFidelity.ts` (Prompt 6)
17
+ * - bounded fidelity/runtime/static context: `domain/referenceFidelityProjection.ts` +
18
+ * `domain/boundedAgentContextProjection.ts` (Prompt 7)
19
+ * - runtime baseline-vs-candidate comparison: `domain/comparisonEngine.ts` (v0.4)
20
+ * - baseline/per-change contract evaluation: `domain/frontendContractEvaluation.ts` (v0.5)
21
+ *
22
+ * This module owns only: reading which of those already-computed results
23
+ * says what, composing one honest overall result, and giving the external
24
+ * implementation actor a bounded, traceable handoff. It never edits target
25
+ * source, never launches a browser, never calls a remote AI provider, never
26
+ * persists anything, and never auto-approves a baseline or a reference -
27
+ * approval remains the caller's own separate, explicit action via the
28
+ * existing `approveAndPersistBaseline`/`approveExternalReference` owners.
29
+ */
30
+ import type { ExternalReferenceArtifact } from './externalReference.js';
31
+ import type { ObservationArtifact } from './schema.js';
32
+ import type { PersistentBaselineContract, PerChangeContract } from './frontendContracts.js';
33
+ import type { ComparisonArtifact, ComparisonConfig } from './comparison.js';
34
+ import type { FrontendContractEvaluationResult } from './frontendContractEvaluation.js';
35
+ import type { ReferenceRuntimeBindingDeclaration } from './externalReferenceRuntimeBinding.js';
36
+ import type { ReferenceCandidateFidelityEvaluation } from './externalReferenceFidelity.js';
37
+ import type { BoundedAgentContextArtifact, ProjectionProfile } from './boundedAgentContext.js';
38
+ interface CommonInput {
39
+ reference: ExternalReferenceArtifact;
40
+ baselineObservation: ObservationArtifact;
41
+ baselineContract: PersistentBaselineContract;
42
+ changeContract: PerChangeContract;
43
+ bindingDeclarations: readonly ReferenceRuntimeBindingDeclaration[];
44
+ }
45
+ export interface PrepareReferenceCorrectionInput extends CommonInput {
46
+ /** The current, pre-change candidate observation fidelity is measured against. For the canonical proof this is the approved baseline observation itself (see docs/CONTRACTS.md "v0.7 Prompt 8"); a caller may supply a distinct current-state observation only when its own architecture justifies that distinction. */
47
+ currentObservation: ObservationArtifact;
48
+ generatedAt: string;
49
+ producerVersion: string;
50
+ projectionProfile: ProjectionProfile;
51
+ fidelityGeometryTolerancePx?: number;
52
+ }
53
+ export type PrepareReferenceCorrectionStatus = 'handoff-ready' | 'blocked-not-evaluated';
54
+ /**
55
+ * The concrete, machine-readable, human-inspectable handoff boundary the
56
+ * external implementation actor receives. Carries no raw image bytes, no
57
+ * full `ObservationArtifact`/`ExternalReferenceArtifact` payload, and no
58
+ * source excerpt - only stable identities plus the already-bounded Prompt 7
59
+ * projection (which itself already carries the actionable fidelity
60
+ * mismatches, protected/preserved context, and - when the caller supplied
61
+ * it - runtime/static correlation).
62
+ */
63
+ export interface ReferenceCorrectionHandoff {
64
+ reviewRequestId: string;
65
+ referenceId: string;
66
+ referenceRequestId: string;
67
+ baselineObservationId: string;
68
+ currentObservationId: string;
69
+ boundedContext: BoundedAgentContextArtifact;
70
+ /** Human-readable statement of what will be re-checked after the external actor edits source - never "make it look like the screenshot". */
71
+ verificationPlan: string[];
72
+ }
73
+ export type PrepareReferenceCorrectionResult = {
74
+ ok: true;
75
+ status: 'handoff-ready';
76
+ reviewRequestId: string;
77
+ fidelity: ReferenceCandidateFidelityEvaluation;
78
+ handoff: ReferenceCorrectionHandoff;
79
+ } | {
80
+ ok: true;
81
+ status: 'blocked-not-evaluated';
82
+ reviewRequestId: string;
83
+ fidelity: ReferenceCandidateFidelityEvaluation;
84
+ } | {
85
+ ok: false;
86
+ reason: string;
87
+ };
88
+ /**
89
+ * Pure and synchronous: no browser, no filesystem, no network, no remote AI
90
+ * call. Evaluates the approved reference against the supplied current
91
+ * (pre-change) observation via Prompt 6, then - only when that evaluation
92
+ * actually produced a result (`state !== 'not-evaluated'`) - projects it
93
+ * into a bounded coding-agent context via Prompt 7/v0.6 and returns the
94
+ * handoff. A `not-evaluated` fidelity (inadequate reference, or reference/
95
+ * candidate incompatible state) is reported honestly as `blocked-not-
96
+ * evaluated`, carrying the full Prompt 6 result for inspection, but never a
97
+ * fabricated handoff that pretends evidence is adequate.
98
+ */
99
+ export declare function prepareReferenceCorrection(input: PrepareReferenceCorrectionInput): PrepareReferenceCorrectionResult;
100
+ export declare const REFERENCE_CORRECTION_OVERALL_STATES: readonly ["not-evaluated", "pass", "fail"];
101
+ export type ReferenceCorrectionOverallState = (typeof REFERENCE_CORRECTION_OVERALL_STATES)[number];
102
+ export interface ReviewReferenceCorrectionAttemptInput extends CommonInput {
103
+ reviewRequestId: string;
104
+ /** The fresh, newly-captured candidate observation (never the baseline itself, never a prior attempt's candidate) to evaluate. */
105
+ candidateObservation: ObservationArtifact;
106
+ /** The immediately-preceding attempt's identity, if this is a correction re-attempt - carried through purely for traceability, never used to alter this attempt's own evaluation (every attempt always compares against the same approved baseline, never attempt-to-attempt). */
107
+ priorAttemptId?: string;
108
+ comparisonConfig?: Partial<ComparisonConfig>;
109
+ fidelityGeometryTolerancePx?: number;
110
+ }
111
+ /**
112
+ * One fully composed, inspectable review attempt. `overallState` is
113
+ * `'pass'` only when both `fidelity.state === 'pass'` and
114
+ * `contractEvaluation.overallVerdict === 'PASS'`; it is `'not-evaluated'`
115
+ * exactly when Prompt 6's own fidelity evaluation could not run at all
116
+ * (preserved, never collapsed into an ordinary FAIL); otherwise `'fail'` -
117
+ * this covers a structurally-incomparable baseline/candidate pair too,
118
+ * since v0.5's own `evaluateFrontendContract` already reports `'FAIL'`
119
+ * (never `'PASS'`) for that case, per its own established precedent, which
120
+ * this workflow reuses rather than re-deciding. `approvalEligible` is
121
+ * `true` only when `overallState === 'pass'` - it is never itself an
122
+ * approval action; the caller must still invoke the existing explicit
123
+ * `approveAndPersistBaseline`/`approveExternalReference` owners separately.
124
+ */
125
+ export interface ReferenceCorrectionAttemptResult {
126
+ reviewRequestId: string;
127
+ attemptId: string;
128
+ priorAttemptId?: string;
129
+ referenceId: string;
130
+ referenceRequestId: string;
131
+ baselineObservationId: string;
132
+ candidateObservationId: string;
133
+ comparison: ComparisonArtifact;
134
+ fidelity: ReferenceCandidateFidelityEvaluation;
135
+ contractEvaluation: FrontendContractEvaluationResult;
136
+ overallState: ReferenceCorrectionOverallState;
137
+ approvalEligible: boolean;
138
+ }
139
+ export type ReviewReferenceCorrectionAttemptResult = {
140
+ ok: true;
141
+ attempt: ReferenceCorrectionAttemptResult;
142
+ } | {
143
+ ok: false;
144
+ reason: string;
145
+ };
146
+ /**
147
+ * Pure and synchronous: no browser, no filesystem, no network, no remote AI
148
+ * call, no source access. Consumes exactly one already-captured candidate
149
+ * `ObservationArtifact` (the caller is responsible for capturing it through
150
+ * the existing real-Chromium observation pipeline after the external actor
151
+ * has edited target source) and composes the canonical v0.4 comparison,
152
+ * v0.7 Prompt 6 fidelity, and v0.5 contract evaluation into one overall
153
+ * result - reimplementing none of them. Every attempt evaluates the
154
+ * candidate against the *same* supplied `baselineObservation`/
155
+ * `baselineContract`/`changeContract` - this function has no mechanism to
156
+ * compare against a prior attempt's candidate instead, so accumulated
157
+ * drift from the approved baseline can never be hidden.
158
+ */
159
+ export declare function reviewReferenceCorrectionAttempt(input: ReviewReferenceCorrectionAttemptInput): ReviewReferenceCorrectionAttemptResult;
160
+ export {};