frontend-project-context 1.3.1 → 1.7.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 (67) hide show
  1. package/CHANGELOG.md +51 -2
  2. package/README.md +156 -40
  3. package/UPGRADING.md +55 -1
  4. package/docs/04-PROGRAM-DESIGN.md +34 -4
  5. package/docs/05-ACCEPTANCE-CONTRACT.md +40 -3
  6. package/docs/08-INSTALLATION-AND-DISTRIBUTION.md +67 -22
  7. package/docs/14-FORMAL-RELEASE-READINESS.md +30 -1
  8. package/docs/18-BRANCH-AWARE-STAGED-CONTEXT-DESIGN.md +2 -2
  9. package/docs/19-POST-1.3.1-AI-TAKEOVER-EVIDENCE-AND-UPGRADE-PLAN.md +579 -0
  10. package/docs/20-PHASE-A-AI-TAKEOVER-AND-HEALTH-CLOSURE-DESIGN.md +535 -0
  11. package/docs/21-PHASE-B-EVIDENCE-FEEDBACK-PROTOCOL-DESIGN.md +347 -0
  12. package/docs/22-PHASE-C-TARGET-UPGRADE-PROTOCOL-DESIGN.md +398 -0
  13. package/docs/23-ADAPTIVE-BOUNDED-TASK-CONTEXT-DESIGN.md +432 -0
  14. package/docs/24-A130-REAL-HOST-TARGET-PROJECT-COMPARISON.md +210 -0
  15. package/docs/25-REAL-PROJECT-SOURCE-OF-TRUTH-MAINTENANCE-DESIGN.md +409 -0
  16. package/docs/26-A130-QUALITY-CLOSURE-AND-ADAPTIVE-DELIVERY-REPAIR-DESIGN.md +609 -0
  17. package/docs/README.md +38 -6
  18. package/docs/USER-AND-AI-OPERATION-MANUAL.md +840 -0
  19. package/examples/README.md +29 -2
  20. package/examples/package.json +6 -2
  21. package/migration-manifest.json +110 -0
  22. package/package.json +3 -2
  23. package/schemas/action-plan.schema.json +31 -3
  24. package/schemas/adaptive-context-bundle.schema.json +70 -0
  25. package/schemas/capabilities.schema.json +64 -18
  26. package/schemas/context-query.schema.json +69 -0
  27. package/schemas/coverage-audit.schema.json +32 -0
  28. package/schemas/evidence-bundle.schema.json +64 -0
  29. package/schemas/evidence-input.schema.json +82 -0
  30. package/schemas/host-promotion-evidence.schema.json +33 -0
  31. package/schemas/migration-manifest.schema.json +29 -0
  32. package/schemas/migration-plan.schema.json +32 -0
  33. package/schemas/project-status.schema.json +75 -0
  34. package/schemas/projection-lock.schema.json +48 -0
  35. package/schemas/review-bundle.schema.json +3 -3
  36. package/schemas/routing-index.schema.json +58 -0
  37. package/schemas/truth-reconciliation-input.schema.json +60 -0
  38. package/schemas/truth-reconciliation-review-bundle.schema.json +155 -0
  39. package/schemas/upgrade-assessment.schema.json +48 -0
  40. package/schemas/upgrade-result-bundle.schema.json +35 -0
  41. package/src/project-context/a130-evaluation.mjs +91 -0
  42. package/src/project-context/adaptive-context-schema.mjs +392 -0
  43. package/src/project-context/adaptive-context.mjs +547 -0
  44. package/src/project-context/ai-entry.mjs +320 -0
  45. package/src/project-context/assist.mjs +4 -2
  46. package/src/project-context/capabilities.mjs +62 -17
  47. package/src/project-context/checker.mjs +24 -6
  48. package/src/project-context/cli.mjs +113 -3
  49. package/src/project-context/contract-schema.mjs +30 -16
  50. package/src/project-context/dashboard-model.mjs +4 -4
  51. package/src/project-context/dashboard-renderer.mjs +3 -3
  52. package/src/project-context/discovery.mjs +13 -8
  53. package/src/project-context/evidence-schema.mjs +209 -0
  54. package/src/project-context/evidence.mjs +99 -0
  55. package/src/project-context/exchange-schema.mjs +23 -12
  56. package/src/project-context/exchange.mjs +26 -4
  57. package/src/project-context/maintenance.mjs +4 -4
  58. package/src/project-context/migration-manifest.mjs +168 -0
  59. package/src/project-context/project-status.mjs +157 -0
  60. package/src/project-context/projection-store.mjs +8 -1
  61. package/src/project-context/renderer.mjs +75 -1
  62. package/src/project-context/source-reader.mjs +63 -30
  63. package/src/project-context/task-context.mjs +14 -2
  64. package/src/project-context/truth-reconciliation-schema.mjs +488 -0
  65. package/src/project-context/truth-reconciliation.mjs +543 -0
  66. package/src/project-context/upgrade-schema.mjs +219 -0
  67. package/src/project-context/upgrade.mjs +494 -0
