archctx 0.4.0 → 0.4.2
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/assets/catalog.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "archcontext.practice-catalog-manifest/v1",
|
|
3
3
|
"catalogVersion": "2026.06.0",
|
|
4
|
-
"productVersion": "0.4.
|
|
4
|
+
"productVersion": "0.4.2",
|
|
5
5
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
6
6
|
"entries": [
|
|
7
7
|
{
|
|
@@ -389,5 +389,5 @@
|
|
|
389
389
|
"structurizr.dsl",
|
|
390
390
|
"twelve-factor"
|
|
391
391
|
],
|
|
392
|
-
"catalogDigest": "sha256:
|
|
392
|
+
"catalogDigest": "sha256:7fc97d6c05657eeeee604a302a22e0afe77dc2d0ffea89442de193e570d9b8bf"
|
|
393
393
|
}
|
package/bin/archctx.mjs
CHANGED
|
@@ -783,7 +783,11 @@ function archctxCapabilities(packageVersion) {
|
|
|
783
783
|
function projectionRequestInvariantIssues(input) {
|
|
784
784
|
const issues = [
|
|
785
785
|
...sortedUniqueIssues("targets", input.targets),
|
|
786
|
-
...sortedUniqueIssues("changedPaths", input.changedPaths)
|
|
786
|
+
...sortedUniqueIssues("changedPaths", input.changedPaths),
|
|
787
|
+
...input.acceptedChange ? [
|
|
788
|
+
...sortedUniqueIssues("acceptedChange.reasonCodes", input.acceptedChange.reasonCodes),
|
|
789
|
+
...sortedUniqueIssues("acceptedChange.affectedNodeIds", input.acceptedChange.affectedNodeIds)
|
|
790
|
+
] : []
|
|
787
791
|
];
|
|
788
792
|
if (input.targets.length === 0)
|
|
789
793
|
issues.push("targets must contain at least one projection target");
|
|
@@ -793,6 +797,25 @@ function projectionRequestInvariantIssues(input) {
|
|
|
793
797
|
issues.push("adoptionPlanId is required when mode=adopt");
|
|
794
798
|
if (input.mode !== "adopt" && input.adoptionPlanId !== undefined)
|
|
795
799
|
issues.push("adoptionPlanId is only allowed when mode=adopt");
|
|
800
|
+
if (input.acceptedChange) {
|
|
801
|
+
if (input.acceptedChange.changeSetId.trim() === "")
|
|
802
|
+
issues.push("acceptedChange.changeSetId must not be empty");
|
|
803
|
+
if (input.acceptedChange.eventId.trim() === "")
|
|
804
|
+
issues.push("acceptedChange.eventId must not be empty");
|
|
805
|
+
if (input.acceptedChange.reasonCodes.length === 0)
|
|
806
|
+
issues.push("acceptedChange.reasonCodes must contain at least one reason");
|
|
807
|
+
if (input.acceptedChange.affectedNodeIds.length === 0)
|
|
808
|
+
issues.push("acceptedChange.affectedNodeIds must contain at least one node");
|
|
809
|
+
const allowedReasons = new Set(ARCHITECTURE_MAJOR_CHANGE_REASON_CODES);
|
|
810
|
+
for (const reason of input.acceptedChange.reasonCodes) {
|
|
811
|
+
if (!allowedReasons.has(reason))
|
|
812
|
+
issues.push(`acceptedChange.reasonCodes contains unsupported reason: ${reason}`);
|
|
813
|
+
}
|
|
814
|
+
for (const nodeId of input.acceptedChange.affectedNodeIds) {
|
|
815
|
+
if (nodeId.trim() === "")
|
|
816
|
+
issues.push("acceptedChange.affectedNodeIds must not contain empty node ids");
|
|
817
|
+
}
|
|
818
|
+
}
|
|
796
819
|
return issues;
|
|
797
820
|
}
|
|
798
821
|
function projectionResultInvariantIssues(input) {
|
|
@@ -977,7 +1000,7 @@ function productVersionManifest() {
|
|
|
977
1000
|
}
|
|
978
1001
|
};
|
|
979
1002
|
}
|
|
980
|
-
var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.4.
|
|
1003
|
+
var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.4.2", ARCHCONTEXT_PACKAGE_MANAGER = "bun@1.3.10", ARCHCONTEXT_NODE_RANGE = ">=24 <26", LOCAL_RUNTIME_RPC_SCHEMA_VERSION = "archcontext.runtime-rpc/v1", ARCHCONTEXT_SCHEMA_SET_VERSION = "2026-07-11.explorer-view-v2";
|
|
981
1004
|
|
|
982
1005
|
// packages/contracts/src/validator.ts
|
|
983
1006
|
function validateJsonSchema(schema, value) {
|
|
@@ -5590,6 +5613,8 @@ var DEFAULT_IGNORES = new Set([
|
|
|
5590
5613
|
"_ops",
|
|
5591
5614
|
"_ref",
|
|
5592
5615
|
".archcontext/.local",
|
|
5616
|
+
".claude/.session-id",
|
|
5617
|
+
".claude/.trace.jsonl",
|
|
5593
5618
|
".DS_Store"
|
|
5594
5619
|
]);
|
|
5595
5620
|
function repositoryFingerprint(root) {
|
|
@@ -5736,6 +5761,8 @@ var DEFAULT_IGNORES2 = new Set([
|
|
|
5736
5761
|
"_ops",
|
|
5737
5762
|
"_ref",
|
|
5738
5763
|
".archcontext/.local",
|
|
5764
|
+
".claude/.session-id",
|
|
5765
|
+
".claude/.trace.jsonl",
|
|
5739
5766
|
".DS_Store"
|
|
5740
5767
|
]);
|
|
5741
5768
|
function repositoryFingerprint2(root) {
|
|
@@ -40285,9 +40312,11 @@ async function runArchitectureDocsProjectionCommand(args2, cwd, daemon) {
|
|
|
40285
40312
|
const generatedAt = readFlag(args2, "--generated-at") ?? new Date(0).toISOString();
|
|
40286
40313
|
let profile;
|
|
40287
40314
|
let projection3;
|
|
40315
|
+
let acceptedChange;
|
|
40288
40316
|
try {
|
|
40289
40317
|
profile = architectureProjectionProfile(args2);
|
|
40290
|
-
|
|
40318
|
+
acceptedChange = acceptedArchitectureChange(args2);
|
|
40319
|
+
projection3 = buildArchitectureDocsProjection(root, generatedAt, profile, undefined, acceptedChange);
|
|
40291
40320
|
} catch (error) {
|
|
40292
40321
|
return errorEnvelope(`docs.${subcommand}`, "AC_PRECONDITION_FAILED", error instanceof Error ? error.message : String(error));
|
|
40293
40322
|
}
|
|
@@ -40320,7 +40349,7 @@ async function runArchitectureDocsProjectionCommand(args2, cwd, daemon) {
|
|
|
40320
40349
|
});
|
|
40321
40350
|
}
|
|
40322
40351
|
if (subcommand === "adopt") {
|
|
40323
|
-
return runArchitectureDocsAdoptionCommand(args2, root, daemon, projection3, profile, generatedAt);
|
|
40352
|
+
return runArchitectureDocsAdoptionCommand(args2, root, daemon, projection3, profile, generatedAt, acceptedChange);
|
|
40324
40353
|
}
|
|
40325
40354
|
if (projection3.plan.rejected.length > 0) {
|
|
40326
40355
|
return errorEnvelope("docs.plan", "AC_PRECONDITION_FAILED", `Architecture documentation projection requires explicit adoption or ownership repair: ${projection3.plan.rejected.map((diff) => `${diff.path} (${diff.reasonCode})`).join(", ")}`);
|
|
@@ -40415,7 +40444,7 @@ function buildArchitectureDocsProjection(root, generatedAt, profile = "default",
|
|
|
40415
40444
|
generatedAt,
|
|
40416
40445
|
refreshContext: {
|
|
40417
40446
|
repositoryId: repositoryFingerprint(root),
|
|
40418
|
-
workspaceId:
|
|
40447
|
+
workspaceId: projectionWorkspaceId(root),
|
|
40419
40448
|
headSha: provenance.baseHeadSha,
|
|
40420
40449
|
worktreeDigest: provenance.worktreeDigest,
|
|
40421
40450
|
...acceptedChange ? { acceptedChange } : {}
|
|
@@ -40456,7 +40485,7 @@ function architectureProjectionProfile(args2) {
|
|
|
40456
40485
|
}
|
|
40457
40486
|
return profile;
|
|
40458
40487
|
}
|
|
40459
|
-
async function runArchitectureDocsAdoptionCommand(args2, root, daemon, projection3, profile, generatedAt) {
|
|
40488
|
+
async function runArchitectureDocsAdoptionCommand(args2, root, daemon, projection3, profile, generatedAt, acceptedChange) {
|
|
40460
40489
|
if (profile !== REPO_HARNESS_PROJECTION_PROFILE) {
|
|
40461
40490
|
return errorEnvelope("docs.adopt", "AC_SCHEMA_INVALID", `docs adopt requires --profile ${REPO_HARNESS_PROJECTION_PROFILE}`);
|
|
40462
40491
|
}
|
|
@@ -40497,11 +40526,11 @@ async function runArchitectureDocsAdoptionCommand(args2, root, daemon, projectio
|
|
|
40497
40526
|
const simulatedByPath = new Map(projection3.loaded.existingFiles.map((file) => [file.path, file]));
|
|
40498
40527
|
for (const file of [...projection3.plan.files, ...adoption2.files])
|
|
40499
40528
|
simulatedByPath.set(file.path, file);
|
|
40500
|
-
const canonicalFirst = buildArchitectureDocsProjection(root, generatedAt, profile, [...simulatedByPath.values()]);
|
|
40529
|
+
const canonicalFirst = buildArchitectureDocsProjection(root, generatedAt, profile, [...simulatedByPath.values()], acceptedChange);
|
|
40501
40530
|
const canonicalExistingByPath = new Map(simulatedByPath);
|
|
40502
40531
|
for (const file of canonicalFirst.files)
|
|
40503
40532
|
canonicalExistingByPath.set(file.path, file);
|
|
40504
|
-
const canonical = buildArchitectureDocsProjection(root, generatedAt, profile, [...canonicalExistingByPath.values()]);
|
|
40533
|
+
const canonical = buildArchitectureDocsProjection(root, generatedAt, profile, [...canonicalExistingByPath.values()], acceptedChange);
|
|
40505
40534
|
if (!canonical.plan.drift.ok || canonical.plan.rejected.length > 0 || canonical.plan.projectionDigest !== canonicalFirst.plan.projectionDigest) {
|
|
40506
40535
|
return errorEnvelope("docs.adopt", "AC_PRECONDITION_FAILED", "projection-adoption-fixed-point-unproven");
|
|
40507
40536
|
}
|
|
@@ -40544,7 +40573,7 @@ async function runProjectionProtocolCommand(args2, cwd, daemon) {
|
|
|
40544
40573
|
const generatedAt = new Date(0).toISOString();
|
|
40545
40574
|
let projection3;
|
|
40546
40575
|
try {
|
|
40547
|
-
projection3 = buildArchitectureDocsProjection(root, generatedAt, REPO_HARNESS_PROJECTION_PROFILE);
|
|
40576
|
+
projection3 = buildArchitectureDocsProjection(root, generatedAt, REPO_HARNESS_PROJECTION_PROFILE, undefined, request.acceptedChange);
|
|
40548
40577
|
assertProjectionExpectedSnapshot(request, root, projection3);
|
|
40549
40578
|
} catch (error) {
|
|
40550
40579
|
return errorEnvelope("projection.run", "AC_PRECONDITION_FAILED", error instanceof Error ? error.message : String(error));
|
|
@@ -40565,12 +40594,12 @@ async function runProjectionProtocolCommand(args2, cwd, daemon) {
|
|
|
40565
40594
|
expectedWorktreeDigest,
|
|
40566
40595
|
"--task-session-id",
|
|
40567
40596
|
request.requestId
|
|
40568
|
-
], root, daemon, projection3, REPO_HARNESS_PROJECTION_PROFILE, generatedAt);
|
|
40597
|
+
], root, daemon, projection3, REPO_HARNESS_PROJECTION_PROFILE, generatedAt, request.acceptedChange);
|
|
40569
40598
|
if (!adopted.ok)
|
|
40570
40599
|
return adopted;
|
|
40571
40600
|
let output;
|
|
40572
40601
|
try {
|
|
40573
|
-
output = buildArchitectureDocsProjection(root, generatedAt, REPO_HARNESS_PROJECTION_PROFILE);
|
|
40602
|
+
output = buildArchitectureDocsProjection(root, generatedAt, REPO_HARNESS_PROJECTION_PROFILE, undefined, request.acceptedChange);
|
|
40574
40603
|
if (!output.plan.drift.ok || output.plan.rejected.length > 0) {
|
|
40575
40604
|
return errorEnvelope("projection.run", "AC_PRECONDITION_FAILED", "projection adoption did not reach the architecture-docs fixed point");
|
|
40576
40605
|
}
|
|
@@ -40632,14 +40661,35 @@ function parseProjectionProtocolRequest(raw) {
|
|
|
40632
40661
|
throw new Error("projection request expected.headSha is invalid");
|
|
40633
40662
|
if (typeof snapshot.worktreeDigest !== "string" || !/^sha256:[a-f0-9]{64}$/.test(snapshot.worktreeDigest))
|
|
40634
40663
|
throw new Error("projection request expected.worktreeDigest is invalid");
|
|
40664
|
+
if (input.acceptedChange !== undefined)
|
|
40665
|
+
validateProjectionAcceptedChange(input.acceptedChange);
|
|
40635
40666
|
const request = input;
|
|
40636
40667
|
const issues = projectionRequestInvariantIssues(request);
|
|
40637
40668
|
if (issues.length > 0)
|
|
40638
40669
|
throw new Error(`projection request invariant failed: ${issues.join("; ")}`);
|
|
40639
40670
|
return request;
|
|
40640
40671
|
}
|
|
40672
|
+
function validateProjectionAcceptedChange(value) {
|
|
40673
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
40674
|
+
throw new Error("projection request acceptedChange must be an object");
|
|
40675
|
+
}
|
|
40676
|
+
const accepted = value;
|
|
40677
|
+
const supportedKeys = new Set(["changeSetId", "eventId", "reasonCodes", "affectedNodeIds"]);
|
|
40678
|
+
const unsupportedKey = Object.keys(accepted).find((key) => !supportedKeys.has(key));
|
|
40679
|
+
if (unsupportedKey)
|
|
40680
|
+
throw new Error(`projection request acceptedChange contains unsupported property: ${unsupportedKey}`);
|
|
40681
|
+
if (typeof accepted.changeSetId !== "string" || typeof accepted.eventId !== "string") {
|
|
40682
|
+
throw new Error("projection request acceptedChange changeSetId and eventId are required");
|
|
40683
|
+
}
|
|
40684
|
+
if (!Array.isArray(accepted.reasonCodes) || accepted.reasonCodes.some((reason) => typeof reason !== "string")) {
|
|
40685
|
+
throw new Error("projection request acceptedChange reasonCodes must be a string array");
|
|
40686
|
+
}
|
|
40687
|
+
if (!Array.isArray(accepted.affectedNodeIds) || accepted.affectedNodeIds.some((nodeId) => typeof nodeId !== "string")) {
|
|
40688
|
+
throw new Error("projection request acceptedChange affectedNodeIds must be a string array");
|
|
40689
|
+
}
|
|
40690
|
+
}
|
|
40641
40691
|
function assertProjectionExpectedSnapshot(request, root, projection3) {
|
|
40642
|
-
const workspaceId =
|
|
40692
|
+
const workspaceId = projectionWorkspaceId(root);
|
|
40643
40693
|
const actual = {
|
|
40644
40694
|
repositoryId: repositoryFingerprint(root),
|
|
40645
40695
|
workspaceId,
|
|
@@ -40651,6 +40701,10 @@ function assertProjectionExpectedSnapshot(request, root, projection3) {
|
|
|
40651
40701
|
throw new Error(`projection request expected snapshot mismatch: ${field}`);
|
|
40652
40702
|
}
|
|
40653
40703
|
}
|
|
40704
|
+
function projectionWorkspaceId(root) {
|
|
40705
|
+
const canonicalRoot = canonicalRepositoryRoot(root);
|
|
40706
|
+
return `workspace.${digestJson({ root: canonicalRoot }).replace(/^sha256:/, "").slice(0, 16)}`;
|
|
40707
|
+
}
|
|
40654
40708
|
function projectionProtocolHumanStatus(request, projection3) {
|
|
40655
40709
|
const humanSignal = projection3.plan.refreshSignals.some((signal) => signal.mode === "human-action-required");
|
|
40656
40710
|
const adoption2 = projection3.plan.rejected.some((diff) => diff.reasonCode === "projection-adoption-required");
|
package/package.json
CHANGED
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"items": { "$ref": "#/$defs/repoPath" }
|
|
25
25
|
},
|
|
26
26
|
"expected": { "$ref": "#/$defs/expectedSnapshot" },
|
|
27
|
-
"adoptionPlanId": { "type": "string", "pattern": "^adoption_plan\\.[a-zA-Z0-9_.-]+$" }
|
|
27
|
+
"adoptionPlanId": { "type": "string", "pattern": "^adoption_plan\\.[a-zA-Z0-9_.-]+$" },
|
|
28
|
+
"acceptedChange": { "$ref": "#/$defs/acceptedChange" }
|
|
28
29
|
},
|
|
29
30
|
"allOf": [
|
|
30
31
|
{
|
|
@@ -46,6 +47,45 @@
|
|
|
46
47
|
]
|
|
47
48
|
}
|
|
48
49
|
},
|
|
50
|
+
"acceptedChange": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"additionalProperties": false,
|
|
53
|
+
"required": ["changeSetId", "eventId", "reasonCodes", "affectedNodeIds"],
|
|
54
|
+
"properties": {
|
|
55
|
+
"changeSetId": { "type": "string", "minLength": 1 },
|
|
56
|
+
"eventId": { "type": "string", "minLength": 1 },
|
|
57
|
+
"reasonCodes": {
|
|
58
|
+
"type": "array",
|
|
59
|
+
"minItems": 1,
|
|
60
|
+
"uniqueItems": true,
|
|
61
|
+
"description": "Canonical wire order is lexicographic and is enforced by projectionRequestInvariantIssues.",
|
|
62
|
+
"items": {
|
|
63
|
+
"enum": [
|
|
64
|
+
"constraint-changed",
|
|
65
|
+
"entrypoint-changed",
|
|
66
|
+
"interface-changed",
|
|
67
|
+
"lifecycle-changed",
|
|
68
|
+
"node-added",
|
|
69
|
+
"node-moved",
|
|
70
|
+
"node-removed",
|
|
71
|
+
"node-renamed",
|
|
72
|
+
"ownership-changed",
|
|
73
|
+
"relation-changed",
|
|
74
|
+
"responsibility-changed",
|
|
75
|
+
"risk-boundary-changed",
|
|
76
|
+
"verified-flow-proof-changed"
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"affectedNodeIds": {
|
|
81
|
+
"type": "array",
|
|
82
|
+
"minItems": 1,
|
|
83
|
+
"uniqueItems": true,
|
|
84
|
+
"description": "Canonical wire order is lexicographic and is enforced by projectionRequestInvariantIssues.",
|
|
85
|
+
"items": { "type": "string", "minLength": 1 }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
49
89
|
"expectedSnapshot": {
|
|
50
90
|
"type": "object",
|
|
51
91
|
"additionalProperties": false,
|