archctx-contracts 0.8.1 → 0.9.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/fixtures/invalid/projection-pr-verification-unrendered-equivalence.json +15 -0
- package/fixtures/invalid/projection-publish-run-foreign-branch.json +19 -0
- package/fixtures/valid/archctx-capabilities.json +2 -2
- package/fixtures/valid/product-version-manifest.json +5 -5
- package/fixtures/valid/projection-pr-verification.json +15 -0
- package/fixtures/valid/projection-publish-run.json +19 -0
- package/fixtures/valid/projection-publish-status.json +29 -0
- package/package.json +1 -1
- package/schemas/runtime/archctx-capabilities.schema.json +1 -1
- package/schemas/runtime/projection-pr-verification.schema.json +34 -0
- package/schemas/runtime/projection-publish-run.schema.json +74 -0
- package/schemas/runtime/projection-publish-status.schema.json +36 -0
- package/src/index.ts +1 -0
- package/src/ports.ts +1 -1
- package/src/product-version.ts +1 -1
- package/src/projection-writer.ts +116 -0
- package/src/projection.ts +2 -0
- package/src/schema.ts +2 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "archcontext.projection-pr-verification/v1",
|
|
3
|
+
"base": "origin/main",
|
|
4
|
+
"baseSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
5
|
+
"headSha": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
6
|
+
"mergeBase": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
7
|
+
"changedPaths": ["docs/architecture/modules/capability-app.md", "src/app.ts"],
|
|
8
|
+
"nonGeneratedPaths": ["src/app.ts"],
|
|
9
|
+
"humanEditedPaths": [],
|
|
10
|
+
"generatedOnly": false,
|
|
11
|
+
"renderEquivalent": true,
|
|
12
|
+
"differingPaths": [],
|
|
13
|
+
"projectionStatus": "noop",
|
|
14
|
+
"verdict": "touches-non-generated"
|
|
15
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "archcontext.projection-publish-run/v1",
|
|
3
|
+
"result": "published",
|
|
4
|
+
"remote": "origin",
|
|
5
|
+
"base": "main",
|
|
6
|
+
"branch": "main",
|
|
7
|
+
"baseSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
8
|
+
"publishedCommit": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
9
|
+
"pushed": true,
|
|
10
|
+
"pullRequest": null,
|
|
11
|
+
"publisher": "none",
|
|
12
|
+
"files": ["docs/architecture/modules/capability-app.md"],
|
|
13
|
+
"projectionStatus": "applied",
|
|
14
|
+
"humanActions": [],
|
|
15
|
+
"error": null,
|
|
16
|
+
"startedAt": "2026-10-20T08:00:00.000Z",
|
|
17
|
+
"finishedAt": "2026-10-20T08:00:09.000Z",
|
|
18
|
+
"iterations": 1
|
|
19
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "archcontext.capabilities/v1",
|
|
3
|
-
"package": { "name": "archctx", "version": "0.
|
|
3
|
+
"package": { "name": "archctx", "version": "0.9.1" },
|
|
4
4
|
"protocols": {
|
|
5
5
|
"projectionRequest": "archcontext.projection-request/v1",
|
|
6
6
|
"projectionResult": "archcontext.projection-result/v2",
|
|
@@ -10,5 +10,5 @@
|
|
|
10
10
|
"architectureDocs": "archcontext.docs-renderer/v6",
|
|
11
11
|
"agentContext": "archcontext.agent-context-renderer/v1"
|
|
12
12
|
},
|
|
13
|
-
"features": ["architecture-change-capabilities-v1", "architecture-debt-v1", "architecture-docs-renderer-v2", "architecture-refresh-signal-v1", "capability-dependencies-declared-v1", "capability-dependencies-v1", "changeset-entity-operations-v1", "changeset-ownership-delta-v1", "code-facts-unavailable-error-v1", "docs-anchors-v1", "flow-selector-check-v1", "module-statistics-v1", "native-context-export-v1", "projection-apply-readback-v1", "projection-apply-receipt-v1", "projection-apply-recovery-v1", "projection-apply-replay-restore-v1", "projection-apply-replay-v1", "projection-architecture-debt-v1", "projection-capability-isolation-v1", "projection-change-classification-v1", "projection-check-freshness-v1", "projection-freshness-v1", "projection-manifest-contract-v3", "projection-observed-major-change-acceptance-v1", "projection-orphan-review-v1", "projection-preview-v1", "projection-prior-committed-applies-v1", "projection-protocol-v2", "projection-snapshot-v1", "recommendation-scan-decision-v1", "recommendation-v3", "refactor-assessment-v1", "refactor-observation-evidence-v1", "refactor-resolution-v1", "refactor-scan-limits-v1", "refactor-scan-untracked-count-v1"]
|
|
13
|
+
"features": ["architecture-change-capabilities-v1", "architecture-debt-v1", "architecture-docs-renderer-v2", "architecture-refresh-signal-v1", "capability-dependencies-declared-v1", "capability-dependencies-v1", "changeset-entity-operations-v1", "changeset-ownership-delta-v1", "code-facts-unavailable-error-v1", "docs-anchors-v1", "flow-selector-check-v1", "module-statistics-v1", "native-context-export-v1", "projection-apply-readback-v1", "projection-apply-receipt-v1", "projection-apply-recovery-v1", "projection-apply-replay-restore-v1", "projection-apply-replay-v1", "projection-architecture-debt-v1", "projection-capability-isolation-v1", "projection-change-classification-v1", "projection-check-freshness-v1", "projection-freshness-v1", "projection-manifest-contract-v3", "projection-observed-major-change-acceptance-v1", "projection-orphan-review-v1", "projection-preview-v1", "projection-prior-committed-applies-v1", "projection-protocol-v2", "projection-publish-v1", "projection-snapshot-v1", "projection-verify-pr-v1", "recommendation-scan-decision-v1", "recommendation-v3", "refactor-assessment-v1", "refactor-observation-evidence-v1", "refactor-resolution-v1", "refactor-scan-limits-v1", "refactor-scan-untracked-count-v1"]
|
|
14
14
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": "archcontext.product-version-manifest/v1",
|
|
3
3
|
"product": {
|
|
4
4
|
"name": "archctx",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.9.1",
|
|
6
6
|
"distribution": "one-package"
|
|
7
7
|
},
|
|
8
8
|
"packageManager": "bun@1.4.3",
|
|
@@ -12,25 +12,25 @@
|
|
|
12
12
|
"surfaces": {
|
|
13
13
|
"cli": {
|
|
14
14
|
"packageName": "@archcontext/surfaces",
|
|
15
|
-
"version": "0.
|
|
15
|
+
"version": "0.9.1",
|
|
16
16
|
"entrypoint": "archctx"
|
|
17
17
|
},
|
|
18
18
|
"daemon": {
|
|
19
19
|
"packageName": "@archcontext/local-runtime",
|
|
20
|
-
"version": "0.
|
|
20
|
+
"version": "0.9.1",
|
|
21
21
|
"entrypoint": "archctx daemon start",
|
|
22
22
|
"rpcSchemaVersion": "archcontext.runtime-rpc/v2"
|
|
23
23
|
},
|
|
24
24
|
"mcp": {
|
|
25
25
|
"packageName": "@archcontext/surfaces",
|
|
26
|
-
"version": "0.
|
|
26
|
+
"version": "0.9.1",
|
|
27
27
|
"entrypoint": "archctx mcp",
|
|
28
28
|
"transport": "stdio"
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"schemas": {
|
|
32
32
|
"schemaSetVersion": "2026-06-25.al0-ledger",
|
|
33
|
-
"contractsPackageVersion": "0.
|
|
33
|
+
"contractsPackageVersion": "0.9.1",
|
|
34
34
|
"reviewChallenge": "archcontext.review-challenge/v2",
|
|
35
35
|
"attestation": "archcontext.attestation/v2",
|
|
36
36
|
"deviceIdentity": "archcontext.device-identity/v1",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "archcontext.projection-pr-verification/v1",
|
|
3
|
+
"base": "origin/main",
|
|
4
|
+
"baseSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
5
|
+
"headSha": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
6
|
+
"mergeBase": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
7
|
+
"changedPaths": ["docs/architecture/.projection-manifest.json", "docs/architecture/modules/capability-app.md"],
|
|
8
|
+
"nonGeneratedPaths": [],
|
|
9
|
+
"humanEditedPaths": [],
|
|
10
|
+
"generatedOnly": true,
|
|
11
|
+
"renderEquivalent": true,
|
|
12
|
+
"differingPaths": [],
|
|
13
|
+
"projectionStatus": "noop",
|
|
14
|
+
"verdict": "generated-only-render-equivalent"
|
|
15
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "archcontext.projection-publish-run/v1",
|
|
3
|
+
"result": "published",
|
|
4
|
+
"remote": "origin",
|
|
5
|
+
"base": "main",
|
|
6
|
+
"branch": "archctx/projection",
|
|
7
|
+
"baseSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
8
|
+
"publishedCommit": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
9
|
+
"pushed": true,
|
|
10
|
+
"pullRequest": { "url": "https://github.com/example/repo/pull/12", "number": 12 },
|
|
11
|
+
"publisher": "gh",
|
|
12
|
+
"files": ["docs/architecture/.projection-manifest.json", "docs/architecture/modules/capability-app.md"],
|
|
13
|
+
"projectionStatus": "applied",
|
|
14
|
+
"humanActions": [],
|
|
15
|
+
"error": null,
|
|
16
|
+
"startedAt": "2026-10-20T08:00:00.000Z",
|
|
17
|
+
"finishedAt": "2026-10-20T08:00:09.000Z",
|
|
18
|
+
"iterations": 1
|
|
19
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "archcontext.projection-publish-status/v1",
|
|
3
|
+
"remote": "origin",
|
|
4
|
+
"base": "main",
|
|
5
|
+
"branch": "archctx/projection",
|
|
6
|
+
"worktreePath": "/Users/example/Library/Application Support/ArchContext/repositories/repo.0123456789abcdef/projection-writer/0123456789abcdef/worktree",
|
|
7
|
+
"running": null,
|
|
8
|
+
"lastProcessedSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
9
|
+
"lastSuccessfulSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
10
|
+
"lastRun": {
|
|
11
|
+
"schemaVersion": "archcontext.projection-publish-run/v1",
|
|
12
|
+
"result": "failed",
|
|
13
|
+
"remote": "origin",
|
|
14
|
+
"base": "main",
|
|
15
|
+
"branch": "archctx/projection",
|
|
16
|
+
"baseSha": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
17
|
+
"publishedCommit": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
18
|
+
"pushed": true,
|
|
19
|
+
"pullRequest": null,
|
|
20
|
+
"publisher": "gh",
|
|
21
|
+
"files": ["docs/architecture/modules/capability-app.md"],
|
|
22
|
+
"projectionStatus": "applied",
|
|
23
|
+
"humanActions": [],
|
|
24
|
+
"error": { "code": "AC_PRECONDITION_FAILED", "reasonCode": "projection-publisher-failed", "message": "gh publisher failed: gh pr list failed: not logged in" },
|
|
25
|
+
"startedAt": "2026-10-20T08:00:00.000Z",
|
|
26
|
+
"finishedAt": "2026-10-20T08:00:09.000Z",
|
|
27
|
+
"iterations": 1
|
|
28
|
+
}
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"type": "string",
|
|
44
44
|
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*-v[0-9]+$",
|
|
45
45
|
"description": "One feature flag: a lowercase kebab-case name that ends in a version suffix (-v1, -v2, ...). The pattern is open, so a validator built from this schema accepts flags that a later archctx adds. A consumer must ignore a flag it does not know. examples lists the flags this schema version knows.",
|
|
46
|
-
"examples": ["architecture-change-capabilities-v1", "architecture-debt-v1", "architecture-docs-renderer-v2", "architecture-refresh-signal-v1", "capability-dependencies-declared-v1", "capability-dependencies-v1", "changeset-entity-operations-v1", "changeset-ownership-delta-v1", "code-facts-unavailable-error-v1", "docs-anchors-v1", "flow-selector-check-v1", "module-statistics-v1", "native-context-export-v1", "projection-apply-readback-v1", "projection-apply-receipt-v1", "projection-apply-recovery-v1", "projection-apply-replay-restore-v1", "projection-apply-replay-v1", "projection-architecture-debt-v1", "projection-capability-isolation-v1", "projection-change-classification-v1", "projection-check-freshness-v1", "projection-freshness-v1", "projection-manifest-contract-v3", "projection-observed-major-change-acceptance-v1", "projection-orphan-review-v1", "projection-preview-v1", "projection-prior-committed-applies-v1", "projection-protocol-v2", "projection-snapshot-v1", "recommendation-scan-decision-v1", "recommendation-v3", "refactor-assessment-v1", "refactor-observation-evidence-v1", "refactor-resolution-v1", "refactor-scan-limits-v1", "refactor-scan-untracked-count-v1"]
|
|
46
|
+
"examples": ["architecture-change-capabilities-v1", "architecture-debt-v1", "architecture-docs-renderer-v2", "architecture-refresh-signal-v1", "capability-dependencies-declared-v1", "capability-dependencies-v1", "changeset-entity-operations-v1", "changeset-ownership-delta-v1", "code-facts-unavailable-error-v1", "docs-anchors-v1", "flow-selector-check-v1", "module-statistics-v1", "native-context-export-v1", "projection-apply-readback-v1", "projection-apply-receipt-v1", "projection-apply-recovery-v1", "projection-apply-replay-restore-v1", "projection-apply-replay-v1", "projection-architecture-debt-v1", "projection-capability-isolation-v1", "projection-change-classification-v1", "projection-check-freshness-v1", "projection-freshness-v1", "projection-manifest-contract-v3", "projection-observed-major-change-acceptance-v1", "projection-orphan-review-v1", "projection-preview-v1", "projection-prior-committed-applies-v1", "projection-protocol-v2", "projection-publish-v1", "projection-snapshot-v1", "projection-verify-pr-v1", "recommendation-scan-decision-v1", "recommendation-v3", "refactor-assessment-v1", "refactor-observation-evidence-v1", "refactor-resolution-v1", "refactor-scan-limits-v1", "refactor-scan-untracked-count-v1"]
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://archcontext.dev/schemas/runtime/projection-pr-verification.schema.json",
|
|
4
|
+
"title": "ProjectionPrVerificationV1",
|
|
5
|
+
"description": "Result of `archctx projection verify-pr --base <ref>` for the checked-out pull request head. A path is generated only when it is the projection manifest, a manifest target path or an agent-context target path at HEAD or at the merge base; for mixed-ownership targets the text outside the generated regions must also be unchanged. A diff with any other change is answered from the diff alone, with no render. generated-only-render-equivalent proves that the generated files and generated regions at HEAD equal a fresh render there and that no text outside those regions changed; it says nothing about whether the rendered content is desirable. The envelope is ok for every valid evaluation. Consumers detect it through the projection-verify-pr-v1 capability.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["schemaVersion", "base", "baseSha", "headSha", "mergeBase", "changedPaths", "nonGeneratedPaths", "humanEditedPaths", "generatedOnly", "renderEquivalent", "differingPaths", "projectionStatus", "verdict"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": { "const": "archcontext.projection-pr-verification/v1" },
|
|
11
|
+
"base": { "type": "string", "minLength": 1 },
|
|
12
|
+
"baseSha": { "$ref": "#/$defs/sha" },
|
|
13
|
+
"headSha": { "$ref": "#/$defs/sha" },
|
|
14
|
+
"mergeBase": { "$ref": "#/$defs/sha" },
|
|
15
|
+
"changedPaths": { "$ref": "#/$defs/paths", "description": "Paths changed between the merge base and HEAD, without rename detection, sorted." },
|
|
16
|
+
"nonGeneratedPaths": { "$ref": "#/$defs/paths", "description": "Changed paths that are not generated outputs: not the projection manifest, not a manifest target path and not an agent-context target path at HEAD or at the merge base, plus every humanEditedPaths entry." },
|
|
17
|
+
"humanEditedPaths": { "$ref": "#/$defs/paths", "description": "Mixed-ownership targets (manifest ownership mixed, and every agent-context target) whose text outside the generated regions differs between the merge base and HEAD, whose regions cannot be delimited, or which were added or deleted. They are also in nonGeneratedPaths and are never rendered." },
|
|
18
|
+
"generatedOnly": { "type": "boolean", "description": "True when the diff is non-empty and every changed path is a generated output with no change outside its generated regions." },
|
|
19
|
+
"renderEquivalent": { "type": ["boolean", "null"], "description": "Whether the generated files and regions at HEAD equal a fresh render (a check status of noop). Null when no render ran." },
|
|
20
|
+
"differingPaths": { "$ref": "#/$defs/paths", "description": "Paths the check would change at HEAD." },
|
|
21
|
+
"projectionStatus": { "type": ["string", "null"] },
|
|
22
|
+
"verdict": { "enum": ["generated-only-not-render-equivalent", "generated-only-render-equivalent", "no-changes", "touches-non-generated"] }
|
|
23
|
+
},
|
|
24
|
+
"allOf": [
|
|
25
|
+
{ "if": { "properties": { "verdict": { "const": "generated-only-render-equivalent" } } }, "then": { "properties": { "generatedOnly": { "const": true }, "renderEquivalent": { "const": true }, "nonGeneratedPaths": { "maxItems": 0 }, "humanEditedPaths": { "maxItems": 0 } } } },
|
|
26
|
+
{ "if": { "properties": { "verdict": { "const": "generated-only-not-render-equivalent" } } }, "then": { "properties": { "generatedOnly": { "const": true }, "renderEquivalent": { "const": false }, "nonGeneratedPaths": { "maxItems": 0 }, "humanEditedPaths": { "maxItems": 0 } } } },
|
|
27
|
+
{ "if": { "properties": { "verdict": { "const": "touches-non-generated" } } }, "then": { "properties": { "generatedOnly": { "const": false }, "renderEquivalent": { "type": "null" }, "nonGeneratedPaths": { "minItems": 1 } } } },
|
|
28
|
+
{ "if": { "properties": { "verdict": { "const": "no-changes" } } }, "then": { "properties": { "generatedOnly": { "const": false }, "renderEquivalent": { "type": "null" }, "changedPaths": { "maxItems": 0 }, "humanEditedPaths": { "maxItems": 0 } } } }
|
|
29
|
+
],
|
|
30
|
+
"$defs": {
|
|
31
|
+
"sha": { "type": "string", "pattern": "^[a-f0-9]{40}$" },
|
|
32
|
+
"paths": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://archcontext.dev/schemas/runtime/projection-publish-run.schema.json",
|
|
4
|
+
"title": "ProjectionPublishRunV1",
|
|
5
|
+
"description": "One run of `archctx projection publish` (the envelope data, and the writer state's lastRun). The writer keeps one rolling archctx/* branch equal to the base tip plus exactly one commit that touches generated projection outputs only. Every result except failed is an ok envelope. Consumers detect it through the projection-publish-v1 capability.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["schemaVersion", "result", "remote", "base", "branch", "baseSha", "publishedCommit", "pushed", "pullRequest", "publisher", "files", "projectionStatus", "humanActions", "error", "startedAt", "finishedAt", "iterations"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": { "const": "archcontext.projection-publish-run/v1" },
|
|
11
|
+
"result": { "enum": ["already-processed", "busy", "failed", "human-action-required", "published", "up-to-date"] },
|
|
12
|
+
"remote": { "type": "string", "minLength": 1 },
|
|
13
|
+
"base": { "type": "string", "minLength": 1 },
|
|
14
|
+
"branch": { "type": "string", "pattern": "^archctx/.+", "description": "The rolling branch. The writer never pushes to any ref outside archctx/." },
|
|
15
|
+
"baseSha": { "oneOf": [{ "$ref": "#/$defs/sha" }, { "type": "null" }], "description": "The base tip this run evaluated; null when the run stopped before resolving one." },
|
|
16
|
+
"publishedCommit": { "oneOf": [{ "$ref": "#/$defs/sha" }, { "type": "null" }], "description": "The rolling branch tip that carries this base's projection, pushed by this run or an earlier one." },
|
|
17
|
+
"pushed": { "type": "boolean", "description": "True only when this run moved the remote rolling branch." },
|
|
18
|
+
"pullRequest": {
|
|
19
|
+
"oneOf": [
|
|
20
|
+
{
|
|
21
|
+
"type": "object",
|
|
22
|
+
"additionalProperties": false,
|
|
23
|
+
"properties": {
|
|
24
|
+
"url": { "type": "string", "minLength": 1 },
|
|
25
|
+
"number": { "type": "integer", "minimum": 1 }
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{ "type": "null" }
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
"publisher": { "enum": ["command", "gh", "none"] },
|
|
32
|
+
"files": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 }, "description": "Repository-relative generated paths the published commit changes, sorted. Paths only, never contents." },
|
|
33
|
+
"projectionStatus": { "type": ["string", "null"], "description": "ProjectionResultV2.status of the apply this run made, or null without one." },
|
|
34
|
+
"humanActions": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"items": {
|
|
37
|
+
"type": "object",
|
|
38
|
+
"additionalProperties": false,
|
|
39
|
+
"required": ["reasonCode"],
|
|
40
|
+
"properties": {
|
|
41
|
+
"reasonCode": { "type": "string", "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" },
|
|
42
|
+
"path": { "type": "string", "minLength": 1 }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"error": {
|
|
47
|
+
"oneOf": [
|
|
48
|
+
{
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": false,
|
|
51
|
+
"required": ["code", "message"],
|
|
52
|
+
"properties": {
|
|
53
|
+
"code": { "type": "string", "pattern": "^AC_[A-Z0-9_]+$" },
|
|
54
|
+
"reasonCode": { "type": "string", "minLength": 1 },
|
|
55
|
+
"message": { "type": "string" }
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{ "type": "null" }
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"startedAt": { "type": "string", "minLength": 1 },
|
|
62
|
+
"finishedAt": { "type": "string", "minLength": 1 },
|
|
63
|
+
"iterations": { "type": "integer", "minimum": 0, "maximum": 3, "description": "Base tips evaluated in this run; above 1 when the base moved while the run worked." },
|
|
64
|
+
"holderPid": { "type": "integer", "minimum": 1, "description": "Present on busy: the pid of the live writer that holds the lock." }
|
|
65
|
+
},
|
|
66
|
+
"allOf": [
|
|
67
|
+
{ "if": { "properties": { "result": { "const": "failed" } } }, "then": { "properties": { "error": { "type": "object" } } }, "else": { "properties": { "error": { "type": "null" } } } },
|
|
68
|
+
{ "if": { "properties": { "result": { "const": "busy" } } }, "then": { "required": ["holderPid"] }, "else": { "not": { "required": ["holderPid"] } } },
|
|
69
|
+
{ "if": { "properties": { "result": { "const": "published" } } }, "then": { "properties": { "publishedCommit": { "$ref": "#/$defs/sha" }, "baseSha": { "$ref": "#/$defs/sha" } } } }
|
|
70
|
+
],
|
|
71
|
+
"$defs": {
|
|
72
|
+
"sha": { "type": "string", "pattern": "^[a-f0-9]{40}$" }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://archcontext.dev/schemas/runtime/projection-publish-status.schema.json",
|
|
4
|
+
"title": "ProjectionPublishStatusV1",
|
|
5
|
+
"description": "Read-only result of `archctx projection publish-status`: the projection writer state for one (remote, base), shared by every checkout of the repository. Consumers detect it through the projection-publish-v1 capability.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["schemaVersion", "remote", "base", "branch", "worktreePath", "running", "lastProcessedSha", "lastSuccessfulSha", "lastRun"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": { "const": "archcontext.projection-publish-status/v1" },
|
|
11
|
+
"remote": { "type": "string", "minLength": 1 },
|
|
12
|
+
"base": { "type": "string", "minLength": 1 },
|
|
13
|
+
"branch": { "oneOf": [{ "type": "string", "pattern": "^archctx/.+" }, { "type": "null" }], "description": "The rolling branch of the last locked run, or null before the first." },
|
|
14
|
+
"worktreePath": { "type": "string", "minLength": 1, "description": "The writer-owned worktree; run `codegraph init <worktreePath>` once when code facts are required." },
|
|
15
|
+
"running": {
|
|
16
|
+
"oneOf": [
|
|
17
|
+
{
|
|
18
|
+
"type": "object",
|
|
19
|
+
"additionalProperties": false,
|
|
20
|
+
"required": ["pid", "startedAt"],
|
|
21
|
+
"properties": {
|
|
22
|
+
"pid": { "type": "integer", "minimum": 1 },
|
|
23
|
+
"startedAt": { "type": "string" }
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{ "type": "null" }
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"lastProcessedSha": { "oneOf": [{ "$ref": "#/$defs/sha" }, { "type": "null" }], "description": "The last base tip a run evaluated." },
|
|
30
|
+
"lastSuccessfulSha": { "oneOf": [{ "$ref": "#/$defs/sha" }, { "type": "null" }], "description": "The last base tip a run published or found up to date." },
|
|
31
|
+
"lastRun": { "oneOf": [{ "$ref": "projection-publish-run.schema.json" }, { "type": "null" }] }
|
|
32
|
+
},
|
|
33
|
+
"$defs": {
|
|
34
|
+
"sha": { "type": "string", "pattern": "^[a-f0-9]{40}$" }
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from "./ports";
|
|
|
11
11
|
export * from "./practices";
|
|
12
12
|
export * from "./projection";
|
|
13
13
|
export * from "./projection-recovery";
|
|
14
|
+
export * from "./projection-writer";
|
|
14
15
|
export * from "./projection-manifest";
|
|
15
16
|
export * from "./product-version";
|
|
16
17
|
export * from "./refactor";
|
package/src/ports.ts
CHANGED
|
@@ -815,7 +815,7 @@ export interface ReviewCheckoutGitPort {
|
|
|
815
815
|
}
|
|
816
816
|
|
|
817
817
|
export interface NonLocalEgressChannel {
|
|
818
|
-
channel: "context7" | "agent-audit" | "github-issue-publishing" | "npm-update-check" | "codegraph-telemetry";
|
|
818
|
+
channel: "context7" | "agent-audit" | "github-issue-publishing" | "npm-update-check" | "projection-publishing" | "codegraph-telemetry";
|
|
819
819
|
destination: string;
|
|
820
820
|
trigger: string;
|
|
821
821
|
data: string;
|
package/src/product-version.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const ARCHCONTEXT_PRODUCT_NAME = "archctx";
|
|
2
|
-
export const ARCHCONTEXT_PRODUCT_VERSION = "0.
|
|
2
|
+
export const ARCHCONTEXT_PRODUCT_VERSION = "0.9.1";
|
|
3
3
|
export const ARCHCONTEXT_PACKAGE_MANAGER = "bun@1.4.3";
|
|
4
4
|
export const ARCHCONTEXT_NODE_RANGE = ">=22.22 <26";
|
|
5
5
|
export const LOCAL_RUNTIME_RPC_SCHEMA_VERSION = "archcontext.runtime-rpc/v2";
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { ProjectionHumanActionReasonCode } from "./projection";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Projection writer mode (issue #379, ADR-0048): `archctx projection publish` keeps one rolling
|
|
5
|
+
* pull request branch (`archctx/...`) equal to the base tip plus exactly one commit that touches
|
|
6
|
+
* generated projection outputs only, and `archctx projection verify-pr` lets downstream CI check
|
|
7
|
+
* such a pull request without trusting its author.
|
|
8
|
+
*/
|
|
9
|
+
export const PROJECTION_PUBLISH_RUN_SCHEMA_VERSION = "archcontext.projection-publish-run/v1" as const;
|
|
10
|
+
export const PROJECTION_PUBLISH_STATUS_SCHEMA_VERSION = "archcontext.projection-publish-status/v1" as const;
|
|
11
|
+
export const PROJECTION_PR_VERIFICATION_SCHEMA_VERSION = "archcontext.projection-pr-verification/v1" as const;
|
|
12
|
+
|
|
13
|
+
/** The only ref namespace the writer ever pushes to. */
|
|
14
|
+
export const PROJECTION_WRITER_BRANCH_PREFIX = "archctx/";
|
|
15
|
+
export const PROJECTION_WRITER_DEFAULT_BRANCH = "archctx/projection";
|
|
16
|
+
|
|
17
|
+
export const PROJECTION_PUBLISH_RESULTS = [
|
|
18
|
+
"already-processed",
|
|
19
|
+
"busy",
|
|
20
|
+
"failed",
|
|
21
|
+
"human-action-required",
|
|
22
|
+
"published",
|
|
23
|
+
"up-to-date"
|
|
24
|
+
] as const;
|
|
25
|
+
export const PROJECTION_PUBLISHERS = ["command", "gh", "none"] as const;
|
|
26
|
+
export const PROJECTION_PR_VERDICTS = [
|
|
27
|
+
"generated-only-not-render-equivalent",
|
|
28
|
+
"generated-only-render-equivalent",
|
|
29
|
+
"no-changes",
|
|
30
|
+
"touches-non-generated"
|
|
31
|
+
] as const;
|
|
32
|
+
|
|
33
|
+
export type ProjectionPublishResult = (typeof PROJECTION_PUBLISH_RESULTS)[number];
|
|
34
|
+
export type ProjectionPublisherKind = (typeof PROJECTION_PUBLISHERS)[number];
|
|
35
|
+
export type ProjectionPrVerdict = (typeof PROJECTION_PR_VERDICTS)[number];
|
|
36
|
+
|
|
37
|
+
export interface ProjectionPublishPullRequestV1 {
|
|
38
|
+
url?: string;
|
|
39
|
+
number?: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ProjectionPublishHumanActionV1 {
|
|
43
|
+
reasonCode: ProjectionHumanActionReasonCode;
|
|
44
|
+
path?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The `data` of `projection.publish`, and the writer state's `lastRun`. */
|
|
48
|
+
export interface ProjectionPublishRunV1 {
|
|
49
|
+
schemaVersion: typeof PROJECTION_PUBLISH_RUN_SCHEMA_VERSION;
|
|
50
|
+
result: ProjectionPublishResult;
|
|
51
|
+
remote: string;
|
|
52
|
+
base: string;
|
|
53
|
+
branch: string;
|
|
54
|
+
/** The base tip this run evaluated; null when the run stopped before resolving one. */
|
|
55
|
+
baseSha: string | null;
|
|
56
|
+
/** The rolling branch tip that carries this base's projection, pushed by this run or an earlier one. */
|
|
57
|
+
publishedCommit: string | null;
|
|
58
|
+
/** True only when this run moved the remote rolling branch. */
|
|
59
|
+
pushed: boolean;
|
|
60
|
+
pullRequest: ProjectionPublishPullRequestV1 | null;
|
|
61
|
+
publisher: ProjectionPublisherKind;
|
|
62
|
+
/** Repository-relative generated paths the published commit changes, sorted. */
|
|
63
|
+
files: string[];
|
|
64
|
+
/** `ProjectionResultV2.status` of the apply this run made, or null without one. */
|
|
65
|
+
projectionStatus: string | null;
|
|
66
|
+
humanActions: ProjectionPublishHumanActionV1[];
|
|
67
|
+
error: { code: string; reasonCode?: string; message: string } | null;
|
|
68
|
+
startedAt: string;
|
|
69
|
+
finishedAt: string;
|
|
70
|
+
/** Base tips evaluated in this run; above 1 when the base moved while the run worked. */
|
|
71
|
+
iterations: number;
|
|
72
|
+
/** Present on `busy`: the pid of the live writer that holds the lock. */
|
|
73
|
+
holderPid?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The `data` of `projection.publish-status`. Read-only. */
|
|
77
|
+
export interface ProjectionPublishStatusV1 {
|
|
78
|
+
schemaVersion: typeof PROJECTION_PUBLISH_STATUS_SCHEMA_VERSION;
|
|
79
|
+
remote: string;
|
|
80
|
+
base: string;
|
|
81
|
+
branch: string | null;
|
|
82
|
+
worktreePath: string;
|
|
83
|
+
running: { pid: number; startedAt: string } | null;
|
|
84
|
+
lastProcessedSha: string | null;
|
|
85
|
+
lastSuccessfulSha: string | null;
|
|
86
|
+
lastRun: ProjectionPublishRunV1 | null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The `data` of `projection.verify-pr`. */
|
|
90
|
+
export interface ProjectionPrVerificationV1 {
|
|
91
|
+
schemaVersion: typeof PROJECTION_PR_VERIFICATION_SCHEMA_VERSION;
|
|
92
|
+
base: string;
|
|
93
|
+
baseSha: string;
|
|
94
|
+
headSha: string;
|
|
95
|
+
mergeBase: string;
|
|
96
|
+
changedPaths: string[];
|
|
97
|
+
/**
|
|
98
|
+
* Changed paths that are not generated: not the projection manifest, not a manifest target path
|
|
99
|
+
* and not an agent-context target path (at HEAD or at the merge base), plus every
|
|
100
|
+
* `humanEditedPaths` entry.
|
|
101
|
+
*/
|
|
102
|
+
nonGeneratedPaths: string[];
|
|
103
|
+
/**
|
|
104
|
+
* Mixed-ownership targets (manifest `ownership: "mixed"` and every agent-context target) whose
|
|
105
|
+
* text outside the generated regions differs between the merge base and HEAD, whose regions
|
|
106
|
+
* cannot be delimited, or which are added or deleted. Never rendered.
|
|
107
|
+
*/
|
|
108
|
+
humanEditedPaths: string[];
|
|
109
|
+
/** True when the diff is non-empty and every changed path is a generated output. */
|
|
110
|
+
generatedOnly: boolean;
|
|
111
|
+
/** Null when no render ran (an empty diff, or a diff that touches a non-generated path). */
|
|
112
|
+
renderEquivalent: boolean | null;
|
|
113
|
+
differingPaths: string[];
|
|
114
|
+
projectionStatus: string | null;
|
|
115
|
+
verdict: ProjectionPrVerdict;
|
|
116
|
+
}
|
package/src/projection.ts
CHANGED
|
@@ -108,7 +108,9 @@ export const ARCHCTX_FEATURES = [
|
|
|
108
108
|
"projection-preview-v1",
|
|
109
109
|
"projection-prior-committed-applies-v1",
|
|
110
110
|
"projection-protocol-v2",
|
|
111
|
+
"projection-publish-v1",
|
|
111
112
|
"projection-snapshot-v1",
|
|
113
|
+
"projection-verify-pr-v1",
|
|
112
114
|
"recommendation-scan-decision-v1",
|
|
113
115
|
"recommendation-v3",
|
|
114
116
|
"refactor-assessment-v1",
|
package/src/schema.ts
CHANGED
|
@@ -146,6 +146,8 @@ export function stableYaml(value: Json, indent = 0): string {
|
|
|
146
146
|
if (value.length === 0) return "[]\n";
|
|
147
147
|
return value
|
|
148
148
|
.map((item) => {
|
|
149
|
+
// The stable reader accepts flow sequences, but not compact nested block sequences.
|
|
150
|
+
if (Array.isArray(item)) return `${pad}- ${canonicalize(item)}\n`;
|
|
149
151
|
if (item !== null && typeof item === "object") {
|
|
150
152
|
return `${pad}- ${stableYaml(item, indent + 2).trimStart()}`;
|
|
151
153
|
}
|