archctx 0.4.5 → 0.4.6
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 +2 -2
- package/bin/archctx.mjs +175 -22
- package/package.json +1 -1
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.6",
|
|
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:12ce681507d3cf7bcec02fe367b1bb9161f3b469559a8f5d2db861d3a692c469"
|
|
393
393
|
}
|
package/bin/archctx.mjs
CHANGED
|
@@ -1088,7 +1088,7 @@ function productVersionManifest() {
|
|
|
1088
1088
|
}
|
|
1089
1089
|
};
|
|
1090
1090
|
}
|
|
1091
|
-
var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.4.
|
|
1091
|
+
var ARCHCONTEXT_PRODUCT_NAME = "archctx", ARCHCONTEXT_PRODUCT_VERSION = "0.4.6", 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";
|
|
1092
1092
|
|
|
1093
1093
|
// packages/contracts/src/validator.ts
|
|
1094
1094
|
function validateJsonSchema(schema, value) {
|
|
@@ -28492,6 +28492,71 @@ function auditGithubIssuesEnabledInManifestText(manifestText) {
|
|
|
28492
28492
|
}
|
|
28493
28493
|
var RUNTIME_RPC_VERSION = LOCAL_RUNTIME_RPC_SCHEMA_VERSION;
|
|
28494
28494
|
|
|
28495
|
+
class RuntimeUpdateInputError extends Error {
|
|
28496
|
+
}
|
|
28497
|
+
function decodeRuntimeWorktreeDigestProfile(value, field) {
|
|
28498
|
+
switch (value) {
|
|
28499
|
+
case "repository":
|
|
28500
|
+
case "architecture-documentation-projection":
|
|
28501
|
+
return value;
|
|
28502
|
+
default:
|
|
28503
|
+
throw new RuntimeUpdateInputError(`${field} must be repository or architecture-documentation-projection`);
|
|
28504
|
+
}
|
|
28505
|
+
}
|
|
28506
|
+
function decodeRuntimePlanUpdateInput(value) {
|
|
28507
|
+
const input = runtimeUpdateInputRecord(value, "plan_update input");
|
|
28508
|
+
if (typeof input.id !== "string" || input.id.length === 0) {
|
|
28509
|
+
throw new RuntimeUpdateInputError("plan_update id must be a non-empty string");
|
|
28510
|
+
}
|
|
28511
|
+
if (!Array.isArray(input.operations)) {
|
|
28512
|
+
throw new RuntimeUpdateInputError("plan_update operations must be an array");
|
|
28513
|
+
}
|
|
28514
|
+
let worktreeDigestPrecondition;
|
|
28515
|
+
if (input.worktreeDigestPrecondition !== undefined) {
|
|
28516
|
+
const precondition = runtimeUpdateInputRecord(input.worktreeDigestPrecondition, "plan_update worktreeDigestPrecondition");
|
|
28517
|
+
const profile = decodeRuntimeWorktreeDigestProfile(precondition.profile, "plan_update worktreeDigestPrecondition.profile");
|
|
28518
|
+
if (profile !== "architecture-documentation-projection") {
|
|
28519
|
+
throw new RuntimeUpdateInputError("plan_update worktreeDigestPrecondition.profile must be architecture-documentation-projection");
|
|
28520
|
+
}
|
|
28521
|
+
if (typeof precondition.expectedDigest !== "string" || precondition.expectedDigest.length === 0) {
|
|
28522
|
+
throw new RuntimeUpdateInputError("plan_update worktreeDigestPrecondition.expectedDigest must be a non-empty string");
|
|
28523
|
+
}
|
|
28524
|
+
worktreeDigestPrecondition = { profile, expectedDigest: precondition.expectedDigest };
|
|
28525
|
+
}
|
|
28526
|
+
return {
|
|
28527
|
+
id: input.id,
|
|
28528
|
+
operations: input.operations,
|
|
28529
|
+
...input.reason === undefined ? {} : { reason: input.reason },
|
|
28530
|
+
...worktreeDigestPrecondition === undefined ? {} : { worktreeDigestPrecondition }
|
|
28531
|
+
};
|
|
28532
|
+
}
|
|
28533
|
+
function decodeRuntimeApplyUpdateInput(value) {
|
|
28534
|
+
const input = runtimeUpdateInputRecord(value, "apply_update input");
|
|
28535
|
+
if (typeof input.id !== "string" || input.id.length === 0) {
|
|
28536
|
+
throw new RuntimeUpdateInputError("apply_update id must be a non-empty string");
|
|
28537
|
+
}
|
|
28538
|
+
if (typeof input.approved !== "boolean") {
|
|
28539
|
+
throw new RuntimeUpdateInputError("apply_update approved must be a boolean");
|
|
28540
|
+
}
|
|
28541
|
+
if (typeof input.expectedWorktreeDigest !== "string" || input.expectedWorktreeDigest.length === 0) {
|
|
28542
|
+
throw new RuntimeUpdateInputError("apply_update expectedWorktreeDigest must be a non-empty string");
|
|
28543
|
+
}
|
|
28544
|
+
const worktreeDigestProfile = input.worktreeDigestProfile === undefined ? undefined : decodeRuntimeWorktreeDigestProfile(input.worktreeDigestProfile, "apply_update worktreeDigestProfile");
|
|
28545
|
+
return {
|
|
28546
|
+
id: input.id,
|
|
28547
|
+
approved: input.approved,
|
|
28548
|
+
expectedWorktreeDigest: input.expectedWorktreeDigest,
|
|
28549
|
+
...worktreeDigestProfile === undefined ? {} : { worktreeDigestProfile },
|
|
28550
|
+
...input.projectionApplyReceipt === undefined ? {} : { projectionApplyReceipt: input.projectionApplyReceipt }
|
|
28551
|
+
};
|
|
28552
|
+
}
|
|
28553
|
+
function runtimeUpdateInputRecord(value, field) {
|
|
28554
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
28555
|
+
throw new RuntimeUpdateInputError(`${field} must be an object`);
|
|
28556
|
+
}
|
|
28557
|
+
return value;
|
|
28558
|
+
}
|
|
28559
|
+
|
|
28495
28560
|
class ArchitectureLedgerReadModelStore {
|
|
28496
28561
|
fallback;
|
|
28497
28562
|
localStore;
|
|
@@ -28602,6 +28667,7 @@ class ArchctxDaemon {
|
|
|
28602
28667
|
checkpointBaselines = new Map;
|
|
28603
28668
|
checkpointCoalesced = new Map;
|
|
28604
28669
|
changesets = new Map;
|
|
28670
|
+
changeSetWorktreeDigestProfiles = new Map;
|
|
28605
28671
|
deferredArchitectureChangeFeedFailures = new Map;
|
|
28606
28672
|
auditRunAbortControllers = new Map;
|
|
28607
28673
|
landscape;
|
|
@@ -29591,6 +29657,7 @@ class ArchctxDaemon {
|
|
|
29591
29657
|
operations: [{ op: "write_waiver", path, expectedHash, body }]
|
|
29592
29658
|
});
|
|
29593
29659
|
this.changesets.set(draft.id, draft);
|
|
29660
|
+
this.changeSetWorktreeDigestProfiles.set(draft.id, "repository");
|
|
29594
29661
|
return okEnvelope("practices.waive", {
|
|
29595
29662
|
schemaVersion: "archcontext.practice-waiver-plan/v1",
|
|
29596
29663
|
waiver,
|
|
@@ -29762,21 +29829,36 @@ class ArchctxDaemon {
|
|
|
29762
29829
|
};
|
|
29763
29830
|
return okEnvelope("resource.read", result);
|
|
29764
29831
|
}
|
|
29765
|
-
async planUpdate(root,
|
|
29832
|
+
async planUpdate(root, rawInput) {
|
|
29766
29833
|
this.assertRunning();
|
|
29834
|
+
let input;
|
|
29835
|
+
try {
|
|
29836
|
+
input = decodeRuntimePlanUpdateInput(rawInput);
|
|
29837
|
+
} catch (error) {
|
|
29838
|
+
if (error instanceof RuntimeUpdateInputError) {
|
|
29839
|
+
return errorEnvelope("plan_update", "AC_SCHEMA_INVALID", error.message);
|
|
29840
|
+
}
|
|
29841
|
+
throw error;
|
|
29842
|
+
}
|
|
29767
29843
|
const session = await this.openSession(root);
|
|
29768
29844
|
const model = await this.readModelStore.validateModel(session.workspace);
|
|
29845
|
+
const worktreeDigestProfile = input.worktreeDigestPrecondition?.profile ?? "repository";
|
|
29846
|
+
const worktreeDigest = runtimeWorktreeDigest(root, worktreeDigestProfile);
|
|
29847
|
+
if (input.worktreeDigestPrecondition && input.worktreeDigestPrecondition.expectedDigest !== worktreeDigest) {
|
|
29848
|
+
throw new Error("Worktree digest changed before plan");
|
|
29849
|
+
}
|
|
29769
29850
|
const draft = this.changeSetEngine.plan({
|
|
29770
29851
|
id: input.id,
|
|
29771
29852
|
base: {
|
|
29772
29853
|
headSha: session.workspace.headSha,
|
|
29773
|
-
worktreeDigest
|
|
29854
|
+
worktreeDigest,
|
|
29774
29855
|
modelDigest: model.modelDigest
|
|
29775
29856
|
},
|
|
29776
29857
|
reason: input.reason ?? { taskSessionId: "task_runtime" },
|
|
29777
29858
|
operations: input.operations
|
|
29778
29859
|
});
|
|
29779
29860
|
this.changesets.set(draft.id, draft);
|
|
29861
|
+
this.changeSetWorktreeDigestProfiles.set(draft.id, worktreeDigestProfile);
|
|
29780
29862
|
return okEnvelope("plan_update", {
|
|
29781
29863
|
draft,
|
|
29782
29864
|
preview: this.changeSetEngine.preview(root, draft)
|
|
@@ -29905,18 +29987,31 @@ class ArchctxDaemon {
|
|
|
29905
29987
|
return cached ? { ...cached.resource, queryDigest, cacheStatus: "stale" } : undefined;
|
|
29906
29988
|
}
|
|
29907
29989
|
}
|
|
29908
|
-
async applyUpdate(root,
|
|
29990
|
+
async applyUpdate(root, rawInput) {
|
|
29909
29991
|
this.assertRunning();
|
|
29992
|
+
let input;
|
|
29993
|
+
try {
|
|
29994
|
+
input = decodeRuntimeApplyUpdateInput(rawInput);
|
|
29995
|
+
} catch (error) {
|
|
29996
|
+
if (error instanceof RuntimeUpdateInputError) {
|
|
29997
|
+
return errorEnvelope("apply_update", "AC_SCHEMA_INVALID", error.message);
|
|
29998
|
+
}
|
|
29999
|
+
throw error;
|
|
30000
|
+
}
|
|
29910
30001
|
return this.withWriter(async () => {
|
|
29911
|
-
if (!input.expectedWorktreeDigest)
|
|
29912
|
-
throw new Error("apply_update requires expectedWorktreeDigest");
|
|
29913
|
-
const current = computeWorktreeDigest2(root);
|
|
29914
|
-
if (current !== input.expectedWorktreeDigest)
|
|
29915
|
-
throw new Error("Worktree digest changed before apply");
|
|
29916
|
-
const session = await this.openSession(root);
|
|
29917
30002
|
const draft = this.changesets.get(input.id);
|
|
29918
30003
|
if (!draft)
|
|
29919
30004
|
throw new Error(`Unknown ChangeSet: ${input.id}`);
|
|
30005
|
+
const plannedProfile = this.changeSetWorktreeDigestProfiles.get(input.id);
|
|
30006
|
+
if (!plannedProfile)
|
|
30007
|
+
throw new Error("ChangeSet worktree digest profile missing before apply");
|
|
30008
|
+
const requestedProfile = input.worktreeDigestProfile ?? "repository";
|
|
30009
|
+
if (requestedProfile !== plannedProfile)
|
|
30010
|
+
throw new Error("ChangeSet worktree digest profile changed before apply");
|
|
30011
|
+
const current = runtimeWorktreeDigest(root, plannedProfile);
|
|
30012
|
+
if (current !== input.expectedWorktreeDigest)
|
|
30013
|
+
throw new Error("Worktree digest changed before apply");
|
|
30014
|
+
const session = await this.openSession(root);
|
|
29920
30015
|
if (draft.base.headSha !== session.workspace.headSha)
|
|
29921
30016
|
throw new Error("ChangeSet HEAD changed before apply");
|
|
29922
30017
|
if (draft.base.worktreeDigest !== current)
|
|
@@ -32404,7 +32499,7 @@ class ArchctxRuntimeRpcServer {
|
|
|
32404
32499
|
pid: process.pid,
|
|
32405
32500
|
protocol: "http-loopback",
|
|
32406
32501
|
version: 1,
|
|
32407
|
-
product: productVersionManifest(),
|
|
32502
|
+
product: this.options.productManifest?.() ?? productVersionManifest(),
|
|
32408
32503
|
composition: this.daemon.compositionReport()
|
|
32409
32504
|
});
|
|
32410
32505
|
return;
|
|
@@ -32719,6 +32814,16 @@ function shouldSkipGeneratedProjectionJob(metadata, input) {
|
|
|
32719
32814
|
function isRuntimeAgentJobCursorStale(job, scope) {
|
|
32720
32815
|
return job.worktree.headSha !== scope.worktree.headSha || job.worktree.worktreeDigest !== scope.worktree.worktreeDigest;
|
|
32721
32816
|
}
|
|
32817
|
+
function runtimeWorktreeDigest(root, profile) {
|
|
32818
|
+
switch (profile) {
|
|
32819
|
+
case "repository":
|
|
32820
|
+
return computeWorktreeDigest2(root);
|
|
32821
|
+
case "architecture-documentation-projection":
|
|
32822
|
+
return architectureDocumentationProjectionWorktreeDigest(root, loadNativeModelFromArchContext(root));
|
|
32823
|
+
default:
|
|
32824
|
+
throw new RuntimeUpdateInputError(`unsupported worktree digest profile: ${String(profile)}`);
|
|
32825
|
+
}
|
|
32826
|
+
}
|
|
32722
32827
|
function isArchContextGeneratedProjectionPath(path) {
|
|
32723
32828
|
return path.replace(/\\/g, "/").startsWith(".archcontext/generated/");
|
|
32724
32829
|
}
|
|
@@ -35773,14 +35878,19 @@ async function runProjectionProtocolCommand(args2, cwd, daemon) {
|
|
|
35773
35878
|
const planned = await daemon.planUpdate(root, {
|
|
35774
35879
|
id: changeSetId,
|
|
35775
35880
|
reason: { taskSessionId: request.requestId },
|
|
35776
|
-
operations: [architectureDocsRenderProjectionOperation(root, projection3.files)]
|
|
35881
|
+
operations: [architectureDocsRenderProjectionOperation(root, projection3.files)],
|
|
35882
|
+
worktreeDigestPrecondition: {
|
|
35883
|
+
profile: "architecture-documentation-projection",
|
|
35884
|
+
expectedDigest: request.expected.worktreeDigest
|
|
35885
|
+
}
|
|
35777
35886
|
});
|
|
35778
35887
|
if (!planned.ok)
|
|
35779
35888
|
return planned;
|
|
35780
35889
|
const applied = await daemon.applyUpdate(root, {
|
|
35781
35890
|
id: changeSetId,
|
|
35782
35891
|
approved: true,
|
|
35783
|
-
expectedWorktreeDigest:
|
|
35892
|
+
expectedWorktreeDigest: request.expected.worktreeDigest,
|
|
35893
|
+
worktreeDigestProfile: "architecture-documentation-projection",
|
|
35784
35894
|
...applyReceipt ? { projectionApplyReceipt: applyReceipt } : {}
|
|
35785
35895
|
});
|
|
35786
35896
|
if (!applied.ok)
|
|
@@ -37571,6 +37681,9 @@ async function doctorDaemon(cwd) {
|
|
|
37571
37681
|
const health = await client.health().catch(() => {
|
|
37572
37682
|
return;
|
|
37573
37683
|
});
|
|
37684
|
+
const healthIssue = runtimeRpcCompatibilityIssueFromHealth(cwd, client, health);
|
|
37685
|
+
if (healthIssue)
|
|
37686
|
+
return incompatibleDaemonStatus(healthIssue);
|
|
37574
37687
|
if (health?.ok === true) {
|
|
37575
37688
|
const stalenessIssue = cliEntryStalenessIssue(cwd);
|
|
37576
37689
|
if (stalenessIssue?.pidAlive)
|
|
@@ -37580,6 +37693,7 @@ async function doctorDaemon(cwd) {
|
|
|
37580
37693
|
running: health?.ok === true,
|
|
37581
37694
|
staleConnection: health?.ok !== true,
|
|
37582
37695
|
rpcVersionCompatible: health?.schemaVersion === productVersionManifest().runtime.localRpc.schemaVersion,
|
|
37696
|
+
productVersionCompatible: health?.product?.product?.version === productVersionManifest().product.version,
|
|
37583
37697
|
connection: client.connectionInfo(),
|
|
37584
37698
|
health: health?.ok === true ? {
|
|
37585
37699
|
composition: health.composition,
|
|
@@ -37723,6 +37837,9 @@ async function createOrStartRuntimeRpcClient(cwd) {
|
|
|
37723
37837
|
const health = await startedClient.health().catch(() => {
|
|
37724
37838
|
return;
|
|
37725
37839
|
});
|
|
37840
|
+
const healthIssue = runtimeRpcCompatibilityIssueFromHealth(cwd, startedClient, health);
|
|
37841
|
+
if (healthIssue)
|
|
37842
|
+
throw new RuntimeVersionUnsupportedError(healthIssue);
|
|
37726
37843
|
if (health?.ok === true)
|
|
37727
37844
|
return startedClient;
|
|
37728
37845
|
}
|
|
@@ -37812,6 +37929,7 @@ async function runDaemonCommand(args2, cwd) {
|
|
|
37812
37929
|
running: true,
|
|
37813
37930
|
product: health.product,
|
|
37814
37931
|
rpcVersionCompatible: health.schemaVersion === RUNTIME_RPC_VERSION,
|
|
37932
|
+
productVersionCompatible: true,
|
|
37815
37933
|
...client.connectionInfo(),
|
|
37816
37934
|
token: "stored-in-connection-file"
|
|
37817
37935
|
});
|
|
@@ -37852,6 +37970,9 @@ async function startBackgroundDaemon(args2, cwd) {
|
|
|
37852
37970
|
return errorEnvelope("daemon.start", "AC_RUNTIME_VERSION_UNSUPPORTED", runtimeVersionUnsupportedMessage(compatibilityIssue));
|
|
37853
37971
|
}
|
|
37854
37972
|
const discovered = await discoverRunningDaemonInfo(cwd, { recoverStale: true });
|
|
37973
|
+
if (discovered.compatibilityIssue?.pidAlive) {
|
|
37974
|
+
return errorEnvelope("daemon.start", "AC_RUNTIME_VERSION_UNSUPPORTED", runtimeVersionUnsupportedMessage(discovered.compatibilityIssue));
|
|
37975
|
+
}
|
|
37855
37976
|
if (discovered.info) {
|
|
37856
37977
|
return okEnvelope("daemon.start", {
|
|
37857
37978
|
running: true,
|
|
@@ -37909,7 +38030,8 @@ async function startBackgroundDaemon(args2, cwd) {
|
|
|
37909
38030
|
}
|
|
37910
38031
|
}
|
|
37911
38032
|
async function upgradeDaemon(args2, cwd) {
|
|
37912
|
-
const
|
|
38033
|
+
const persistedIssue = runtimeRpcCompatibilityIssue(cwd) ?? cliEntryStalenessIssue(cwd);
|
|
38034
|
+
const issue = persistedIssue ?? (await discoverRunningDaemonInfo(cwd)).compatibilityIssue;
|
|
37913
38035
|
if (!issue) {
|
|
37914
38036
|
const started2 = await startBackgroundDaemon(args2, cwd);
|
|
37915
38037
|
return started2.ok ? { ...started2, requestId: "daemon.upgrade", data: { ...started2.data, upgraded: false, reason: "runtime-compatible" } } : started2;
|
|
@@ -37930,6 +38052,10 @@ async function upgradeDaemon(args2, cwd) {
|
|
|
37930
38052
|
previousStartedAt: issue.received,
|
|
37931
38053
|
entrypointMtime: issue.expected,
|
|
37932
38054
|
previousPid: issue.pid
|
|
38055
|
+
} : issue.reason === "product-version-mismatch" ? {
|
|
38056
|
+
previousProductVersion: issue.received,
|
|
38057
|
+
expectedProductVersion: issue.expected,
|
|
38058
|
+
previousPid: issue.pid
|
|
37933
38059
|
} : {
|
|
37934
38060
|
previousRpcSchemaVersion: issue.received,
|
|
37935
38061
|
expectedRpcSchemaVersion: issue.expected,
|
|
@@ -37954,17 +38080,27 @@ async function discoverRunningDaemonInfo(cwd, options = {}) {
|
|
|
37954
38080
|
if (!client) {
|
|
37955
38081
|
return {
|
|
37956
38082
|
info: undefined,
|
|
38083
|
+
compatibilityIssue: undefined,
|
|
37957
38084
|
recovery: options.recoverStale ? recoverStaleDaemonControlFiles(cwd) : emptyRecovery(cwd)
|
|
37958
38085
|
};
|
|
37959
38086
|
}
|
|
37960
38087
|
const health = await client.health().catch(() => {
|
|
37961
38088
|
return;
|
|
37962
38089
|
});
|
|
38090
|
+
const compatibilityIssue = runtimeRpcCompatibilityIssueFromHealth(cwd, client, health) ?? cliEntryStalenessIssue(cwd);
|
|
38091
|
+
if (compatibilityIssue) {
|
|
38092
|
+
return {
|
|
38093
|
+
info: undefined,
|
|
38094
|
+
compatibilityIssue,
|
|
38095
|
+
recovery: emptyRecovery(cwd)
|
|
38096
|
+
};
|
|
38097
|
+
}
|
|
37963
38098
|
if (health?.ok === true) {
|
|
37964
|
-
return { info: client.connectionInfo(), recovery: emptyRecovery(cwd) };
|
|
38099
|
+
return { info: client.connectionInfo(), compatibilityIssue: undefined, recovery: emptyRecovery(cwd) };
|
|
37965
38100
|
}
|
|
37966
38101
|
return {
|
|
37967
38102
|
info: undefined,
|
|
38103
|
+
compatibilityIssue: undefined,
|
|
37968
38104
|
recovery: options.recoverStale ? recoverStaleDaemonControlFiles(cwd, { removeUnhealthyConnection: true }) : emptyRecovery(cwd)
|
|
37969
38105
|
};
|
|
37970
38106
|
}
|
|
@@ -37972,26 +38108,40 @@ function runtimeRpcCompatibilityIssueFromHealth(cwd, client, health) {
|
|
|
37972
38108
|
if (!(health && typeof health === "object"))
|
|
37973
38109
|
return;
|
|
37974
38110
|
const body = health;
|
|
37975
|
-
if (body.ok !== false || body.error !== "runtime RPC version mismatch")
|
|
37976
|
-
return;
|
|
37977
38111
|
const connection = client.connectionInfo();
|
|
37978
38112
|
const pid = typeof connection.pid === "number" ? connection.pid : undefined;
|
|
37979
|
-
|
|
37980
|
-
reason: "rpc-version-mismatch",
|
|
37981
|
-
expected: RUNTIME_RPC_VERSION,
|
|
37982
|
-
received: typeof body.expected === "string" ? body.expected : "unknown",
|
|
38113
|
+
const location = {
|
|
37983
38114
|
connectionPath: connection.connectionPath ?? defaultDaemonConnectionPath(cwd),
|
|
37984
38115
|
lockPath: connection.lockPath ?? defaultDaemonLockPath(cwd),
|
|
37985
38116
|
pid,
|
|
37986
38117
|
pidAlive: pid !== undefined ? isPidAlive(pid) : false,
|
|
37987
38118
|
upgradeCommand: "archctx daemon upgrade"
|
|
37988
38119
|
};
|
|
38120
|
+
if (body.ok === true) {
|
|
38121
|
+
const expected = productVersionManifest().product.version;
|
|
38122
|
+
const received = typeof body.product?.product?.version === "string" ? body.product.product.version : "unknown";
|
|
38123
|
+
return received === expected ? undefined : {
|
|
38124
|
+
reason: "product-version-mismatch",
|
|
38125
|
+
expected,
|
|
38126
|
+
received,
|
|
38127
|
+
...location
|
|
38128
|
+
};
|
|
38129
|
+
}
|
|
38130
|
+
if (body.ok !== false || body.error !== "runtime RPC version mismatch")
|
|
38131
|
+
return;
|
|
38132
|
+
return {
|
|
38133
|
+
reason: "rpc-version-mismatch",
|
|
38134
|
+
expected: RUNTIME_RPC_VERSION,
|
|
38135
|
+
received: typeof body.expected === "string" ? body.expected : "unknown",
|
|
38136
|
+
...location
|
|
38137
|
+
};
|
|
37989
38138
|
}
|
|
37990
38139
|
function incompatibleDaemonStatus(issue) {
|
|
37991
38140
|
return {
|
|
37992
38141
|
running: issue.pidAlive,
|
|
37993
38142
|
protocol: "http-loopback",
|
|
37994
|
-
rpcVersionCompatible:
|
|
38143
|
+
rpcVersionCompatible: issue.reason === "product-version-mismatch",
|
|
38144
|
+
productVersionCompatible: issue.reason !== "product-version-mismatch",
|
|
37995
38145
|
connectionPath: issue.connectionPath,
|
|
37996
38146
|
lockPath: issue.lockPath,
|
|
37997
38147
|
pid: issue.pid,
|
|
@@ -38008,6 +38158,9 @@ function runtimeVersionUnsupportedMessage(issue) {
|
|
|
38008
38158
|
if (issue.reason === "stale-daemon-entry") {
|
|
38009
38159
|
return `archctxd (pid ${issue.pid ?? "unknown"}, started ${issue.received}) was spawned from an older copy of the archctx entrypoint than the one running this command (modified ${issue.expected}); run ${issue.upgradeCommand} to replace the local daemon.`;
|
|
38010
38160
|
}
|
|
38161
|
+
if (issue.reason === "product-version-mismatch") {
|
|
38162
|
+
return `archctxd product version ${issue.received} does not exactly match this CLI (${issue.expected}); run ${issue.upgradeCommand} to replace the local daemon.`;
|
|
38163
|
+
}
|
|
38011
38164
|
return `archctxd RPC version ${issue.received} is incompatible with this CLI (${issue.expected}); run ${issue.upgradeCommand} to replace the local daemon.`;
|
|
38012
38165
|
}
|
|
38013
38166
|
async function waitForPidExit(pid, timeoutMs) {
|