frontend-project-context 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -2
- package/README.md +74 -6
- package/UPGRADING.md +28 -0
- package/docs/04-PROGRAM-DESIGN.md +20 -1
- package/docs/05-ACCEPTANCE-CONTRACT.md +32 -3
- package/docs/08-INSTALLATION-AND-DISTRIBUTION.md +16 -8
- package/docs/14-FORMAL-RELEASE-READINESS.md +36 -0
- package/docs/17-AI-EXCHANGE-BOUNDARY-DESIGN.md +4 -2
- package/docs/18-BRANCH-AWARE-STAGED-CONTEXT-DESIGN.md +408 -0
- package/docs/README.md +10 -6
- package/examples/README.md +11 -0
- package/examples/package.json +1 -1
- package/package.json +2 -2
- package/schemas/capabilities.schema.json +25 -2
- package/schemas/integration-review-bundle.schema.json +43 -0
- package/schemas/stage-context-bundle.schema.json +56 -0
- package/schemas/stage-receipt.schema.json +55 -0
- package/schemas/task-context-plan.schema.json +85 -0
- package/src/project-context/capabilities.mjs +74 -0
- package/src/project-context/cli.mjs +29 -2
- package/src/project-context/exchange-schema.mjs +3 -3
- package/src/project-context/exchange.mjs +2 -60
- package/src/project-context/task-context-schema.mjs +526 -0
- package/src/project-context/task-context.mjs +502 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "urn:frontend-project-context:schema:stage-context-bundle:1",
|
|
4
|
+
"title": "Frontend Project Context Stage Context Bundle",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schemaVersion", "kind", "project", "task", "stage", "workspace", "planDigest", "snapshots", "dependencyReceipts", "changedPaths", "contractItems", "readTargets", "findings", "excluded", "budget", "status", "bundleDigest"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": { "const": 1 },
|
|
10
|
+
"kind": { "const": "stage-context-bundle" },
|
|
11
|
+
"project": { "$ref": "#/$defs/identity" },
|
|
12
|
+
"task": { "$ref": "#/$defs/task" },
|
|
13
|
+
"stage": { "$ref": "#/$defs/stage" },
|
|
14
|
+
"workspace": { "$ref": "#/$defs/workspace" },
|
|
15
|
+
"planDigest": { "$ref": "#/$defs/digest" },
|
|
16
|
+
"snapshots": { "$ref": "#/$defs/snapshots" },
|
|
17
|
+
"dependencyReceipts": { "type": "array", "items": { "$ref": "#/$defs/receiptSummary" } },
|
|
18
|
+
"changedPaths": { "$ref": "#/$defs/paths" },
|
|
19
|
+
"contractItems": { "type": "array", "items": { "$ref": "#/$defs/contractItem" } },
|
|
20
|
+
"readTargets": { "type": "array", "items": { "$ref": "#/$defs/readTarget" } },
|
|
21
|
+
"findings": { "type": "array", "items": { "type": "object" } },
|
|
22
|
+
"excluded": { "type": "array", "uniqueItems": true, "items": { "type": "string" } },
|
|
23
|
+
"budget": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"additionalProperties": false,
|
|
26
|
+
"required": ["unit", "maxUtf8Bytes", "maxReadTargets", "usedUtf8Bytes", "readTargetCount"],
|
|
27
|
+
"properties": {
|
|
28
|
+
"unit": { "const": "canonical-utf8-bytes" },
|
|
29
|
+
"maxUtf8Bytes": { "type": "integer", "minimum": 1 },
|
|
30
|
+
"maxReadTargets": { "type": "integer", "minimum": 1 },
|
|
31
|
+
"usedUtf8Bytes": { "type": "integer", "minimum": 0 },
|
|
32
|
+
"readTargetCount": { "type": "integer", "minimum": 0 }
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"status": { "enum": ["ready", "blocked"] },
|
|
36
|
+
"bundleDigest": { "$ref": "#/$defs/digest" }
|
|
37
|
+
},
|
|
38
|
+
"$defs": {
|
|
39
|
+
"digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
40
|
+
"identity": { "type": "object", "additionalProperties": false, "required": ["id", "name"], "properties": { "id": { "$ref": "#/$defs/id" }, "name": { "$ref": "#/$defs/text" } } },
|
|
41
|
+
"id": { "type": "string", "pattern": "^[a-z0-9]+(?:[.-][a-z0-9]+)*$" },
|
|
42
|
+
"text": { "type": "string", "minLength": 1 },
|
|
43
|
+
"paths": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
|
|
44
|
+
"snapshots": { "type": "object", "additionalProperties": false, "required": ["contract", "sourcesLock", "projectionsLock"], "properties": { "contract": { "$ref": "#/$defs/digest" }, "sourcesLock": { "$ref": "#/$defs/digest" }, "projectionsLock": { "$ref": "#/$defs/digest" } } },
|
|
45
|
+
"task": { "type": "object", "additionalProperties": false, "required": ["id", "title", "goal"], "properties": { "id": { "$ref": "#/$defs/id" }, "title": { "$ref": "#/$defs/text" }, "goal": { "$ref": "#/$defs/text" } } },
|
|
46
|
+
"acceptance": { "type": "object", "additionalProperties": false, "required": ["id", "text"], "properties": { "id": { "$ref": "#/$defs/id" }, "text": { "$ref": "#/$defs/text" } } },
|
|
47
|
+
"stage": { "type": "object", "additionalProperties": false, "required": ["id", "title", "objective", "acceptance", "paths"], "properties": { "id": { "$ref": "#/$defs/id" }, "title": { "$ref": "#/$defs/text" }, "objective": { "$ref": "#/$defs/text" }, "acceptance": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/acceptance" } }, "paths": { "$ref": "#/$defs/paths" } } },
|
|
48
|
+
"workspace": { "type": "object", "additionalProperties": false, "required": ["branchLabel", "baseRevision"], "properties": { "branchLabel": { "$ref": "#/$defs/text" }, "baseRevision": { "$ref": "#/$defs/text" } } },
|
|
49
|
+
"acceptanceResult": { "type": "object", "additionalProperties": false, "required": ["id", "status", "evidence"], "properties": { "id": { "$ref": "#/$defs/id" }, "status": { "enum": ["observed", "not-observed"] }, "evidence": { "$ref": "#/$defs/paths" } } },
|
|
50
|
+
"verificationResult": { "type": "object", "additionalProperties": false, "required": ["id", "status", "summary", "evidence"], "properties": { "id": { "$ref": "#/$defs/id" }, "status": { "enum": ["passed", "failed", "observed", "skipped"] }, "summary": { "$ref": "#/$defs/text" }, "evidence": { "$ref": "#/$defs/paths" } } },
|
|
51
|
+
"receiptSummary": { "type": "object", "additionalProperties": false, "required": ["stageId", "status", "inputBundleDigest", "changedPaths", "acceptanceResults", "verificationResults", "decisions", "openIssues"], "properties": { "stageId": { "$ref": "#/$defs/id" }, "status": { "enum": ["completed", "blocked"] }, "inputBundleDigest": { "$ref": "#/$defs/digest" }, "changedPaths": { "$ref": "#/$defs/paths" }, "acceptanceResults": { "type": "array", "items": { "$ref": "#/$defs/acceptanceResult" } }, "verificationResults": { "type": "array", "items": { "$ref": "#/$defs/verificationResult" } }, "decisions": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/text" } }, "openIssues": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/text" } } } },
|
|
52
|
+
"scope": { "type": "object", "additionalProperties": false, "required": ["kind"], "properties": { "kind": { "enum": ["project", "path-prefix", "file"] }, "path": { "type": "string", "minLength": 1 } } },
|
|
53
|
+
"contractItem": { "type": "object", "additionalProperties": false, "required": ["id", "kind", "subject", "value", "statement", "scope", "sourceIds"], "properties": { "id": { "$ref": "#/$defs/id" }, "kind": { "enum": ["fact", "policy", "reference", "validation-description"] }, "subject": { "$ref": "#/$defs/id" }, "value": {}, "statement": { "$ref": "#/$defs/text" }, "scope": { "$ref": "#/$defs/scope" }, "sourceIds": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/id" } } } },
|
|
54
|
+
"readTarget": { "type": "object", "additionalProperties": false, "required": ["path", "reason"], "properties": { "path": { "type": "string", "minLength": 1 }, "reason": { "enum": ["stage-scope", "host-changed-path-signal", "contract-source"] }, "sourceId": { "$ref": "#/$defs/id" } } }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "urn:frontend-project-context:schema:stage-receipt:1",
|
|
4
|
+
"title": "Frontend Project Context Stage Receipt",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schemaVersion", "kind", "projectId", "taskId", "stageId", "planDigest", "inputBundleDigest", "status", "changedPaths", "acceptanceResults", "verificationResults", "decisions", "openIssues"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": { "const": 1 },
|
|
10
|
+
"kind": { "const": "stage-receipt" },
|
|
11
|
+
"projectId": { "$ref": "#/$defs/id" },
|
|
12
|
+
"taskId": { "$ref": "#/$defs/id" },
|
|
13
|
+
"stageId": { "$ref": "#/$defs/id" },
|
|
14
|
+
"planDigest": { "$ref": "#/$defs/digest" },
|
|
15
|
+
"inputBundleDigest": { "$ref": "#/$defs/digest" },
|
|
16
|
+
"status": { "enum": ["completed", "blocked"] },
|
|
17
|
+
"changedPaths": { "$ref": "#/$defs/paths" },
|
|
18
|
+
"acceptanceResults": {
|
|
19
|
+
"type": "array",
|
|
20
|
+
"items": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"additionalProperties": false,
|
|
23
|
+
"required": ["id", "status", "evidence"],
|
|
24
|
+
"properties": {
|
|
25
|
+
"id": { "$ref": "#/$defs/id" },
|
|
26
|
+
"status": { "enum": ["observed", "not-observed"] },
|
|
27
|
+
"evidence": { "$ref": "#/$defs/paths" }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"verificationResults": {
|
|
32
|
+
"type": "array",
|
|
33
|
+
"items": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"additionalProperties": false,
|
|
36
|
+
"required": ["id", "status", "summary", "evidence"],
|
|
37
|
+
"properties": {
|
|
38
|
+
"id": { "$ref": "#/$defs/id" },
|
|
39
|
+
"status": { "enum": ["passed", "failed", "observed", "skipped"] },
|
|
40
|
+
"summary": { "type": "string", "minLength": 1 },
|
|
41
|
+
"evidence": { "$ref": "#/$defs/paths" }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"decisions": { "$ref": "#/$defs/texts" },
|
|
46
|
+
"openIssues": { "$ref": "#/$defs/texts" },
|
|
47
|
+
"nextStageId": { "$ref": "#/$defs/id" }
|
|
48
|
+
},
|
|
49
|
+
"$defs": {
|
|
50
|
+
"id": { "type": "string", "pattern": "^[a-z0-9]+(?:[.-][a-z0-9]+)*$" },
|
|
51
|
+
"digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
52
|
+
"paths": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } },
|
|
53
|
+
"texts": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "urn:frontend-project-context:schema:task-context-plan:1",
|
|
4
|
+
"title": "Frontend Project Context Task Context Plan",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": ["schemaVersion", "kind", "projectId", "task", "workspace", "snapshots", "budget", "stages"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"schemaVersion": { "const": 1 },
|
|
10
|
+
"kind": { "const": "task-context-plan" },
|
|
11
|
+
"projectId": { "$ref": "#/$defs/id" },
|
|
12
|
+
"task": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"additionalProperties": false,
|
|
15
|
+
"required": ["id", "title", "goal", "acceptance"],
|
|
16
|
+
"properties": {
|
|
17
|
+
"id": { "$ref": "#/$defs/id" },
|
|
18
|
+
"title": { "$ref": "#/$defs/text" },
|
|
19
|
+
"goal": { "$ref": "#/$defs/text" },
|
|
20
|
+
"acceptance": {
|
|
21
|
+
"type": "array",
|
|
22
|
+
"minItems": 1,
|
|
23
|
+
"items": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"additionalProperties": false,
|
|
26
|
+
"required": ["id", "text"],
|
|
27
|
+
"properties": { "id": { "$ref": "#/$defs/id" }, "text": { "$ref": "#/$defs/text" } }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"workspace": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"additionalProperties": false,
|
|
35
|
+
"required": ["branchLabel", "baseRevision"],
|
|
36
|
+
"properties": { "branchLabel": { "$ref": "#/$defs/text" }, "baseRevision": { "$ref": "#/$defs/text" } }
|
|
37
|
+
},
|
|
38
|
+
"snapshots": { "$ref": "#/$defs/snapshots" },
|
|
39
|
+
"budget": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"additionalProperties": false,
|
|
42
|
+
"required": ["maxUtf8Bytes", "maxReadTargets"],
|
|
43
|
+
"properties": {
|
|
44
|
+
"maxUtf8Bytes": { "type": "integer", "minimum": 1 },
|
|
45
|
+
"maxReadTargets": { "type": "integer", "minimum": 1 }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"stages": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"minItems": 1,
|
|
51
|
+
"items": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"additionalProperties": false,
|
|
54
|
+
"required": ["id", "title", "objective", "dependsOn", "paths", "acceptanceIds"],
|
|
55
|
+
"properties": {
|
|
56
|
+
"id": { "$ref": "#/$defs/id" },
|
|
57
|
+
"title": { "$ref": "#/$defs/text" },
|
|
58
|
+
"objective": { "$ref": "#/$defs/text" },
|
|
59
|
+
"dependsOn": { "$ref": "#/$defs/ids" },
|
|
60
|
+
"paths": { "$ref": "#/$defs/paths" },
|
|
61
|
+
"acceptanceIds": { "$ref": "#/$defs/nonEmptyIds" }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"$defs": {
|
|
67
|
+
"id": { "type": "string", "pattern": "^[a-z0-9]+(?:[.-][a-z0-9]+)*$" },
|
|
68
|
+
"text": { "type": "string", "minLength": 1 },
|
|
69
|
+
"digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
|
|
70
|
+
"path": { "type": "string", "minLength": 1 },
|
|
71
|
+
"ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/id" } },
|
|
72
|
+
"nonEmptyIds": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/id" } },
|
|
73
|
+
"paths": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/path" } },
|
|
74
|
+
"snapshots": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"additionalProperties": false,
|
|
77
|
+
"required": ["contract", "sourcesLock", "projectionsLock"],
|
|
78
|
+
"properties": {
|
|
79
|
+
"contract": { "$ref": "#/$defs/digest" },
|
|
80
|
+
"sourcesLock": { "$ref": "#/$defs/digest" },
|
|
81
|
+
"projectionsLock": { "$ref": "#/$defs/digest" }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ASSIST_BUNDLE_SCHEMA_VERSION } from "./assist.mjs";
|
|
2
|
+
import { DASHBOARD_SCHEMA_VERSION } from "./dashboard-model.mjs";
|
|
3
|
+
import {
|
|
4
|
+
ACTION_KINDS,
|
|
5
|
+
ACTION_PLAN_SCHEMA_VERSION,
|
|
6
|
+
CAPABILITIES_SCHEMA_VERSION,
|
|
7
|
+
COMMANDS,
|
|
8
|
+
EXCHANGE_PROTOCOL_VERSION,
|
|
9
|
+
PACKAGE_VERSION,
|
|
10
|
+
REVIEW_BUNDLE_SCHEMA_VERSION,
|
|
11
|
+
} from "./exchange-schema.mjs";
|
|
12
|
+
import { inspectProjectInitialization, loadProject } from "./project-store.mjs";
|
|
13
|
+
import { RENDERER_VERSION } from "./renderer.mjs";
|
|
14
|
+
import {
|
|
15
|
+
CONTEXT_BUDGET_UNIT,
|
|
16
|
+
INTEGRATION_REVIEW_BUNDLE_SCHEMA_VERSION,
|
|
17
|
+
STAGE_CONTEXT_BUNDLE_SCHEMA_VERSION,
|
|
18
|
+
STAGE_RECEIPT_SCHEMA_VERSION,
|
|
19
|
+
TASK_CONTEXT_PLAN_SCHEMA_VERSION,
|
|
20
|
+
} from "./task-context-schema.mjs";
|
|
21
|
+
|
|
22
|
+
function schemas() {
|
|
23
|
+
return {
|
|
24
|
+
actionPlan: ACTION_PLAN_SCHEMA_VERSION,
|
|
25
|
+
assistBundle: ASSIST_BUNDLE_SCHEMA_VERSION,
|
|
26
|
+
capabilities: CAPABILITIES_SCHEMA_VERSION,
|
|
27
|
+
contract: 2,
|
|
28
|
+
dashboardViewModel: DASHBOARD_SCHEMA_VERSION,
|
|
29
|
+
integrationReviewBundle: INTEGRATION_REVIEW_BUNDLE_SCHEMA_VERSION,
|
|
30
|
+
projectionLock: 1,
|
|
31
|
+
projectionRenderer: RENDERER_VERSION,
|
|
32
|
+
proposal: 1,
|
|
33
|
+
reviewBundle: REVIEW_BUNDLE_SCHEMA_VERSION,
|
|
34
|
+
sourceLock: 1,
|
|
35
|
+
stageContextBundle: STAGE_CONTEXT_BUNDLE_SCHEMA_VERSION,
|
|
36
|
+
stageReceipt: STAGE_RECEIPT_SCHEMA_VERSION,
|
|
37
|
+
taskContextPlan: TASK_CONTEXT_PLAN_SCHEMA_VERSION,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function buildCapabilities(root) {
|
|
42
|
+
const initialization = await inspectProjectInitialization(root);
|
|
43
|
+
let project = null;
|
|
44
|
+
if (initialization.status === "initialized") {
|
|
45
|
+
const loaded = await loadProject(root);
|
|
46
|
+
project = { id: loaded.contract.project.id, name: loaded.contract.project.name };
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
schemaVersion: CAPABILITIES_SCHEMA_VERSION,
|
|
50
|
+
package: { name: "frontend-project-context", version: PACKAGE_VERSION },
|
|
51
|
+
exchangeProtocolVersion: EXCHANGE_PROTOCOL_VERSION,
|
|
52
|
+
schemas: schemas(),
|
|
53
|
+
commands: [...COMMANDS],
|
|
54
|
+
actionKinds: [...ACTION_KINDS],
|
|
55
|
+
contextBudget: { unit: CONTEXT_BUDGET_UNIT, modelTokens: false, callerMustProvideLimit: true },
|
|
56
|
+
initialization: initialization.status,
|
|
57
|
+
initialized: initialization.status === "initialized",
|
|
58
|
+
project,
|
|
59
|
+
boundaries: {
|
|
60
|
+
provider: false,
|
|
61
|
+
agentRuntime: false,
|
|
62
|
+
git: false,
|
|
63
|
+
network: false,
|
|
64
|
+
dependencyInstallation: false,
|
|
65
|
+
automaticApproval: false,
|
|
66
|
+
businessCodeWrites: false,
|
|
67
|
+
taskExecution: false,
|
|
68
|
+
stagePathBodyReads: false,
|
|
69
|
+
applyPlan: false,
|
|
70
|
+
scheduler: false,
|
|
71
|
+
daemon: false,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -16,6 +16,7 @@ import { normalizeRelativePath, resolveExistingInside, resolveProjectRoot, resol
|
|
|
16
16
|
import { initializeProject, inspectProjectInitialization, loadProject } from "./project-store.mjs";
|
|
17
17
|
import { publishProjection } from "./projection-store.mjs";
|
|
18
18
|
import { renderContextBundle } from "./renderer.mjs";
|
|
19
|
+
import { buildIntegrationReviewBundleFiles, buildStageContextBundleFiles } from "./task-context.mjs";
|
|
19
20
|
|
|
20
21
|
const HELP = `project-context — model-neutral project contract compiler
|
|
21
22
|
|
|
@@ -38,6 +39,8 @@ Usage:
|
|
|
38
39
|
project-context dashboard --project PATH [--json]
|
|
39
40
|
project-context sync --project PATH [--changed-path RELATIVE_PATH...] [--json]
|
|
40
41
|
project-context preflight --project PATH --plan FILE [--json]
|
|
42
|
+
project-context stage-context --project PATH --plan FILE --stage STAGE_ID [--receipt FILE...] [--receipt-bundle FILE...] [--changed-path RELATIVE_PATH...] [--json]
|
|
43
|
+
project-context integration-review --project PATH --plan FILE [--receipt FILE...] [--receipt-bundle FILE...] [--main-changed-path RELATIVE_PATH...] [--branch-changed-path RELATIVE_PATH...] [--json]
|
|
41
44
|
|
|
42
45
|
All commands are read-only unless their own --write flag is present.
|
|
43
46
|
`;
|
|
@@ -45,9 +48,11 @@ const VALUE_FLAGS = new Set([
|
|
|
45
48
|
"project", "id", "name", "output", "proposal", "by", "task", "target", "rationale",
|
|
46
49
|
"kind", "pointer", "reference", "subject", "value", "value-json", "statement", "scope", "scope-path",
|
|
47
50
|
"verification", "verification-source", "verification-expected-json",
|
|
48
|
-
"expected-digest", "expected-item-digest", "expected-source-digest", "locale", "plan",
|
|
51
|
+
"expected-digest", "expected-item-digest", "expected-source-digest", "locale", "plan", "stage",
|
|
52
|
+
]);
|
|
53
|
+
const LIST_FLAGS = new Set([
|
|
54
|
+
"ids", "path", "changed-path", "sources", "overrides", "affected-items", "receipt", "receipt-bundle", "main-changed-path", "branch-changed-path",
|
|
49
55
|
]);
|
|
50
|
-
const LIST_FLAGS = new Set(["ids", "path", "changed-path", "sources", "overrides", "affected-items"]);
|
|
51
56
|
const BOOLEAN_FLAGS = new Set(["write", "json", "full-json", "help", "pending"]);
|
|
52
57
|
const COMMAND_OPTIONS = new Map([
|
|
53
58
|
["init", new Set(["project", "id", "name", "write", "json", "help"])],
|
|
@@ -81,6 +86,8 @@ const COMMAND_OPTIONS = new Map([
|
|
|
81
86
|
["dashboard", new Set(["project", "json", "help"])],
|
|
82
87
|
["sync", new Set(["project", "changed-path", "json", "help"])],
|
|
83
88
|
["preflight", new Set(["project", "plan", "json", "help"])],
|
|
89
|
+
["stage-context", new Set(["project", "plan", "stage", "receipt", "receipt-bundle", "changed-path", "json", "help"])],
|
|
90
|
+
["integration-review", new Set(["project", "plan", "receipt", "receipt-bundle", "main-changed-path", "branch-changed-path", "json", "help"])],
|
|
84
91
|
]);
|
|
85
92
|
|
|
86
93
|
export function parseArgs(argv) {
|
|
@@ -330,6 +337,26 @@ async function runCommand(command, options) {
|
|
|
330
337
|
const summary = `Preflight ${bundle.status}: ${bundle.summary.reviewable} reviewable, ${bundle.summary.blocked} blocked action(s).\n`;
|
|
331
338
|
return { exitCode: bundle.status === "reviewable" ? 0 : 1, stdout: jsonOrText(options, bundle, summary), stderr: "" };
|
|
332
339
|
}
|
|
340
|
+
if (command === "stage-context") {
|
|
341
|
+
const bundle = await buildStageContextBundleFiles(root, required(options, "plan"), {
|
|
342
|
+
stageId: required(options, "stage"),
|
|
343
|
+
receiptPaths: options.receipt ?? [],
|
|
344
|
+
receiptBundlePaths: options["receipt-bundle"] ?? [],
|
|
345
|
+
changedPaths: options["changed-path"] ?? [],
|
|
346
|
+
});
|
|
347
|
+
const summary = `Stage context ${bundle.status}: ${bundle.stage.id}; ${bundle.contractItems.length} contract item(s), ${bundle.readTargets.length} read target(s), ${bundle.budget.usedUtf8Bytes}/${bundle.budget.maxUtf8Bytes} UTF-8 bytes.\n`;
|
|
348
|
+
return { exitCode: bundle.status === "ready" ? 0 : 1, stdout: jsonOrText(options, bundle, summary), stderr: "" };
|
|
349
|
+
}
|
|
350
|
+
if (command === "integration-review") {
|
|
351
|
+
const bundle = await buildIntegrationReviewBundleFiles(root, required(options, "plan"), {
|
|
352
|
+
receiptPaths: options.receipt ?? [],
|
|
353
|
+
receiptBundlePaths: options["receipt-bundle"] ?? [],
|
|
354
|
+
mainChangedPaths: options["main-changed-path"] ?? [],
|
|
355
|
+
branchChangedPaths: options["branch-changed-path"] ?? [],
|
|
356
|
+
});
|
|
357
|
+
const summary = `Integration review ${bundle.status}: ${bundle.findings.length} finding(s), ${bundle.contractOverlapItemIds.length} contract overlap(s), ${bundle.decisionCandidates.length} decision candidate(s).\n`;
|
|
358
|
+
return { exitCode: bundle.status === "reviewable" ? 0 : 1, stdout: jsonOrText(options, bundle, summary), stderr: "" };
|
|
359
|
+
}
|
|
333
360
|
const project = await loadProject(root);
|
|
334
361
|
if (command === "register") {
|
|
335
362
|
const result = await registerSource(root, project, {
|
|
@@ -2,7 +2,7 @@ import { canonicalValue, digestJson, validateJsonValue } from "./canonical-json.
|
|
|
2
2
|
import { fail } from "./errors.mjs";
|
|
3
3
|
import { normalizeRelativePath } from "./path-policy.mjs";
|
|
4
4
|
|
|
5
|
-
export const PACKAGE_VERSION = "1.
|
|
5
|
+
export const PACKAGE_VERSION = "1.3.1";
|
|
6
6
|
export const EXCHANGE_PROTOCOL_VERSION = 1;
|
|
7
7
|
export const ACTION_PLAN_SCHEMA_VERSION = 1;
|
|
8
8
|
export const REVIEW_BUNDLE_SCHEMA_VERSION = 1;
|
|
@@ -21,8 +21,8 @@ export const ACTION_KINDS = Object.freeze([
|
|
|
21
21
|
|
|
22
22
|
export const COMMANDS = Object.freeze([
|
|
23
23
|
"accept-source-change", "approve", "capabilities", "check", "context", "dashboard", "deprecate",
|
|
24
|
-
"deprecate-source", "discover", "init", "preflight", "propose", "publish", "register",
|
|
25
|
-
"revise", "setup", "sync",
|
|
24
|
+
"deprecate-source", "discover", "init", "integration-review", "preflight", "propose", "publish", "register",
|
|
25
|
+
"review-source", "revise", "setup", "stage-context", "sync",
|
|
26
26
|
]);
|
|
27
27
|
|
|
28
28
|
const ACTION_KIND_SET = new Set(ACTION_KINDS);
|
|
@@ -3,17 +3,10 @@ import { approvePendingItems, approveProposal } from "./approver.mjs";
|
|
|
3
3
|
import { registerSource, buildItemProposal } from "./authoring.mjs";
|
|
4
4
|
import { blockingContextFindings, checkProject } from "./checker.mjs";
|
|
5
5
|
import { canonicalJson, digestJson, prettyCanonicalJson, sha256 } from "./canonical-json.mjs";
|
|
6
|
-
import { DASHBOARD_SCHEMA_VERSION } from "./dashboard-model.mjs";
|
|
7
6
|
import { ProjectContextError, fail } from "./errors.mjs";
|
|
8
7
|
import {
|
|
9
|
-
ACTION_KINDS,
|
|
10
|
-
ACTION_PLAN_SCHEMA_VERSION,
|
|
11
8
|
assertActionPlanConflictFree,
|
|
12
|
-
CAPABILITIES_SCHEMA_VERSION,
|
|
13
|
-
COMMANDS,
|
|
14
|
-
EXCHANGE_PROTOCOL_VERSION,
|
|
15
9
|
itemPrimitiveInput,
|
|
16
|
-
PACKAGE_VERSION,
|
|
17
10
|
REVIEW_BUNDLE_SCHEMA_VERSION,
|
|
18
11
|
validateActionPlan,
|
|
19
12
|
validateReviewBundle,
|
|
@@ -21,17 +14,12 @@ import {
|
|
|
21
14
|
import { readJsonFile } from "./io.mjs";
|
|
22
15
|
import { acceptSourceChange, deprecateItem, deprecateSource, reviewSource, reviseItem } from "./maintenance.mjs";
|
|
23
16
|
import { resolveExistingInside, resolveWritableInside } from "./path-policy.mjs";
|
|
24
|
-
import {
|
|
17
|
+
import { loadProject } from "./project-store.mjs";
|
|
25
18
|
import { publishProjection } from "./projection-store.mjs";
|
|
26
|
-
|
|
27
|
-
import { ASSIST_BUNDLE_SCHEMA_VERSION } from "./assist.mjs";
|
|
19
|
+
export { buildCapabilities } from "./capabilities.mjs";
|
|
28
20
|
|
|
29
21
|
const INTERNAL_AUTHORITY_SENTINEL = "exchange-preflight-not-authority";
|
|
30
22
|
const INTERNAL_TIMESTAMP = "1970-01-01T00:00:00.000Z";
|
|
31
|
-
const CONTRACT_SCHEMA_VERSION = 2;
|
|
32
|
-
const PROPOSAL_SCHEMA_VERSION = 1;
|
|
33
|
-
const SOURCE_LOCK_SCHEMA_VERSION = 1;
|
|
34
|
-
const PROJECTION_LOCK_SCHEMA_VERSION = 1;
|
|
35
23
|
const GROUP_BY_ACTION = new Map([
|
|
36
24
|
["accept-source-change", "source-change"],
|
|
37
25
|
["register-source", "source-change"],
|
|
@@ -47,52 +35,6 @@ function uniqueSorted(values) {
|
|
|
47
35
|
return [...new Set(values)].sort((left, right) => left.localeCompare(right));
|
|
48
36
|
}
|
|
49
37
|
|
|
50
|
-
function schemas() {
|
|
51
|
-
return {
|
|
52
|
-
actionPlan: ACTION_PLAN_SCHEMA_VERSION,
|
|
53
|
-
assistBundle: ASSIST_BUNDLE_SCHEMA_VERSION,
|
|
54
|
-
capabilities: CAPABILITIES_SCHEMA_VERSION,
|
|
55
|
-
contract: CONTRACT_SCHEMA_VERSION,
|
|
56
|
-
dashboardViewModel: DASHBOARD_SCHEMA_VERSION,
|
|
57
|
-
projectionLock: PROJECTION_LOCK_SCHEMA_VERSION,
|
|
58
|
-
projectionRenderer: RENDERER_VERSION,
|
|
59
|
-
proposal: PROPOSAL_SCHEMA_VERSION,
|
|
60
|
-
reviewBundle: REVIEW_BUNDLE_SCHEMA_VERSION,
|
|
61
|
-
sourceLock: SOURCE_LOCK_SCHEMA_VERSION,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export async function buildCapabilities(root) {
|
|
66
|
-
const initialization = await inspectProjectInitialization(root);
|
|
67
|
-
let project = null;
|
|
68
|
-
if (initialization.status === "initialized") {
|
|
69
|
-
const loaded = await loadProject(root);
|
|
70
|
-
project = { id: loaded.contract.project.id, name: loaded.contract.project.name };
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
schemaVersion: CAPABILITIES_SCHEMA_VERSION,
|
|
74
|
-
package: { name: "frontend-project-context", version: PACKAGE_VERSION },
|
|
75
|
-
exchangeProtocolVersion: EXCHANGE_PROTOCOL_VERSION,
|
|
76
|
-
schemas: schemas(),
|
|
77
|
-
commands: [...COMMANDS],
|
|
78
|
-
actionKinds: [...ACTION_KINDS],
|
|
79
|
-
initialization: initialization.status,
|
|
80
|
-
initialized: initialization.status === "initialized",
|
|
81
|
-
project,
|
|
82
|
-
boundaries: {
|
|
83
|
-
provider: false,
|
|
84
|
-
agentRuntime: false,
|
|
85
|
-
git: false,
|
|
86
|
-
network: false,
|
|
87
|
-
dependencyInstallation: false,
|
|
88
|
-
automaticApproval: false,
|
|
89
|
-
businessCodeWrites: false,
|
|
90
|
-
applyPlan: false,
|
|
91
|
-
scheduler: false,
|
|
92
|
-
daemon: false,
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
38
|
|
|
97
39
|
function allProjectionPaths(project) {
|
|
98
40
|
return project.projectionsLock.projections.map((entry) => entry.path).sort();
|