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.
- package/CHANGELOG.md +51 -2
- package/README.md +156 -40
- package/UPGRADING.md +55 -1
- package/docs/04-PROGRAM-DESIGN.md +34 -4
- package/docs/05-ACCEPTANCE-CONTRACT.md +40 -3
- package/docs/08-INSTALLATION-AND-DISTRIBUTION.md +67 -22
- package/docs/14-FORMAL-RELEASE-READINESS.md +30 -1
- package/docs/18-BRANCH-AWARE-STAGED-CONTEXT-DESIGN.md +2 -2
- package/docs/19-POST-1.3.1-AI-TAKEOVER-EVIDENCE-AND-UPGRADE-PLAN.md +579 -0
- package/docs/20-PHASE-A-AI-TAKEOVER-AND-HEALTH-CLOSURE-DESIGN.md +535 -0
- package/docs/21-PHASE-B-EVIDENCE-FEEDBACK-PROTOCOL-DESIGN.md +347 -0
- package/docs/22-PHASE-C-TARGET-UPGRADE-PROTOCOL-DESIGN.md +398 -0
- package/docs/23-ADAPTIVE-BOUNDED-TASK-CONTEXT-DESIGN.md +432 -0
- package/docs/24-A130-REAL-HOST-TARGET-PROJECT-COMPARISON.md +210 -0
- package/docs/25-REAL-PROJECT-SOURCE-OF-TRUTH-MAINTENANCE-DESIGN.md +409 -0
- package/docs/26-A130-QUALITY-CLOSURE-AND-ADAPTIVE-DELIVERY-REPAIR-DESIGN.md +609 -0
- package/docs/README.md +38 -6
- package/docs/USER-AND-AI-OPERATION-MANUAL.md +840 -0
- package/examples/README.md +29 -2
- package/examples/package.json +6 -2
- package/migration-manifest.json +110 -0
- package/package.json +3 -2
- package/schemas/action-plan.schema.json +31 -3
- package/schemas/adaptive-context-bundle.schema.json +70 -0
- package/schemas/capabilities.schema.json +64 -18
- package/schemas/context-query.schema.json +69 -0
- package/schemas/coverage-audit.schema.json +32 -0
- package/schemas/evidence-bundle.schema.json +64 -0
- package/schemas/evidence-input.schema.json +82 -0
- package/schemas/host-promotion-evidence.schema.json +33 -0
- package/schemas/migration-manifest.schema.json +29 -0
- package/schemas/migration-plan.schema.json +32 -0
- package/schemas/project-status.schema.json +75 -0
- package/schemas/projection-lock.schema.json +48 -0
- package/schemas/review-bundle.schema.json +3 -3
- package/schemas/routing-index.schema.json +58 -0
- package/schemas/truth-reconciliation-input.schema.json +60 -0
- package/schemas/truth-reconciliation-review-bundle.schema.json +155 -0
- package/schemas/upgrade-assessment.schema.json +48 -0
- package/schemas/upgrade-result-bundle.schema.json +35 -0
- package/src/project-context/a130-evaluation.mjs +91 -0
- package/src/project-context/adaptive-context-schema.mjs +392 -0
- package/src/project-context/adaptive-context.mjs +547 -0
- package/src/project-context/ai-entry.mjs +320 -0
- package/src/project-context/assist.mjs +4 -2
- package/src/project-context/capabilities.mjs +62 -17
- package/src/project-context/checker.mjs +24 -6
- package/src/project-context/cli.mjs +113 -3
- package/src/project-context/contract-schema.mjs +30 -16
- package/src/project-context/dashboard-model.mjs +4 -4
- package/src/project-context/dashboard-renderer.mjs +3 -3
- package/src/project-context/discovery.mjs +13 -8
- package/src/project-context/evidence-schema.mjs +209 -0
- package/src/project-context/evidence.mjs +99 -0
- package/src/project-context/exchange-schema.mjs +23 -12
- package/src/project-context/exchange.mjs +26 -4
- package/src/project-context/maintenance.mjs +4 -4
- package/src/project-context/migration-manifest.mjs +168 -0
- package/src/project-context/project-status.mjs +157 -0
- package/src/project-context/projection-store.mjs +8 -1
- package/src/project-context/renderer.mjs +75 -1
- package/src/project-context/source-reader.mjs +63 -30
- package/src/project-context/task-context.mjs +14 -2
- package/src/project-context/truth-reconciliation-schema.mjs +488 -0
- package/src/project-context/truth-reconciliation.mjs +543 -0
- package/src/project-context/upgrade-schema.mjs +219 -0
- 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
|
+
}
|