@@ -0,0 +1,155 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "urn:frontend-project-context:schema:truth-reconciliation-review-bundle:2",
4
+ "title": "Frontend Project Context Truth Reconciliation Review Bundle",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "kind", "project", "current", "task", "inputDigest", "summary", "candidateOutcomes", "collisionGroups", "findings", "resolutionOutcomes", "guarantees", "boundaries", "bundleDigest"],
8
+ "properties": {
9
+ "schemaVersion": { "const": 2 },
10
+ "kind": { "const": "truth-reconciliation-review-bundle" },
11
+ "project": { "$ref": "#/$defs/project" },
12
+ "current": { "$ref": "#/$defs/current" },
13
+ "task": { "$ref": "#/$defs/task" },
14
+ "inputDigest": { "$ref": "#/$defs/digest" },
15
+ "summary": { "$ref": "#/$defs/summary" },
16
+ "candidateOutcomes": { "type": "array", "items": { "$ref": "#/$defs/candidateOutcome" } },
17
+ "collisionGroups": { "type": "array", "items": { "$ref": "#/$defs/collisionGroup" } },
18
+ "findings": { "type": "array", "items": { "$ref": "#/$defs/finding" } },
19
+ "resolutionOutcomes": { "type": "array", "items": { "$ref": "#/$defs/resolutionOutcome" } },
20
+ "guarantees": { "$ref": "#/$defs/guarantees" },
21
+ "boundaries": { "$ref": "#/$defs/boundaries" },
22
+ "bundleDigest": { "$ref": "#/$defs/digest" }
23
+ },
24
+ "$defs": {
25
+ "id": { "type": "string", "pattern": "^[a-z0-9]+(?:[.-][a-z0-9]+)*$" },
26
+ "text": { "type": "string", "minLength": 1 },
27
+ "digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
28
+ "nullableDigest": { "oneOf": [{ "$ref": "#/$defs/digest" }, { "type": "null" }] },
29
+ "nullableText": { "oneOf": [{ "$ref": "#/$defs/text" }, { "type": "null" }] },
30
+ "ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/id" } },
31
+ "paths": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
32
+ "scope": {
33
+ "oneOf": [
34
+ { "type": "object", "additionalProperties": false, "required": ["kind"], "properties": { "kind": { "const": "project" } } },
35
+ { "type": "object", "additionalProperties": false, "required": ["kind", "path"], "properties": { "kind": { "enum": ["path-prefix", "file"] }, "path": { "type": "string", "minLength": 1 } } }
36
+ ]
37
+ },
38
+ "scopes": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/scope" } },
39
+ "snapshots": {
40
+ "type": "object", "additionalProperties": false,
41
+ "required": ["contract", "sourcesLock", "projectionsLock"],
42
+ "properties": { "contract": { "$ref": "#/$defs/digest" }, "sourcesLock": { "$ref": "#/$defs/digest" }, "projectionsLock": { "$ref": "#/$defs/digest" } }
43
+ },
44
+ "project": {
45
+ "type": "object", "additionalProperties": false, "required": ["id", "name"],
46
+ "properties": { "id": { "$ref": "#/$defs/id" }, "name": { "$ref": "#/$defs/text" } }
47
+ },
48
+ "current": {
49
+ "type": "object", "additionalProperties": false, "required": ["revision", "projectSnapshots"],
50
+ "properties": { "revision": { "$ref": "#/$defs/text" }, "projectSnapshots": { "$ref": "#/$defs/snapshots" } }
51
+ },
52
+ "task": {
53
+ "type": "object", "additionalProperties": false, "required": ["id", "paths"],
54
+ "properties": { "id": { "$ref": "#/$defs/id" }, "paths": { "$ref": "#/$defs/paths" } }
55
+ },
56
+ "summary": {
57
+ "type": "object", "additionalProperties": false,
58
+ "required": ["candidates", "eligibleCandidates", "collisionGroups", "findings", "taskHealth", "globalHealth", "existingDelivery"],
59
+ "properties": {
60
+ "candidates": { "type": "integer", "minimum": 0 },
61
+ "eligibleCandidates": { "type": "integer", "minimum": 0 },
62
+ "collisionGroups": { "type": "integer", "minimum": 0 },
63
+ "findings": { "type": "integer", "minimum": 0 },
64
+ "taskHealth": { "enum": ["ready", "blocked"] },
65
+ "globalHealth": { "enum": ["clean", "attention"] },
66
+ "existingDelivery": { "const": "not-blocked" }
67
+ }
68
+ },
69
+ "promotionEvidence": {
70
+ "type": "object", "additionalProperties": false,
71
+ "required": ["assurance", "currentEvidenceCount", "staleEvidenceCount", "localQaReusable", "integrationVerified"],
72
+ "properties": {
73
+ "assurance": { "const": "host-asserted" },
74
+ "currentEvidenceCount": { "type": "integer", "minimum": 0 },
75
+ "staleEvidenceCount": { "type": "integer", "minimum": 0 },
76
+ "localQaReusable": { "type": "boolean" },
77
+ "integrationVerified": { "type": "boolean" }
78
+ }
79
+ },
80
+ "candidateOutcome": {
81
+ "type": "object", "additionalProperties": false,
82
+ "required": ["candidateId", "lifecycle", "baseline", "promotionEvidence", "decisionCandidates", "eligibleForReconciliation"],
83
+ "properties": {
84
+ "candidateId": { "$ref": "#/$defs/id" },
85
+ "lifecycle": { "enum": ["active", "released", "withdrawn", "rolled-back"] },
86
+ "baseline": { "enum": ["current", "stale"] },
87
+ "promotionEvidence": { "$ref": "#/$defs/promotionEvidence" },
88
+ "decisionCandidates": { "enum": ["authority-free-candidates", "discarded-not-promoted"] },
89
+ "eligibleForReconciliation": { "type": "boolean" }
90
+ }
91
+ },
92
+ "resolutionKind": { "enum": ["keep-current-baseline", "accept-branch-change", "compose-compatible-changes", "split-scope-or-override", "replace-or-deprecate-source", "fix-source-and-rerun", "refresh-promotion-evidence", "defer-scoped-conflict", "external-implementation-fix-required"] },
93
+ "collisionGroup": {
94
+ "type": "object", "additionalProperties": false,
95
+ "required": ["kind", "key", "classification", "candidateIds", "candidateDigests", "affectedSourceIds", "affectedItemIds", "affectedSubjects", "affectedScopes", "resolutionKinds", "promoted"],
96
+ "properties": {
97
+ "kind": { "enum": ["source", "item", "subject"] },
98
+ "key": { "$ref": "#/$defs/id" },
99
+ "classification": { "enum": ["duplicate", "compatible-compose", "scope-split", "supersede", "semantic-conflict", "implementation-only"] },
100
+ "candidateIds": { "$ref": "#/$defs/ids" },
101
+ "candidateDigests": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/digest" } },
102
+ "affectedSourceIds": { "$ref": "#/$defs/ids" },
103
+ "affectedItemIds": { "$ref": "#/$defs/ids" },
104
+ "affectedSubjects": { "$ref": "#/$defs/ids" },
105
+ "affectedScopes": { "$ref": "#/$defs/scopes" },
106
+ "resolutionKinds": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/resolutionKind" } },
107
+ "promoted": { "const": false }
108
+ }
109
+ },
110
+ "baseline": {
111
+ "type": "object", "additionalProperties": false,
112
+ "required": ["expectedDigest", "actualDigest", "expectedLabel", "actualLabel"],
113
+ "properties": { "expectedDigest": { "$ref": "#/$defs/nullableDigest" }, "actualDigest": { "$ref": "#/$defs/nullableDigest" }, "expectedLabel": { "$ref": "#/$defs/nullableText" }, "actualLabel": { "$ref": "#/$defs/nullableText" } }
114
+ },
115
+ "invocation": {
116
+ "type": "object", "additionalProperties": false, "required": ["command", "args"],
117
+ "properties": { "command": { "$ref": "#/$defs/id" }, "args": { "type": "array", "items": { "type": "string" } } }
118
+ },
119
+ "externalAction": { "type": "object", "additionalProperties": false, "required": ["kind"], "properties": { "kind": { "type": "string" }, "affectedSourceIds": { "$ref": "#/$defs/ids" }, "affectedItemIds": { "$ref": "#/$defs/ids" }, "affectedPaths": { "$ref": "#/$defs/paths" } } },
120
+ "recoveryPreview": { "type": "object", "additionalProperties": false, "required": ["resolutionKind"], "properties": { "resolutionKind": { "$ref": "#/$defs/resolutionKind" }, "invocation": { "$ref": "#/$defs/invocation" }, "externalAction": { "$ref": "#/$defs/externalAction" }, "requiredHumanInputs": { "type": "array", "items": { "type": "string" } } } },
121
+ "resolutionContract": { "type": "object", "additionalProperties": false, "required": ["resolutionState", "resolutionKinds", "requiredHumanInputs", "nextActions", "requiredPostResolutionEvidence", "completionCriteria", "recomputeFromCurrentBaseline"], "properties": { "resolutionState": { "enum": ["needs-human-decision", "contract-action-required", "external-fix-required", "revalidation-required", "resolved", "deferred-open"] }, "resolutionKinds": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/resolutionKind" } }, "requiredHumanInputs": { "type": "array", "uniqueItems": true, "items": { "type": "string" } }, "nextActions": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/recoveryPreview" } }, "requiredPostResolutionEvidence": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string" } }, "completionCriteria": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string" } }, "recomputeFromCurrentBaseline": { "const": true } } },
122
+ "finding": {
123
+ "type": "object", "additionalProperties": false,
124
+ "required": ["code", "severity", "affectedSourceIds", "affectedItemIds", "affectedSubjects", "affectedScopes", "baseline", "blocksTask", "blocksExistingDelivery", "resolutionKinds", "recoveryPreviews", "humanRoles", "validateAfterResolution", "recomputeFromCurrentBaseline", "findingDigest", "resolutionContract"],
125
+ "properties": {
126
+ "code": { "$ref": "#/$defs/id" },
127
+ "severity": { "enum": ["attention", "conflict", "blocked"] },
128
+ "affectedSourceIds": { "$ref": "#/$defs/ids" },
129
+ "affectedItemIds": { "$ref": "#/$defs/ids" },
130
+ "affectedSubjects": { "$ref": "#/$defs/ids" },
131
+ "affectedScopes": { "$ref": "#/$defs/scopes" },
132
+ "baseline": { "$ref": "#/$defs/baseline" },
133
+ "blocksTask": { "type": "boolean" },
134
+ "blocksExistingDelivery": { "const": false },
135
+ "resolutionKinds": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/resolutionKind" } },
136
+ "recoveryPreviews": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/recoveryPreview" } },
137
+ "humanRoles": { "$ref": "#/$defs/ids" },
138
+ "validateAfterResolution": { "$ref": "#/$defs/ids" },
139
+ "recomputeFromCurrentBaseline": { "const": true },
140
+ "findingDigest": { "$ref": "#/$defs/digest" },
141
+ "resolutionContract": { "$ref": "#/$defs/resolutionContract" }
142
+ }
143
+ },
144
+ "resolutionOutcome": { "type": "object", "additionalProperties": false, "required": ["findingDigest", "resolutionKind", "resolutionState", "outcome", "completionCriteriaMet", "recomputedFromCurrentBaseline"], "properties": { "findingDigest": { "$ref": "#/$defs/digest" }, "resolutionKind": { "$ref": "#/$defs/resolutionKind" }, "resolutionState": { "enum": ["revalidation-required", "external-fix-required", "resolved", "deferred-open"] }, "outcome": { "enum": ["open", "deferred", "resolved", "rejected"] }, "completionCriteriaMet": { "type": "array", "uniqueItems": true, "items": { "type": "string" } }, "recomputedFromCurrentBaseline": { "const": true } } },
145
+ "guarantees": {
146
+ "type": "object", "additionalProperties": false, "required": ["projectContextVerified", "hostAsserted", "humanDecided"],
147
+ "properties": { "projectContextVerified": { "$ref": "#/$defs/ids" }, "hostAsserted": { "$ref": "#/$defs/ids" }, "humanDecided": { "$ref": "#/$defs/ids" } }
148
+ },
149
+ "boundaries": {
150
+ "type": "object", "additionalProperties": false,
151
+ "required": ["readOnly", "git", "ciClient", "network", "provider", "taskExecution", "automaticApproval", "automaticPromotion", "persistentQueue", "blocksExistingDelivery"],
152
+ "properties": { "readOnly": { "const": true }, "git": { "const": false }, "ciClient": { "const": false }, "network": { "const": false }, "provider": { "const": false }, "taskExecution": { "const": false }, "automaticApproval": { "const": false }, "automaticPromotion": { "const": false }, "persistentQueue": { "const": false }, "blocksExistingDelivery": { "const": false } }
153
+ }
154
+ }
155
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "urn:frontend-project-context:schema:upgrade-assessment:1",
4
+ "title": "Frontend Project Context Upgrade Assessment",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "kind", "product", "fromVersion", "targetVersion", "fromVersionEvidence", "manifestSchemaVersion", "manifestDigest", "initialization", "health", "entryState", "findingCodes", "snapshots", "compatibility", "migrationPath", "rollbackClass", "requiresHumanReview", "state", "boundaries", "assessmentDigest"],
8
+ "properties": {
9
+ "schemaVersion": {"const": 1},
10
+ "kind": {"const": "upgrade-assessment"},
11
+ "product": {"type": "object", "additionalProperties": false, "required": ["name"], "properties": {"name": {"const": "frontend-project-context"}}},
12
+ "fromVersion": {"enum": ["1.3.1", "1.4.0", "1.5.0", "1.6.0"]},
13
+ "targetVersion": {"const": "1.7.0"},
14
+ "fromVersionEvidence": {"const": "host-asserted"},
15
+ "manifestSchemaVersion": {"const": 2},
16
+ "manifestDigest": {"$ref": "#/$defs/digest"},
17
+ "initialization": {"type": "object", "additionalProperties": false, "required": ["state", "present", "missing"], "properties": {"state": {"enum": ["uninitialized", "partial", "initialized", "invalid"]}, "present": {"$ref": "#/$defs/strings"}, "missing": {"$ref": "#/$defs/strings"}}},
18
+ "health": {"enum": ["uninitialized", "partial", "invalid", "attention", "conflict", "clean"]},
19
+ "entryState": {"type": "object", "additionalProperties": false, "required": ["state", "path", "rendererVersion"], "properties": {"state": {"type": "string"}, "path": {"type": ["string", "null"]}, "rendererVersion": {"type": ["integer", "null"]}}},
20
+ "findingCodes": {"$ref": "#/$defs/strings"},
21
+ "snapshots": {"anyOf": [{"type": "null"}, {"$ref": "#/$defs/snapshots"}]},
22
+ "compatibility": {"type": "object", "additionalProperties": false, "required": ["stores", "renderers", "protocols"], "properties": {"stores": {"$ref": "#/$defs/compatibility"}, "renderers": {"$ref": "#/$defs/compatibility"}, "protocols": {"$ref": "#/$defs/compatibility"}}},
23
+ "migrationPath": {"$ref": "#/$defs/strings"},
24
+ "rollbackClass": {"enum": ["package-only", "reversible-data", "forward-only"]},
25
+ "requiresHumanReview": {"type": "boolean"},
26
+ "state": {"enum": ["not-applicable", "blocked", "ready-for-plan", "core-complete"]},
27
+ "boundaries": {"$ref": "#/$defs/boundaries"},
28
+ "assessmentDigest": {"$ref": "#/$defs/digest"}
29
+ },
30
+ "$defs": {
31
+ "digest": {"type": "string", "pattern": "^sha256:[a-f0-9]{64}$"},
32
+ "strings": {"type": "array", "uniqueItems": true, "items": {"type": "string"}},
33
+ "snapshots": {"type": "object", "additionalProperties": false, "required": ["contract", "sourcesLock", "projectionsLock"], "properties": {"contract": {"$ref": "#/$defs/digest"}, "sourcesLock": {"$ref": "#/$defs/digest"}, "projectionsLock": {"$ref": "#/$defs/digest"}}},
34
+ "compatibility": {"type": "object", "additionalProperties": {"enum": ["compatible", "republish", "regenerate", "invalidate", "unsupported", "not-applicable"]}},
35
+ "boundaries": {
36
+ "type": "object",
37
+ "additionalProperties": false,
38
+ "required": ["provider", "agentRuntime", "git", "network", "dependencyInstallation", "automaticApproval", "businessCodeWrites", "taskExecution", "stagePathBodyReads", "applyPlan", "scheduler", "daemon", "telemetry", "selfUpdate", "automaticEvidenceUpload", "packageManager", "automaticUpgrade"],
39
+ "properties": {
40
+ "provider": {"const": false}, "agentRuntime": {"const": false}, "git": {"const": false}, "network": {"const": false},
41
+ "dependencyInstallation": {"const": false}, "automaticApproval": {"const": false}, "businessCodeWrites": {"const": false},
42
+ "taskExecution": {"const": false}, "stagePathBodyReads": {"const": false}, "applyPlan": {"const": false},
43
+ "scheduler": {"const": false}, "daemon": {"const": false}, "telemetry": {"const": false}, "selfUpdate": {"const": false},
44
+ "automaticEvidenceUpload": {"const": false}, "packageManager": {"const": false}, "automaticUpgrade": {"const": false}
45
+ }
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "urn:frontend-project-context:schema:upgrade-result-bundle:1",
4
+ "title": "Frontend Project Context Upgrade Result Bundle",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "kind", "product", "fromVersion", "targetVersion", "manifestDigest", "planDigest", "mode", "action", "written", "targets", "snapshots", "actionResult", "findingCodes", "coreMigration", "hostAcceptance", "overallUpgrade", "resultDigest"],
8
+ "properties": {
9
+ "schemaVersion": {"const": 1},
10
+ "kind": {"const": "upgrade-result-bundle"},
11
+ "product": {"type": "object", "additionalProperties": false, "required": ["name"], "properties": {"name": {"const": "frontend-project-context"}}},
12
+ "fromVersion": {"type": "string"},
13
+ "targetVersion": {"const": "1.7.0"},
14
+ "manifestDigest": {"$ref": "#/$defs/digest"},
15
+ "planDigest": {"$ref": "#/$defs/digest"},
16
+ "mode": {"enum": ["preview", "write"]},
17
+ "action": {"$ref": "#/$defs/action"},
18
+ "written": {"type": "boolean"},
19
+ "targets": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["path", "beforeDigest", "afterDigest"], "properties": {"path": {"$ref": "#/$defs/path"}, "beforeDigest": {"anyOf": [{"type": "null"}, {"$ref": "#/$defs/digest"}]}, "afterDigest": {"anyOf": [{"type": "null"}, {"$ref": "#/$defs/digest"}]}}}},
20
+ "snapshots": {"type": "object", "additionalProperties": false, "required": ["before", "after"], "properties": {"before": {"anyOf": [{"type": "null"}, {"$ref": "#/$defs/snapshots"}]}, "after": {"anyOf": [{"type": "null"}, {"$ref": "#/$defs/snapshots"}]}}},
21
+ "actionResult": {"type": "string"},
22
+ "findingCodes": {"type": "array", "uniqueItems": true, "items": {"type": "string"}},
23
+ "coreMigration": {"enum": ["previewed", "applied", "blocked", "complete"]},
24
+ "hostAcceptance": {"const": ["dependency-and-lockfile", "independent-new-window", "project-tests-or-ci"]},
25
+ "overallUpgrade": {"const": "host-validation-required"},
26
+ "resultDigest": {"$ref": "#/$defs/digest"}
27
+ },
28
+ "$defs": {
29
+ "digest": {"type": "string", "pattern": "^sha256:[a-f0-9]{64}$"},
30
+ "path": {"type": "string", "minLength": 1, "pattern": "^(?!/)(?![A-Za-z]:)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*\\\\).+$"},
31
+ "strings": {"type": "array", "uniqueItems": true, "items": {"type": "string"}},
32
+ "snapshots": {"type": "object", "additionalProperties": false, "required": ["contract", "sourcesLock", "projectionsLock"], "properties": {"contract": {"$ref": "#/$defs/digest"}, "sourcesLock": {"$ref": "#/$defs/digest"}, "projectionsLock": {"$ref": "#/$defs/digest"}}},
33
+ "action": {"type": "object", "additionalProperties": false, "required": ["id", "kind", "migrationId", "targets", "writes", "semanticImpact"], "properties": {"id": {"type": "string"}, "kind": {"enum": ["verify-complete", "republish-ai-entry", "republish-projection", "built-in-store-migration", "invalidate-ephemeral-protocol"]}, "migrationId": {"type": ["string", "null"]}, "targets": {"type": "array", "uniqueItems": true, "items": {"$ref": "#/$defs/path"}}, "writes": {"type": "boolean"}, "semanticImpact": {"enum": ["none", "managed-rendering", "store-structure", "protocol-artifact-invalidation"]}}}
34
+ }
35
+ }
@@ -0,0 +1,91 @@
1
+ import { canonicalJson, digestJson } from "./canonical-json.mjs";
2
+ import { fail } from "./errors.mjs";
3
+
4
+ function median(values) {
5
+ const sorted = [...values].sort((left, right) => left - right);
6
+ return sorted[Math.floor(sorted.length / 2)];
7
+ }
8
+
9
+ function sameStringSet(left = [], right = []) {
10
+ return canonicalJson([...left].sort()) === canonicalJson([...right].sort());
11
+ }
12
+
13
+ function pairEntries(entries) {
14
+ return Array.from({ length: entries.length / 2 }, (_, index) => entries.slice(index * 2, index * 2 + 2));
15
+ }
16
+
17
+ function pairArms(pair) {
18
+ return {
19
+ full: pair.find((run) => run.arm === "full"),
20
+ candidate: pair.find((run) => run.arm === "candidate"),
21
+ };
22
+ }
23
+
24
+ function assertFailureEvidence(run) {
25
+ if (run.score < 8 && (!Array.isArray(run.failedChecks) || run.failedChecks.length === 0 || run.failedChecks.some((entry) => typeof entry !== "string" || !entry))) {
26
+ fail("a130-run-result-invalid", "a failed A-130 run must name its failed checks");
27
+ }
28
+ }
29
+
30
+ export function validateA130EvaluationPlan(plan, contract, readablePaths) {
31
+ if (!plan || typeof plan !== "object" || Array.isArray(plan)) fail("a130-evaluation-invalid", "evaluation plan must be an object");
32
+ const allowed = new Set(["arms", "cases", "forbiddenPaths", "model", "oracleApproval", "wrapper"]);
33
+ if (Object.keys(plan).some((key) => !allowed.has(key)) || !Array.isArray(plan.arms) || !Array.isArray(plan.cases)) fail("a130-evaluation-invalid", "evaluation plan structure is invalid");
34
+ if (plan.arms.length !== 2 || plan.arms.some((arm) => !arm || typeof arm !== "object" || arm.format !== plan.arms[0].format || canonicalJson(arm.wrapper) !== canonicalJson(plan.wrapper))) fail("arm-format-mismatch", "full and candidate arms must use the same delivery format and wrapper");
35
+ const approvedIds = new Set(contract.items.filter((item) => item.status === "approved").map((item) => item.id));
36
+ const readable = new Set(readablePaths);
37
+ for (const scenario of plan.cases) {
38
+ if (!Array.isArray(scenario.oracle) || scenario.oracle.length === 0) fail("oracle-evidence-missing", "every evaluation case needs a non-empty oracle");
39
+ for (const oracle of scenario.oracle) {
40
+ if (!oracle.contractItemId && !oracle.sourcePath) fail("oracle-evidence-missing", "oracle truth must be available to both arms through Contract or readable source");
41
+ if (oracle.contractItemId && !approvedIds.has(oracle.contractItemId)) fail("oracle-evidence-missing", `oracle item ${oracle.contractItemId} is not approved`);
42
+ if (oracle.sourcePath && !readable.has(oracle.sourcePath)) fail("oracle-evidence-missing", `oracle source ${oracle.sourcePath} is not readable by both arms`);
43
+ if (plan.forbiddenPaths.includes(oracle.sourcePath)) fail("oracle-evidence-forbidden", "forbidden oracle locators cannot be model evidence");
44
+ }
45
+ }
46
+ const oracleDigest = digestJson(plan.cases.map(({ id, oracle }) => ({ id, oracle })));
47
+ const approval = plan.oracleApproval;
48
+ if (!approval || typeof approval !== "object" || Array.isArray(approval) || Object.keys(approval).some((key) => !["at", "by", "oracleDigest"].includes(key)) || typeof approval.by !== "string" || !approval.by || typeof approval.at !== "string" || !approval.at || approval.oracleDigest !== oracleDigest) {
49
+ fail("oracle-human-approval-missing", "the exact A-130 oracle table must be digest-bound and explicitly approved by a human before Provider use");
50
+ }
51
+ return { planDigest: digestJson(plan), status: "ready", armFormat: plan.arms[0].format, oracleDigest, wrapperDigest: digestJson(plan.wrapper) };
52
+ }
53
+
54
+ export function evaluateA130Runs(runs) {
55
+ if (!Array.isArray(runs) || runs.length !== 8) fail("a130-run-set-invalid", "A-130 requires one S pair and three order-balanced L pairs (eight runs maximum)");
56
+ const expectedOrders = { S: ["full", "candidate"], L: ["full", "candidate", "candidate", "full", "full", "candidate"] };
57
+ for (const caseId of ["S", "L"]) {
58
+ const entries = runs.filter((run) => run.caseId === caseId);
59
+ if (canonicalJson(entries.map((run) => run.arm)) !== canonicalJson(expectedOrders[caseId])) fail("a130-run-order-invalid", `${caseId} does not match its frozen pair order`);
60
+ if (entries.some((run) => run.forbiddenAccess || run.targetWritten || run.gitChanged)) fail("a130-safety-gate-failed", `${caseId} contains a forbidden Host action`);
61
+ entries.forEach(assertFailureEvidence);
62
+ }
63
+ const small = runs.filter((run) => run.caseId === "S");
64
+ if (small[0].promptDigest !== small[1].promptDigest) fail("a130-small-prompt-mismatch", "A-130-S prompts must be byte-identical before Provider comparison");
65
+ if (small[0].score !== 8 || small[1].score !== 8) {
66
+ if (small[0].score < 8 && small[1].score < 8 && sameStringSet(small[0].failedChecks, small[1].failedChecks)) fail("a130-fixture-inconclusive", "byte-identical A-130-S arms failed the same checks; review the task/oracle without changing product selection");
67
+ fail("a130-provider-variance-inconclusive", "byte-identical A-130-S arms produced different quality and cannot identify a product defect");
68
+ }
69
+ const large = runs.filter((run) => run.caseId === "L");
70
+ const full = large.filter((run) => run.arm === "full");
71
+ const candidate = large.filter((run) => run.arm === "candidate");
72
+ if (candidate.some((run) => run.deliveryMode !== "adaptive" || run.requiredRecall !== 1)) fail("a130-adaptive-evidence-defect", "A-130-L candidate runs must be real adaptive deliveries with complete required-item recall");
73
+ const attributedFailures = [];
74
+ for (const pair of pairEntries(large)) {
75
+ const { full: fullRun, candidate: candidateRun } = pairArms(pair);
76
+ if (fullRun.score < 8 && candidateRun.score < 8 && sameStringSet(fullRun.failedChecks, candidateRun.failedChecks)) fail("a130-fixture-inconclusive", "paired A-130-L arms failed the same checks; review the task/oracle without changing product selection");
77
+ if (fullRun.score < 8) fail("a130-baseline-inconclusive", "an A-130-L full baseline failed, so the pair cannot identify an adaptive product defect");
78
+ if (candidateRun.score < 8) {
79
+ const attribution = candidateRun.attribution;
80
+ if (!attribution || attribution.kind !== "delivery-evidence-gap" || !Array.isArray(attribution.itemIds) || attribution.itemIds.length === 0) fail("a130-causality-inconclusive", "a candidate-only failure needs a governed delivery-evidence attribution before it can be a product defect");
81
+ attributedFailures.push(attribution.itemIds.slice().sort());
82
+ }
83
+ }
84
+ if (attributedFailures.length > 0) {
85
+ const reproducible = attributedFailures.some((ids, index) => attributedFailures.some((other, otherIndex) => otherIndex > index && canonicalJson(ids) === canonicalJson(other)));
86
+ if (!reproducible) fail("a130-causality-inconclusive", "an attributed adaptive failure was not reproduced in a second balanced pair");
87
+ fail("a130-adaptive-evidence-defect", "a governed delivery-evidence gap reproducibly caused candidate-only quality failure");
88
+ }
89
+ if (median(candidate.map((run) => run.promptBytes)) > median(full.map((run) => run.promptBytes)) * 0.7 || median(candidate.map((run) => run.inputTokens)) > median(full.map((run) => run.inputTokens)) || median(candidate.map((run) => run.commandCount)) > median(full.map((run) => run.commandCount)) || median(candidate.map((run) => run.wallSeconds)) > median(full.map((run) => run.wallSeconds)) * 1.1) fail("a130-efficiency-gate-failed", "A-130-L median efficiency gates failed");
90
+ return { status: "passed", pairs: 4, runs: 8 };
91
+ }