@devrouter/cli 0.1.1 → 0.1.3
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/dist/devrouter-lifecycle-worker.js +418 -119
- package/dist/devrouter.js +764 -226
- package/package.json +6 -1
- package/upgrade-prompts/0.1.2.md +57 -0
- package/upgrade-prompts/0.1.3.md +55 -0
package/dist/devrouter.js
CHANGED
|
@@ -4275,7 +4275,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs7.default.read
|
|
|
4275
4275
|
const config = parseConfig(parsed ?? {}, configPath);
|
|
4276
4276
|
const requiredVersion = config.devrouter?.version;
|
|
4277
4277
|
if (requiredVersion && !hasWarnedVersionMismatch) {
|
|
4278
|
-
const cliVersion = true ? "0.1.
|
|
4278
|
+
const cliVersion = true ? "0.1.3" : "0.0.0-dev";
|
|
4279
4279
|
if (cliVersion !== "0.0.0-dev" && compareSemver(requiredVersion, cliVersion) > 0) {
|
|
4280
4280
|
hasWarnedVersionMismatch = true;
|
|
4281
4281
|
process.stderr.write(
|
|
@@ -5263,10 +5263,11 @@ function serializeSnapshot(snapshot) {
|
|
|
5263
5263
|
throw new Error("Capacity reservation snapshot exceeds byte limit.");
|
|
5264
5264
|
return contents;
|
|
5265
5265
|
}
|
|
5266
|
-
var import_node_fs9, import_node_path11, MAX_BYTES2, CapacityHistoryError, CapacitySnapshotChangedError, CapacityStore;
|
|
5266
|
+
var import_node_crypto6, import_node_fs9, import_node_path11, MAX_BYTES2, CapacityHistoryError, CapacitySnapshotChangedError, CapacityStore;
|
|
5267
5267
|
var init_capacity_store = __esm({
|
|
5268
5268
|
"src/core/capacity-store.ts"() {
|
|
5269
5269
|
"use strict";
|
|
5270
|
+
import_node_crypto6 = require("crypto");
|
|
5270
5271
|
import_node_fs9 = __toESM(require("fs"));
|
|
5271
5272
|
import_node_path11 = __toESM(require("path"));
|
|
5272
5273
|
init_atomic_file();
|
|
@@ -5274,11 +5275,13 @@ var init_capacity_store = __esm({
|
|
|
5274
5275
|
init_file_lock();
|
|
5275
5276
|
MAX_BYTES2 = 1048576;
|
|
5276
5277
|
CapacityHistoryError = class extends Error {
|
|
5277
|
-
constructor(code) {
|
|
5278
|
+
constructor(code, cause = null, location = null) {
|
|
5278
5279
|
super(
|
|
5279
5280
|
code === "capacity-ledger-lost" ? "Capacity ledger history is lost; restore verified capacity-reservations.json." : "Capacity history cannot be proven; inspect the private lifecycle journals."
|
|
5280
5281
|
);
|
|
5281
5282
|
this.code = code;
|
|
5283
|
+
this.cause = cause;
|
|
5284
|
+
this.location = location;
|
|
5282
5285
|
this.name = "CapacityHistoryError";
|
|
5283
5286
|
}
|
|
5284
5287
|
};
|
|
@@ -5351,9 +5354,10 @@ var init_capacity_store = __esm({
|
|
|
5351
5354
|
const buffer = Buffer.alloc(MAX_BYTES2 + 1);
|
|
5352
5355
|
const count = import_node_fs9.default.readSync(descriptor, buffer, 0, buffer.length, 0);
|
|
5353
5356
|
if (count > MAX_BYTES2) throw new Error("Capacity reservation snapshot exceeds byte limit.");
|
|
5354
|
-
const
|
|
5357
|
+
const bytes2 = buffer.subarray(0, count);
|
|
5358
|
+
const value = JSON.parse(bytes2.toString("utf8"));
|
|
5355
5359
|
validate(value);
|
|
5356
|
-
this.ledgerGeneration =
|
|
5360
|
+
this.ledgerGeneration = this.generationIdentity(stat, bytes2);
|
|
5357
5361
|
if (value.revision < minimumRevision) return { kind: "stale", revision: value.revision };
|
|
5358
5362
|
this.observedLedger = true;
|
|
5359
5363
|
return { kind: "intact", revision: value.revision, snapshot: value };
|
|
@@ -5406,20 +5410,30 @@ var init_capacity_store = __esm({
|
|
|
5406
5410
|
return snapshot;
|
|
5407
5411
|
}
|
|
5408
5412
|
commit(snapshot) {
|
|
5409
|
-
|
|
5413
|
+
const contents = serializeSnapshot(snapshot);
|
|
5414
|
+
this.write(this.file, contents);
|
|
5410
5415
|
this.observedLedger = true;
|
|
5411
|
-
this.rememberGeneration();
|
|
5416
|
+
this.rememberGeneration(contents);
|
|
5412
5417
|
this.establish();
|
|
5413
5418
|
}
|
|
5414
5419
|
/** Remember the published snapshot identity for the next generation fence. */
|
|
5415
|
-
rememberGeneration() {
|
|
5420
|
+
rememberGeneration(contents) {
|
|
5416
5421
|
try {
|
|
5417
5422
|
const stat = import_node_fs9.default.statSync(this.file);
|
|
5418
|
-
this.ledgerGeneration = stat.isFile() ?
|
|
5423
|
+
this.ledgerGeneration = stat.isFile() ? this.generationIdentity(stat, contents) : void 0;
|
|
5419
5424
|
} catch {
|
|
5420
5425
|
this.ledgerGeneration = void 0;
|
|
5421
5426
|
}
|
|
5422
5427
|
}
|
|
5428
|
+
/**
|
|
5429
|
+
* File identity plus content digest. Deleting and recreating the snapshot can
|
|
5430
|
+
* reuse its inode number, so the inode alone cannot fence a replacement that
|
|
5431
|
+
* reuses a revision number.
|
|
5432
|
+
*/
|
|
5433
|
+
generationIdentity(stat, contents) {
|
|
5434
|
+
const digest3 = (0, import_node_crypto6.createHash)("sha256").update(contents).digest("hex");
|
|
5435
|
+
return `${stat.dev}:${stat.ino}:${digest3}`;
|
|
5436
|
+
}
|
|
5423
5437
|
/**
|
|
5424
5438
|
* Durable evidence that recorded history is gone, for a stop whose physical
|
|
5425
5439
|
* cessation is already proven. The caller holds that proof; this writes no
|
|
@@ -5898,11 +5912,11 @@ function retain(session, previous) {
|
|
|
5898
5912
|
environment: { ...environment }
|
|
5899
5913
|
};
|
|
5900
5914
|
}
|
|
5901
|
-
var
|
|
5915
|
+
var import_node_crypto7, import_node_fs10, import_node_path12, CONTROLLER_SNAPSHOT_BYTES, EVENT_KINDS, LEGACY_EVENT_KINDS, PROJECTION_STATUSES, ControllerStore;
|
|
5902
5916
|
var init_controller_store = __esm({
|
|
5903
5917
|
"src/core/controller-store.ts"() {
|
|
5904
5918
|
"use strict";
|
|
5905
|
-
|
|
5919
|
+
import_node_crypto7 = require("crypto");
|
|
5906
5920
|
import_node_fs10 = __toESM(require("fs"));
|
|
5907
5921
|
import_node_path12 = __toESM(require("path"));
|
|
5908
5922
|
init_atomic_file();
|
|
@@ -5993,7 +6007,7 @@ var init_controller_store = __esm({
|
|
|
5993
6007
|
provenance(identity2) {
|
|
5994
6008
|
if (identity2.version !== 2) throw new Error("Controller binding provenance is unavailable.");
|
|
5995
6009
|
return {
|
|
5996
|
-
digest: (0,
|
|
6010
|
+
digest: (0, import_node_crypto7.createHash)("sha256").update(JSON.stringify(["devrouter-controller-binding-v1", identity2.store, identity2.key])).digest("hex"),
|
|
5997
6011
|
enrolledEpoch: identity2.enrolledEpoch
|
|
5998
6012
|
};
|
|
5999
6013
|
}
|
|
@@ -6017,7 +6031,7 @@ var init_controller_store = __esm({
|
|
|
6017
6031
|
if (!current || current.store !== captured.store || current.epoch !== captured.epoch || JSON.stringify(current.fingerprint) !== JSON.stringify(captured.fingerprint) || identity2?.version !== 2)
|
|
6018
6032
|
throw new Error("Controller binding incarnation changed.");
|
|
6019
6033
|
this.checkProvenance(current, identity2);
|
|
6020
|
-
return (0,
|
|
6034
|
+
return (0, import_node_crypto7.createHmac)("sha256", Buffer.from(identity2.key, "hex")).update(JSON.stringify({ owner, config })).digest("hex");
|
|
6021
6035
|
};
|
|
6022
6036
|
}
|
|
6023
6037
|
read() {
|
|
@@ -6070,7 +6084,7 @@ var init_controller_store = __esm({
|
|
|
6070
6084
|
const identity2 = existing?.version === 2 ? existing : {
|
|
6071
6085
|
version: 2,
|
|
6072
6086
|
store,
|
|
6073
|
-
key: (0,
|
|
6087
|
+
key: (0, import_node_crypto7.randomBytes)(32).toString("hex"),
|
|
6074
6088
|
enrolledEpoch: epoch
|
|
6075
6089
|
};
|
|
6076
6090
|
if (existing?.version !== 2)
|
|
@@ -6116,7 +6130,7 @@ var init_controller_store = __esm({
|
|
|
6116
6130
|
if (!previous) {
|
|
6117
6131
|
previous = {
|
|
6118
6132
|
version: 2,
|
|
6119
|
-
store: (0,
|
|
6133
|
+
store: (0, import_node_crypto7.randomUUID)(),
|
|
6120
6134
|
epoch: 0,
|
|
6121
6135
|
revision: 0,
|
|
6122
6136
|
parkingRevision: 0,
|
|
@@ -6259,7 +6273,7 @@ var init_reliability_contract = __esm({
|
|
|
6259
6273
|
|
|
6260
6274
|
// src/core/reliability-operation-store.ts
|
|
6261
6275
|
function installedCliVersion() {
|
|
6262
|
-
return true ? "0.1.
|
|
6276
|
+
return true ? "0.1.3" : "0.0.0-dev";
|
|
6263
6277
|
}
|
|
6264
6278
|
function compareCliVersions(left, right) {
|
|
6265
6279
|
const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
@@ -6275,7 +6289,7 @@ function identityKey(identity2) {
|
|
|
6275
6289
|
if (!import_node_path13.default.isAbsolute(identity2.repoPath) || import_node_path13.default.resolve(identity2.repoPath) !== identity2.repoPath || identity2.repoPath.includes("\0") || identity2.workspace !== null && !isReliabilityId(identity2.workspace) || !["devpod", "devsy"].includes(identity2.provider)) {
|
|
6276
6290
|
throw new Error("Invalid reliability workspace identity.");
|
|
6277
6291
|
}
|
|
6278
|
-
return (0,
|
|
6292
|
+
return (0, import_node_crypto8.createHash)("sha256").update(identity2.repoPath).digest("hex");
|
|
6279
6293
|
}
|
|
6280
6294
|
function reliabilityOperationPath(identity2) {
|
|
6281
6295
|
return import_node_path13.default.join(DEVROUTER_HOME, "reliability", `${identityKey(identity2)}.json`);
|
|
@@ -6392,6 +6406,7 @@ function validate2(record5, identity2) {
|
|
|
6392
6406
|
"revision",
|
|
6393
6407
|
"state",
|
|
6394
6408
|
"worker",
|
|
6409
|
+
"stopWorkStarted",
|
|
6395
6410
|
"effectSequence",
|
|
6396
6411
|
"outcome",
|
|
6397
6412
|
"result",
|
|
@@ -6573,13 +6588,24 @@ function validate2(record5, identity2) {
|
|
|
6573
6588
|
throw new Error("Reliability worker identity is invalid.");
|
|
6574
6589
|
}
|
|
6575
6590
|
}
|
|
6591
|
+
if (record5.stopWorkStarted !== void 0 && record5.stopWorkStarted !== null) {
|
|
6592
|
+
if (record5.stopWorkStarted !== true) throw new Error("Invalid stop work marker.");
|
|
6593
|
+
}
|
|
6594
|
+
}
|
|
6595
|
+
function journalEntryLocation(name) {
|
|
6596
|
+
const printable = name.replace(/[^A-Za-z0-9._-]/g, "?");
|
|
6597
|
+
return printable.length > MAX_REPORTED_ENTRY_NAME ? `${printable.slice(0, MAX_REPORTED_ENTRY_NAME - 3)}...` : printable;
|
|
6576
6598
|
}
|
|
6577
6599
|
function createLifecycleCapacityStore(directory = import_node_path13.default.join(DEVROUTER_HOME, "controller")) {
|
|
6578
6600
|
return new CapacityStore(directory, void 0, () => {
|
|
6579
6601
|
try {
|
|
6580
6602
|
return listUnsettledCapacityBindings().floor;
|
|
6581
|
-
} catch {
|
|
6582
|
-
throw new CapacityHistoryError("capacity-history-unprovable")
|
|
6603
|
+
} catch (error) {
|
|
6604
|
+
throw error instanceof ReliabilityJournalError ? new CapacityHistoryError("capacity-history-unprovable", error.cause, error.location) : new CapacityHistoryError(
|
|
6605
|
+
"capacity-history-unprovable",
|
|
6606
|
+
"journal-enumeration-failed",
|
|
6607
|
+
null
|
|
6608
|
+
);
|
|
6583
6609
|
}
|
|
6584
6610
|
});
|
|
6585
6611
|
}
|
|
@@ -6638,11 +6664,12 @@ function readBoundedPrivateJson(file, label2) {
|
|
|
6638
6664
|
try {
|
|
6639
6665
|
const stat = import_node_fs11.default.fstatSync(descriptor);
|
|
6640
6666
|
if (!stat.isFile() || stat.uid !== process.getuid?.() || stat.size > MAX_RECORD_BYTES || (stat.mode & 63) !== 0) {
|
|
6641
|
-
throw new
|
|
6667
|
+
throw new JournalFileGuardError(`${label2} is not a bounded private file.`);
|
|
6642
6668
|
}
|
|
6643
6669
|
const bytes2 = Buffer.alloc(MAX_RECORD_BYTES + 1);
|
|
6644
6670
|
const count = import_node_fs11.default.readSync(descriptor, bytes2, 0, bytes2.length, 0);
|
|
6645
|
-
if (count > MAX_RECORD_BYTES)
|
|
6671
|
+
if (count > MAX_RECORD_BYTES)
|
|
6672
|
+
throw new JournalFileGuardError(`${label2} exceeds its byte limit.`);
|
|
6646
6673
|
return JSON.parse(bytes2.subarray(0, count).toString("utf8"));
|
|
6647
6674
|
} finally {
|
|
6648
6675
|
import_node_fs11.default.closeSync(descriptor);
|
|
@@ -6650,7 +6677,11 @@ function readBoundedPrivateJson(file, label2) {
|
|
|
6650
6677
|
}
|
|
6651
6678
|
function assertReliabilityEnumerationTime(startedAtMs) {
|
|
6652
6679
|
if (performance.now() - startedAtMs > MAX_RELIABILITY_ENUMERATION_MS)
|
|
6653
|
-
throw new
|
|
6680
|
+
throw new ReliabilityJournalError(
|
|
6681
|
+
"journal-enumeration-timeout",
|
|
6682
|
+
null,
|
|
6683
|
+
"Reliability journal enumeration exceeded its time limit."
|
|
6684
|
+
);
|
|
6654
6685
|
}
|
|
6655
6686
|
function reliabilityDirectory() {
|
|
6656
6687
|
return import_node_path13.default.join(DEVROUTER_HOME, "reliability");
|
|
@@ -6671,22 +6702,56 @@ function listReliabilityOperations() {
|
|
|
6671
6702
|
stat = import_node_fs11.default.lstatSync(directory);
|
|
6672
6703
|
} catch (error) {
|
|
6673
6704
|
if (error.code === "ENOENT") return [];
|
|
6674
|
-
throw
|
|
6705
|
+
throw new ReliabilityJournalError(
|
|
6706
|
+
"journal-directory-unreadable",
|
|
6707
|
+
null,
|
|
6708
|
+
"Reliability journal directory could not be read."
|
|
6709
|
+
);
|
|
6675
6710
|
}
|
|
6676
6711
|
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
6677
|
-
throw new
|
|
6712
|
+
throw new ReliabilityJournalError(
|
|
6713
|
+
"journal-directory-unsafe",
|
|
6714
|
+
null,
|
|
6715
|
+
"Reliability journal directory is unsafe."
|
|
6716
|
+
);
|
|
6678
6717
|
if (stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
|
|
6679
|
-
throw new
|
|
6718
|
+
throw new ReliabilityJournalError(
|
|
6719
|
+
"journal-directory-unsafe",
|
|
6720
|
+
null,
|
|
6721
|
+
"Reliability journal directory is not private."
|
|
6722
|
+
);
|
|
6680
6723
|
const entries = [];
|
|
6681
|
-
|
|
6724
|
+
let handle;
|
|
6725
|
+
try {
|
|
6726
|
+
handle = import_node_fs11.default.opendirSync(directory);
|
|
6727
|
+
} catch {
|
|
6728
|
+
throw new ReliabilityJournalError(
|
|
6729
|
+
"journal-directory-unreadable",
|
|
6730
|
+
null,
|
|
6731
|
+
"Reliability journal directory could not be read."
|
|
6732
|
+
);
|
|
6733
|
+
}
|
|
6682
6734
|
try {
|
|
6683
6735
|
for (; ; ) {
|
|
6684
6736
|
assertReliabilityEnumerationTime(startedAtMs);
|
|
6685
|
-
|
|
6737
|
+
let entry;
|
|
6738
|
+
try {
|
|
6739
|
+
entry = handle.readSync();
|
|
6740
|
+
} catch {
|
|
6741
|
+
throw new ReliabilityJournalError(
|
|
6742
|
+
"journal-directory-unreadable",
|
|
6743
|
+
null,
|
|
6744
|
+
"Reliability journal directory could not be read."
|
|
6745
|
+
);
|
|
6746
|
+
}
|
|
6686
6747
|
if (!entry) break;
|
|
6687
6748
|
entries.push(entry);
|
|
6688
6749
|
if (entries.length > MAX_RELIABILITY_DIRECTORY_ENTRIES)
|
|
6689
|
-
throw new
|
|
6750
|
+
throw new ReliabilityJournalError(
|
|
6751
|
+
"journal-enumeration-limit",
|
|
6752
|
+
null,
|
|
6753
|
+
"Reliability journal directory exceeds its entry limit."
|
|
6754
|
+
);
|
|
6690
6755
|
}
|
|
6691
6756
|
} finally {
|
|
6692
6757
|
handle.closeSync();
|
|
@@ -6695,27 +6760,82 @@ function listReliabilityOperations() {
|
|
|
6695
6760
|
for (const entry of entries) {
|
|
6696
6761
|
assertReliabilityEnumerationTime(startedAtMs);
|
|
6697
6762
|
if (entry.isSymbolicLink())
|
|
6698
|
-
throw new
|
|
6763
|
+
throw new ReliabilityJournalError(
|
|
6764
|
+
"journal-entry-unsupported",
|
|
6765
|
+
journalEntryLocation(entry.name),
|
|
6766
|
+
"Reliability journal directory contains a symlink."
|
|
6767
|
+
);
|
|
6699
6768
|
if (!entry.isFile())
|
|
6700
|
-
throw new
|
|
6769
|
+
throw new ReliabilityJournalError(
|
|
6770
|
+
"journal-entry-unsupported",
|
|
6771
|
+
journalEntryLocation(entry.name),
|
|
6772
|
+
"Reliability journal directory contains an unsupported entry."
|
|
6773
|
+
);
|
|
6701
6774
|
if (RELIABILITY_LOCK_NAME_RE.test(entry.name) || RELIABILITY_ATOMIC_TEMP_NAME_RE.test(entry.name))
|
|
6702
6775
|
continue;
|
|
6703
6776
|
const match = RELIABILITY_JOURNAL_NAME_RE.exec(entry.name);
|
|
6704
|
-
if (!match)
|
|
6777
|
+
if (!match)
|
|
6778
|
+
throw new ReliabilityJournalError(
|
|
6779
|
+
"journal-entry-unsupported",
|
|
6780
|
+
journalEntryLocation(entry.name),
|
|
6781
|
+
"Reliability journal directory contains an unsupported entry."
|
|
6782
|
+
);
|
|
6705
6783
|
journals.push({ name: entry.name, key: match[1] });
|
|
6706
6784
|
}
|
|
6707
6785
|
if (journals.length > MAX_RELIABILITY_JOURNALS)
|
|
6708
|
-
throw new
|
|
6786
|
+
throw new ReliabilityJournalError(
|
|
6787
|
+
"journal-enumeration-limit",
|
|
6788
|
+
null,
|
|
6789
|
+
"Reliability journal directory exceeds its journal limit."
|
|
6790
|
+
);
|
|
6709
6791
|
journals.sort((left, right) => left.name.localeCompare(right.name));
|
|
6710
6792
|
const records = [];
|
|
6711
6793
|
for (const journal of journals) {
|
|
6712
6794
|
assertReliabilityEnumerationTime(startedAtMs);
|
|
6713
6795
|
const file = import_node_path13.default.join(directory, journal.name);
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6796
|
+
let raw;
|
|
6797
|
+
try {
|
|
6798
|
+
raw = readBoundedPrivateJson(file, "Reliability journal");
|
|
6799
|
+
} catch (error) {
|
|
6800
|
+
const fsCode = error?.code;
|
|
6801
|
+
const cause = error instanceof JournalFileGuardError ? "journal-entry-unsafe" : error instanceof SyntaxError || !fsCode ? "journal-invalid" : "journal-unreadable";
|
|
6802
|
+
throw new ReliabilityJournalError(
|
|
6803
|
+
cause,
|
|
6804
|
+
journalEntryLocation(journal.name),
|
|
6805
|
+
error instanceof JournalFileGuardError ? error.message : cause === "journal-invalid" ? "Reliability journal entry is invalid." : "Reliability journal entry could not be read."
|
|
6806
|
+
);
|
|
6807
|
+
}
|
|
6808
|
+
if (raw === void 0)
|
|
6809
|
+
throw new ReliabilityJournalError(
|
|
6810
|
+
"journal-unstable",
|
|
6811
|
+
journalEntryLocation(journal.name),
|
|
6812
|
+
"Reliability journal disappeared during enumeration."
|
|
6813
|
+
);
|
|
6814
|
+
let identity2;
|
|
6815
|
+
let record5;
|
|
6816
|
+
try {
|
|
6817
|
+
identity2 = journalIdentity(raw);
|
|
6818
|
+
if (identityKey(identity2) !== journal.key)
|
|
6819
|
+
throw new ReliabilityJournalError(
|
|
6820
|
+
"journal-identity-mismatch",
|
|
6821
|
+
journalEntryLocation(journal.name),
|
|
6822
|
+
"Reliability journal filename does not match its identity."
|
|
6823
|
+
);
|
|
6824
|
+
record5 = readReliabilityOperation(identity2);
|
|
6825
|
+
} catch (error) {
|
|
6826
|
+
if (error instanceof ReliabilityJournalError) throw error;
|
|
6827
|
+
throw new ReliabilityJournalError(
|
|
6828
|
+
"journal-invalid",
|
|
6829
|
+
journalEntryLocation(journal.name),
|
|
6830
|
+
"Reliability journal entry is invalid."
|
|
6831
|
+
);
|
|
6832
|
+
}
|
|
6833
|
+
if (!record5)
|
|
6834
|
+
throw new ReliabilityJournalError(
|
|
6835
|
+
"journal-unstable",
|
|
6836
|
+
journalEntryLocation(journal.name),
|
|
6837
|
+
"Reliability journal disappeared during enumeration."
|
|
6838
|
+
);
|
|
6719
6839
|
records.push(record5);
|
|
6720
6840
|
assertReliabilityEnumerationTime(startedAtMs);
|
|
6721
6841
|
}
|
|
@@ -6872,11 +6992,11 @@ function setReliabilityHumanPin(identity2, expectedJournalRevision, expectedProt
|
|
|
6872
6992
|
};
|
|
6873
6993
|
});
|
|
6874
6994
|
}
|
|
6875
|
-
var
|
|
6995
|
+
var import_node_crypto8, import_node_fs11, import_node_path13, import_node_util3, MAX_RECORD_BYTES, MAX_RELIABILITY_JOURNALS, MAX_RELIABILITY_DIRECTORY_ENTRIES, MAX_RELIABILITY_ENUMERATION_MS, RELIABILITY_JOURNAL_NAME_RE, RELIABILITY_LOCK_NAME_RE, RELIABILITY_ATOMIC_TEMP_NAME_RE, ReliabilityJournalError, MAX_REPORTED_ENTRY_NAME, JournalFileGuardError;
|
|
6876
6996
|
var init_reliability_operation_store = __esm({
|
|
6877
6997
|
"src/core/reliability-operation-store.ts"() {
|
|
6878
6998
|
"use strict";
|
|
6879
|
-
|
|
6999
|
+
import_node_crypto8 = require("crypto");
|
|
6880
7000
|
import_node_fs11 = __toESM(require("fs"));
|
|
6881
7001
|
import_node_path13 = __toESM(require("path"));
|
|
6882
7002
|
import_node_util3 = require("util");
|
|
@@ -6893,6 +7013,21 @@ var init_reliability_operation_store = __esm({
|
|
|
6893
7013
|
RELIABILITY_JOURNAL_NAME_RE = /^([0-9a-f]{64})\.json$/;
|
|
6894
7014
|
RELIABILITY_LOCK_NAME_RE = /^[0-9a-f]{64}\.json\.lock(?:\.[0-9]+\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.candidate(?:\.stale)?|\.queue\.[0-9]+\.[0-9]+\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}(?:\.candidate)?)?$/;
|
|
6895
7015
|
RELIABILITY_ATOMIC_TEMP_NAME_RE = /^\.[0-9a-f]{64}\.json\.[0-9]+\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.tmp$/;
|
|
7016
|
+
ReliabilityJournalError = class extends Error {
|
|
7017
|
+
constructor(cause, location, message) {
|
|
7018
|
+
super(message);
|
|
7019
|
+
this.cause = cause;
|
|
7020
|
+
this.location = location;
|
|
7021
|
+
this.name = "ReliabilityJournalError";
|
|
7022
|
+
}
|
|
7023
|
+
};
|
|
7024
|
+
MAX_REPORTED_ENTRY_NAME = 160;
|
|
7025
|
+
JournalFileGuardError = class extends Error {
|
|
7026
|
+
constructor(message) {
|
|
7027
|
+
super(message);
|
|
7028
|
+
this.name = "JournalFileGuardError";
|
|
7029
|
+
}
|
|
7030
|
+
};
|
|
6896
7031
|
}
|
|
6897
7032
|
});
|
|
6898
7033
|
|
|
@@ -7258,7 +7393,7 @@ var init_managed_stop_baseline = __esm({
|
|
|
7258
7393
|
|
|
7259
7394
|
// src/core/managed-runtime-state.ts
|
|
7260
7395
|
function stateKey(repoPath, workspace) {
|
|
7261
|
-
return (0,
|
|
7396
|
+
return (0, import_node_crypto9.createHash)("sha256").update(`${repoPath}\0${workspace ?? ""}`, "utf-8").digest("hex");
|
|
7262
7397
|
}
|
|
7263
7398
|
function managedRuntimeStatePath(repoPath, workspace) {
|
|
7264
7399
|
return import_node_path17.default.join(DEVROUTER_HOME, "managed-runtime", `${stateKey(repoPath, workspace)}.json`);
|
|
@@ -7337,11 +7472,11 @@ function readManagedRuntimeState(repoPath, workspace, read2 = (file) => import_n
|
|
|
7337
7472
|
}
|
|
7338
7473
|
return validateState(parsed, repoPath, workspace);
|
|
7339
7474
|
}
|
|
7340
|
-
var
|
|
7475
|
+
var import_node_crypto9, import_node_fs13, import_node_path17;
|
|
7341
7476
|
var init_managed_runtime_state = __esm({
|
|
7342
7477
|
"src/core/managed-runtime-state.ts"() {
|
|
7343
7478
|
"use strict";
|
|
7344
|
-
|
|
7479
|
+
import_node_crypto9 = require("crypto");
|
|
7345
7480
|
import_node_fs13 = __toESM(require("fs"));
|
|
7346
7481
|
import_node_path17 = __toESM(require("path"));
|
|
7347
7482
|
init_atomic_file();
|
|
@@ -8416,7 +8551,7 @@ async function observeControllerBinding(directory, input2) {
|
|
|
8416
8551
|
};
|
|
8417
8552
|
}
|
|
8418
8553
|
async function controllerRequest(directory, input2, emit, timeoutMs) {
|
|
8419
|
-
const request2 = parseControllerRequest({ ...input2, version: 1, id: (0,
|
|
8554
|
+
const request2 = parseControllerRequest({ ...input2, version: 1, id: (0, import_node_crypto10.randomUUID)() });
|
|
8420
8555
|
const socketPath = import_node_path20.default.join(directory, "control.sock");
|
|
8421
8556
|
const stat = import_node_fs14.default.lstatSync(socketPath);
|
|
8422
8557
|
if (!stat.isSocket() || stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
|
|
@@ -8426,7 +8561,7 @@ async function controllerRequest(directory, input2, emit, timeoutMs) {
|
|
|
8426
8561
|
let buffer = Buffer.alloc(0);
|
|
8427
8562
|
let handshake = false;
|
|
8428
8563
|
let completed = false;
|
|
8429
|
-
const handshakeId = (0,
|
|
8564
|
+
const handshakeId = (0, import_node_crypto10.randomUUID)();
|
|
8430
8565
|
const timeout = request2.method === "watch" || request2.method === "operation-watch" ? Math.min(request2.timeout + 5, 2147483) * 1e3 : 5e3;
|
|
8431
8566
|
const timer = setTimeout(
|
|
8432
8567
|
() => {
|
|
@@ -8492,11 +8627,11 @@ async function controllerRequest(directory, input2, emit, timeoutMs) {
|
|
|
8492
8627
|
});
|
|
8493
8628
|
});
|
|
8494
8629
|
}
|
|
8495
|
-
var
|
|
8630
|
+
var import_node_crypto10, import_node_fs14, import_node_net, import_node_path20, CONTROLLER_OPERATION_WATCH_SECONDS, CONTROLLER_OPERATION_DEFAULT_WAIT_SECONDS, CONTROLLER_OPERATION_MAX_WAIT_SECONDS, CONTROLLER_ID_RE2, ControllerResponseDeadlineError, ControllerOperationSubmissionError;
|
|
8496
8631
|
var init_controller_client = __esm({
|
|
8497
8632
|
"src/core/controller-client.ts"() {
|
|
8498
8633
|
"use strict";
|
|
8499
|
-
|
|
8634
|
+
import_node_crypto10 = require("crypto");
|
|
8500
8635
|
import_node_fs14 = __toESM(require("fs"));
|
|
8501
8636
|
import_node_net = __toESM(require("net"));
|
|
8502
8637
|
import_node_path20 = __toESM(require("path"));
|
|
@@ -8632,11 +8767,11 @@ var init_reliability_output = __esm({
|
|
|
8632
8767
|
|
|
8633
8768
|
// src/core/controller-monitor.ts
|
|
8634
8769
|
function controllerCapability(selector) {
|
|
8635
|
-
return selector === "runtime" ? "runtime" : `app-${(0,
|
|
8770
|
+
return selector === "runtime" ? "runtime" : `app-${(0, import_node_crypto11.createHash)("sha256").update(selector).digest("hex")}`;
|
|
8636
8771
|
}
|
|
8637
8772
|
function sessionConsumerId(input2) {
|
|
8638
8773
|
const { store, epoch, session, generation } = input2;
|
|
8639
|
-
return `session-${(0,
|
|
8774
|
+
return `session-${(0, import_node_crypto11.createHash)("sha256").update(JSON.stringify([store, epoch, session, generation])).digest("hex")}`;
|
|
8640
8775
|
}
|
|
8641
8776
|
function environmentIdentity(environment) {
|
|
8642
8777
|
return {
|
|
@@ -8657,11 +8792,11 @@ function parkingConsumers(consumers) {
|
|
|
8657
8792
|
consentRevision
|
|
8658
8793
|
})).sort((a, b) => a.id.localeCompare(b.id));
|
|
8659
8794
|
}
|
|
8660
|
-
var
|
|
8795
|
+
var import_node_crypto11, import_node_util7, ControllerObservationBindingChanged, UNFINISHED_PARK_SCAN_MS, ControllerMonitor;
|
|
8661
8796
|
var init_controller_monitor = __esm({
|
|
8662
8797
|
"src/core/controller-monitor.ts"() {
|
|
8663
8798
|
"use strict";
|
|
8664
|
-
|
|
8799
|
+
import_node_crypto11 = require("crypto");
|
|
8665
8800
|
import_node_util7 = require("util");
|
|
8666
8801
|
init_reliability_operation_store();
|
|
8667
8802
|
init_reliability_output();
|
|
@@ -8935,7 +9070,7 @@ var init_controller_monitor = __esm({
|
|
|
8935
9070
|
const projections = /* @__PURE__ */ new Map();
|
|
8936
9071
|
for (const consumer of consumers) {
|
|
8937
9072
|
const transient = structuredClone(journal.state);
|
|
8938
|
-
const consumerId = `observer-${(0,
|
|
9073
|
+
const consumerId = `observer-${(0, import_node_crypto11.createHash)("sha256").update(consumer.id).digest("hex")}`;
|
|
8939
9074
|
transient.consumers = [
|
|
8940
9075
|
{
|
|
8941
9076
|
id: consumerId,
|
|
@@ -9055,9 +9190,11 @@ function listDevsyWorkspaces() {
|
|
|
9055
9190
|
);
|
|
9056
9191
|
if (result.status !== 0) {
|
|
9057
9192
|
const details = [result.error?.message, result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
9058
|
-
|
|
9193
|
+
const failure2 = new Error(
|
|
9059
9194
|
`devsy workspace list failed: ${details || "devsy is not installed or unavailable"}`
|
|
9060
9195
|
);
|
|
9196
|
+
if (result.error) failure2.code = result.error.code;
|
|
9197
|
+
throw failure2;
|
|
9061
9198
|
}
|
|
9062
9199
|
let parsed;
|
|
9063
9200
|
try {
|
|
@@ -9353,7 +9490,7 @@ function writeManifestRecord(cacheRoot, manifest) {
|
|
|
9353
9490
|
import_node_fs16.default.mkdirSync(directory, { recursive: true, mode: 448 });
|
|
9354
9491
|
const temporary = import_node_path22.default.join(
|
|
9355
9492
|
directory,
|
|
9356
|
-
`.${DEVSY_AGENT_MANIFEST_FILE}.${process.pid}.${(0,
|
|
9493
|
+
`.${DEVSY_AGENT_MANIFEST_FILE}.${process.pid}.${(0, import_node_crypto12.randomUUID)()}.tmp`
|
|
9357
9494
|
);
|
|
9358
9495
|
const record5 = {
|
|
9359
9496
|
version: 1,
|
|
@@ -9451,7 +9588,7 @@ function managedBinaryPath(cacheRoot, devsyVersion, asset) {
|
|
|
9451
9588
|
return import_node_path22.default.join(cacheRoot, `v${devsyVersion}`, asset.name);
|
|
9452
9589
|
}
|
|
9453
9590
|
function hashOpenFile(file) {
|
|
9454
|
-
const digest3 = (0,
|
|
9591
|
+
const digest3 = (0, import_node_crypto12.createHash)("sha256");
|
|
9455
9592
|
const buffer = Buffer.allocUnsafe(1024 * 1024);
|
|
9456
9593
|
let position = 0;
|
|
9457
9594
|
for (; ; ) {
|
|
@@ -9647,7 +9784,7 @@ async function downloadAndPublish(asset, binaryPath, fetcher, githubCliDownloade
|
|
|
9647
9784
|
import_node_fs16.default.mkdirSync(directory, { recursive: true, mode: 448 });
|
|
9648
9785
|
const temporaryPath = import_node_path22.default.join(
|
|
9649
9786
|
directory,
|
|
9650
|
-
`.${import_node_path22.default.basename(binaryPath)}.${process.pid}.${(0,
|
|
9787
|
+
`.${import_node_path22.default.basename(binaryPath)}.${process.pid}.${(0, import_node_crypto12.randomUUID)()}.tmp`
|
|
9651
9788
|
);
|
|
9652
9789
|
let handle;
|
|
9653
9790
|
try {
|
|
@@ -9659,7 +9796,7 @@ async function downloadAndPublish(asset, binaryPath, fetcher, githubCliDownloade
|
|
|
9659
9796
|
directFailure = error;
|
|
9660
9797
|
}
|
|
9661
9798
|
handle = await import_node_fs16.default.promises.open(temporaryPath, "wx", 384);
|
|
9662
|
-
const digest3 = (0,
|
|
9799
|
+
const digest3 = (0, import_node_crypto12.createHash)("sha256");
|
|
9663
9800
|
let size = 0;
|
|
9664
9801
|
const writeChunk = async (chunk) => {
|
|
9665
9802
|
size += chunk.byteLength;
|
|
@@ -9795,12 +9932,12 @@ async function prepareDevsyAgent(options = {}) {
|
|
|
9795
9932
|
return { ...preparedFromInspection(published), changed: true, transport };
|
|
9796
9933
|
});
|
|
9797
9934
|
}
|
|
9798
|
-
var import_node_child_process7,
|
|
9935
|
+
var import_node_child_process7, import_node_crypto12, import_node_fs16, import_node_path22, PINNED_DEVSY_AGENT_VERSION, SUPPORTED_DEVSY_MIN_VERSION, SUPPORTED_DEVSY_MAX_VERSION, SUPPORTED_DEVSY_RANGE, DEVSY_AGENT_SETUP_COMMAND, DEVSY_RELEASE_TAG_PREFIX, DEVSY_RELEASE_METADATA_BASE_URL, DEVSY_AGENT_ASSETS, DevsyAgentReadinessError, DEVSY_AGENT_CACHE_LOCK, DEVSY_AGENT_LOCK_WAIT_MS, DEVSY_AGENT_MANIFEST_FILE, DEVSY_AGENT_ASSET_NAMES, GITHUB_CLI_STDERR_TAIL_BYTES;
|
|
9799
9936
|
var init_devsy_agent = __esm({
|
|
9800
9937
|
"src/core/devsy-agent.ts"() {
|
|
9801
9938
|
"use strict";
|
|
9802
9939
|
import_node_child_process7 = require("child_process");
|
|
9803
|
-
|
|
9940
|
+
import_node_crypto12 = require("crypto");
|
|
9804
9941
|
import_node_fs16 = __toESM(require("fs"));
|
|
9805
9942
|
import_node_path22 = __toESM(require("path"));
|
|
9806
9943
|
init_file_lock();
|
|
@@ -10037,7 +10174,7 @@ function isWildcard(values) {
|
|
|
10037
10174
|
return values?.length === 1 && values[0] === "*";
|
|
10038
10175
|
}
|
|
10039
10176
|
function sha256(contents) {
|
|
10040
|
-
return (0,
|
|
10177
|
+
return (0, import_node_crypto13.createHash)("sha256").update(contents, "utf-8").digest("hex");
|
|
10041
10178
|
}
|
|
10042
10179
|
function safeComposeProject(value) {
|
|
10043
10180
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(value)) {
|
|
@@ -10123,6 +10260,9 @@ ${JSON.stringify(effective, null, 2)}
|
|
|
10123
10260
|
contents
|
|
10124
10261
|
};
|
|
10125
10262
|
}
|
|
10263
|
+
function writeManagedDevcontainerConfig(plan) {
|
|
10264
|
+
writeFileAtomically(plan.generatedPath, plan.contents);
|
|
10265
|
+
}
|
|
10126
10266
|
function inspectManagedDevcontainerGeneratedConfig(plan) {
|
|
10127
10267
|
let stat;
|
|
10128
10268
|
try {
|
|
@@ -10260,12 +10400,12 @@ function stopExactManagedService(containerId, service, options) {
|
|
|
10260
10400
|
throw new Error(`Could not stop exact managed service '${service}' (${containerId}).`);
|
|
10261
10401
|
}
|
|
10262
10402
|
}
|
|
10263
|
-
var import_node_child_process8,
|
|
10403
|
+
var import_node_child_process8, import_node_crypto13, import_node_fs18, import_node_path25, import_yaml3, MANAGED_DEVCONTAINER_PATH, MANAGED_DEVCONTAINER_MARKER, COMPOSE_HASH_TIMEOUT_MS;
|
|
10264
10404
|
var init_devcontainer_profile = __esm({
|
|
10265
10405
|
"src/core/devcontainer-profile.ts"() {
|
|
10266
10406
|
"use strict";
|
|
10267
10407
|
import_node_child_process8 = require("child_process");
|
|
10268
|
-
|
|
10408
|
+
import_node_crypto13 = require("crypto");
|
|
10269
10409
|
import_node_fs18 = __toESM(require("fs"));
|
|
10270
10410
|
import_node_path25 = __toESM(require("path"));
|
|
10271
10411
|
import_yaml3 = __toESM(require("yaml"));
|
|
@@ -10291,7 +10431,11 @@ function listDevpodWorkspacesRaw(options = {}) {
|
|
|
10291
10431
|
}
|
|
10292
10432
|
if (result.error || result.status !== 0) {
|
|
10293
10433
|
const details = [result.error?.message, result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
10294
|
-
|
|
10434
|
+
const failure2 = new Error(
|
|
10435
|
+
`devpod list failed: ${details || "devpod is not installed or unavailable"}`
|
|
10436
|
+
);
|
|
10437
|
+
if (result.error) failure2.code = result.error.code;
|
|
10438
|
+
throw failure2;
|
|
10295
10439
|
}
|
|
10296
10440
|
let parsed;
|
|
10297
10441
|
try {
|
|
@@ -10583,25 +10727,23 @@ function writeWorkspaceRuntimeConfig(config) {
|
|
|
10583
10727
|
writeFileAtomically(RUNTIME_CONFIG_FILE, `${JSON.stringify(next, null, 2)}
|
|
10584
10728
|
`);
|
|
10585
10729
|
}
|
|
10730
|
+
function readRegistrySnapshot(runtime, read2, snapshots) {
|
|
10731
|
+
try {
|
|
10732
|
+
return read2();
|
|
10733
|
+
} catch (error) {
|
|
10734
|
+
if (error?.code === "ENOENT") return void 0;
|
|
10735
|
+
snapshots.unavailable.push(runtime);
|
|
10736
|
+
snapshots.errors[runtime] = error instanceof Error ? error.message : String(error);
|
|
10737
|
+
return void 0;
|
|
10738
|
+
}
|
|
10739
|
+
}
|
|
10586
10740
|
function getWorkspaceRegistrySnapshots() {
|
|
10587
10741
|
if (cachedSnapshots) return cachedSnapshots;
|
|
10588
10742
|
const snapshots = { unavailable: [], errors: {} };
|
|
10589
|
-
|
|
10590
|
-
|
|
10591
|
-
|
|
10592
|
-
|
|
10593
|
-
snapshots.unavailable.push("devsy");
|
|
10594
|
-
snapshots.errors.devsy = error instanceof Error ? error.message : String(error);
|
|
10595
|
-
}
|
|
10596
|
-
}
|
|
10597
|
-
if (isRuntimeInstalled("devpod")) {
|
|
10598
|
-
try {
|
|
10599
|
-
snapshots.devpod = listDevpodWorkspacesRaw();
|
|
10600
|
-
} catch (error) {
|
|
10601
|
-
snapshots.unavailable.push("devpod");
|
|
10602
|
-
snapshots.errors.devpod = error instanceof Error ? error.message : String(error);
|
|
10603
|
-
}
|
|
10604
|
-
}
|
|
10743
|
+
const devsy = readRegistrySnapshot("devsy", listDevsyWorkspaces, snapshots);
|
|
10744
|
+
if (devsy !== void 0) snapshots.devsy = devsy;
|
|
10745
|
+
const devpod = readRegistrySnapshot("devpod", listDevpodWorkspacesRaw, snapshots);
|
|
10746
|
+
if (devpod !== void 0) snapshots.devpod = devpod;
|
|
10605
10747
|
cachedSnapshots = snapshots;
|
|
10606
10748
|
return snapshots;
|
|
10607
10749
|
}
|
|
@@ -11380,11 +11522,19 @@ function absentRegistrationIdentity(state) {
|
|
|
11380
11522
|
resetWorkspaceRuntimeCaches();
|
|
11381
11523
|
if (resolveWorkspaceRuntimeOrDefault(state.repoPath) !== "devsy")
|
|
11382
11524
|
throw new Error("Stop provider changed.");
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11525
|
+
const linked = isLinkedWorktree(state.repoPath);
|
|
11526
|
+
if (linked !== (state.workspace !== void 0))
|
|
11527
|
+
throw new Error("Absent stop requires the exact workspace identity.");
|
|
11528
|
+
let identity2;
|
|
11529
|
+
if (linked) {
|
|
11530
|
+
const workspace = state.workspace;
|
|
11531
|
+
const record5 = readWorkspaceOwnership(state.repoPath, workspace);
|
|
11532
|
+
if (!record5 || record5.workspace !== workspace || record5.devpodId !== state.devpodId || !sameWorkspacePath(record5.worktreePath, state.repoPath) || resolveWorktreeWorkspace(state.repoPath) !== workspace || inspectWorkspaceOwnership(record5, listGitWorktrees(state.repoPath), void 0).ownerStatus !== "present")
|
|
11533
|
+
throw new Error("Absent stop workspace ownership changed.");
|
|
11534
|
+
identity2 = { kind: "linked", record: record5, gitCommonDir: resolveGitCommonDir(state.repoPath) };
|
|
11535
|
+
} else {
|
|
11536
|
+
identity2 = { kind: "primary", repoPath: state.repoPath, devpodId: state.devpodId };
|
|
11537
|
+
}
|
|
11388
11538
|
for (const entries of [
|
|
11389
11539
|
listDevsyWorkspaces(),
|
|
11390
11540
|
listDevpodWorkspacesRaw({ allowMissingExecutable: true })
|
|
@@ -11394,7 +11544,7 @@ function absentRegistrationIdentity(state) {
|
|
|
11394
11544
|
))
|
|
11395
11545
|
throw new Error("Absent stop requires both provider registrations to remain absent.");
|
|
11396
11546
|
}
|
|
11397
|
-
return
|
|
11547
|
+
return identity2;
|
|
11398
11548
|
}
|
|
11399
11549
|
function replacementObservation(state) {
|
|
11400
11550
|
resetWorkspaceRuntimeCaches();
|
|
@@ -11504,7 +11654,7 @@ function proveManagedStop(state) {
|
|
|
11504
11654
|
const identityKeys = ["context", "providerId", "uid", "sourcePath", "sourceContainer"];
|
|
11505
11655
|
const current = identityOf(owner.workspace);
|
|
11506
11656
|
const changed = identityKeys.filter((key) => baseline[key] !== current[key]);
|
|
11507
|
-
if (changed.length === 0 &&
|
|
11657
|
+
if (changed.length === 0 && inspectManagedStopContainers(baseline.project, baseline.endpoint).length === 0) {
|
|
11508
11658
|
proveAbsentPopulationStop(state, baseline, current);
|
|
11509
11659
|
return { status: "proven-absent", containers: [] };
|
|
11510
11660
|
}
|
|
@@ -11751,7 +11901,7 @@ function parseDnsHostsFromSubjectAltName(subjectAltName) {
|
|
|
11751
11901
|
return normalizeUniqueHosts(names);
|
|
11752
11902
|
}
|
|
11753
11903
|
function parseCertificateDnsHosts(pem) {
|
|
11754
|
-
const certificate = new
|
|
11904
|
+
const certificate = new import_node_crypto14.X509Certificate(pem);
|
|
11755
11905
|
const subjectAltName = certificate.subjectAltName ?? "";
|
|
11756
11906
|
if (subjectAltName.length === 0) {
|
|
11757
11907
|
return [];
|
|
@@ -11951,12 +12101,12 @@ Run: ${tlsSetupCommand(options.repoPath)}`
|
|
|
11951
12101
|
);
|
|
11952
12102
|
}
|
|
11953
12103
|
}
|
|
11954
|
-
var import_node_child_process14,
|
|
12104
|
+
var import_node_child_process14, import_node_crypto14, import_node_fs23, import_node_path31, DEFAULT_TLS_CERT_HOSTS, TLS_CERTIFICATE_LOCK_FILE, TLS_CERTIFICATE_LOCK_WAIT_MS, TLS_CERTIFICATE_WRITE_ATTEMPTS;
|
|
11955
12105
|
var init_tls = __esm({
|
|
11956
12106
|
"src/core/tls.ts"() {
|
|
11957
12107
|
"use strict";
|
|
11958
12108
|
import_node_child_process14 = require("child_process");
|
|
11959
|
-
|
|
12109
|
+
import_node_crypto14 = require("crypto");
|
|
11960
12110
|
import_node_fs23 = __toESM(require("fs"));
|
|
11961
12111
|
import_node_path31 = __toESM(require("path"));
|
|
11962
12112
|
init_docker();
|
|
@@ -12455,6 +12605,41 @@ function stopInitialManagedDevsyWorkspace(repoPath, devsyId) {
|
|
|
12455
12605
|
throw new Error("Initial managed stop left a workload running.");
|
|
12456
12606
|
return true;
|
|
12457
12607
|
}
|
|
12608
|
+
function restoreRecordedManagedDevcontainerConfig(repoPath) {
|
|
12609
|
+
const plan = recordedManagedDevcontainerRestorePlan(repoPath);
|
|
12610
|
+
if (!plan) return false;
|
|
12611
|
+
writeManagedDevcontainerConfig(plan);
|
|
12612
|
+
if (inspectManagedDevcontainerGeneratedConfig(plan).status !== "valid") {
|
|
12613
|
+
throw new Error(
|
|
12614
|
+
`Managed Dev Container path '${plan.generatedPath}' could not be restored from the recorded state.`
|
|
12615
|
+
);
|
|
12616
|
+
}
|
|
12617
|
+
return true;
|
|
12618
|
+
}
|
|
12619
|
+
function recordedManagedDevcontainerRestorePlan(repoPath) {
|
|
12620
|
+
try {
|
|
12621
|
+
if (!import_node_fs25.default.existsSync(import_node_path33.default.join(repoPath, ".devrouter.yml"))) return void 0;
|
|
12622
|
+
const linked = isLinkedWorktree(repoPath);
|
|
12623
|
+
const workspace = linked ? resolveWorktreeWorkspace(repoPath) : void 0;
|
|
12624
|
+
const state = readManagedRuntimeState(repoPath, workspace);
|
|
12625
|
+
if (!state) return void 0;
|
|
12626
|
+
const runtime = loadRuntimeConfig(repoPath, workspace ?? "", state.profile);
|
|
12627
|
+
if (!runtime.config.managedRuntime || runtime.profile !== state.profile || runtime.workspace !== workspace)
|
|
12628
|
+
return void 0;
|
|
12629
|
+
const plan = inspectManagedDevcontainerConfig({
|
|
12630
|
+
repoPath,
|
|
12631
|
+
config: runtime.config,
|
|
12632
|
+
profile: runtime.resolvedProfile,
|
|
12633
|
+
linked
|
|
12634
|
+
});
|
|
12635
|
+
if (inspectManagedDevcontainerGeneratedConfig(plan).status !== "missing") return void 0;
|
|
12636
|
+
if (plan.sourceConfigSha256 !== state.sourceConfigSha256 || plan.effectiveConfigSha256 !== state.effectiveConfigSha256)
|
|
12637
|
+
return void 0;
|
|
12638
|
+
return plan;
|
|
12639
|
+
} catch {
|
|
12640
|
+
return void 0;
|
|
12641
|
+
}
|
|
12642
|
+
}
|
|
12458
12643
|
function stopRetainedManagedDevsyWorkspace(options) {
|
|
12459
12644
|
const { repoPath, devsyId } = options;
|
|
12460
12645
|
const linked = isLinkedWorktree(repoPath);
|
|
@@ -13515,7 +13700,7 @@ function validateRoot(root) {
|
|
|
13515
13700
|
return resolved;
|
|
13516
13701
|
}
|
|
13517
13702
|
function hashKey(value) {
|
|
13518
|
-
return (0,
|
|
13703
|
+
return (0, import_node_crypto15.createHash)("sha256").update(value).digest("hex");
|
|
13519
13704
|
}
|
|
13520
13705
|
function cloneFence(fence) {
|
|
13521
13706
|
return { ...fence };
|
|
@@ -13538,11 +13723,11 @@ function isErrno2(error, code) {
|
|
|
13538
13723
|
function claimError(code, message) {
|
|
13539
13724
|
return new NetworkClaimError(code, message);
|
|
13540
13725
|
}
|
|
13541
|
-
var
|
|
13726
|
+
var import_node_crypto15, import_node_fs27, import_node_path35, NETWORK_CLAIMS_VERSION, NETWORK_CLAIMS_ROOT, NETWORK_CLAIMS_MAX_RECORDS, NETWORK_CLAIMS_MAX_FILE_BYTES, NetworkClaimError, CLAIM_CORE_KEYS, CLAIM_KEYS, FENCE_KEYS, DOCUMENT_KEYS, MAX_CLAIM_TEXT, MAX_ENDPOINT_TEXT;
|
|
13542
13727
|
var init_network_claims = __esm({
|
|
13543
13728
|
"src/core/network-claims.ts"() {
|
|
13544
13729
|
"use strict";
|
|
13545
|
-
|
|
13730
|
+
import_node_crypto15 = require("crypto");
|
|
13546
13731
|
import_node_fs27 = __toESM(require("fs"));
|
|
13547
13732
|
import_node_path35 = __toESM(require("path"));
|
|
13548
13733
|
init_atomic_file();
|
|
@@ -13595,7 +13780,7 @@ var init_network_claims = __esm({
|
|
|
13595
13780
|
function networkOwnerKey(repoPath) {
|
|
13596
13781
|
if (!import_node_path36.default.isAbsolute(repoPath) || import_node_path36.default.resolve(repoPath) !== repoPath)
|
|
13597
13782
|
throw new Error("Invalid network owner path.");
|
|
13598
|
-
return (0,
|
|
13783
|
+
return (0, import_node_crypto16.createHash)("sha256").update(repoPath).digest("hex");
|
|
13599
13784
|
}
|
|
13600
13785
|
function findOwnedNetworkClaim(repoPath, root = NETWORK_CLAIMS_ROOT) {
|
|
13601
13786
|
let names;
|
|
@@ -13635,7 +13820,7 @@ function findOwnedNetworkClaim(repoPath, root = NETWORK_CLAIMS_ROOT) {
|
|
|
13635
13820
|
} finally {
|
|
13636
13821
|
import_node_fs28.default.closeSync(descriptor);
|
|
13637
13822
|
}
|
|
13638
|
-
if (typeof value.daemonId !== "string" || `${(0,
|
|
13823
|
+
if (typeof value.daemonId !== "string" || `${(0, import_node_crypto16.createHash)("sha256").update(value.daemonId).digest("hex")}.json` !== file)
|
|
13639
13824
|
throw new Error("Retained network daemon identity is invalid.");
|
|
13640
13825
|
const claim2 = readNetworkClaim({
|
|
13641
13826
|
daemonId: value.daemonId,
|
|
@@ -13649,11 +13834,11 @@ function findOwnedNetworkClaim(repoPath, root = NETWORK_CLAIMS_ROOT) {
|
|
|
13649
13834
|
}
|
|
13650
13835
|
return found;
|
|
13651
13836
|
}
|
|
13652
|
-
var
|
|
13837
|
+
var import_node_crypto16, import_node_fs28, import_node_path36;
|
|
13653
13838
|
var init_network_claim_lookup = __esm({
|
|
13654
13839
|
"src/core/network-claim-lookup.ts"() {
|
|
13655
13840
|
"use strict";
|
|
13656
|
-
|
|
13841
|
+
import_node_crypto16 = require("crypto");
|
|
13657
13842
|
import_node_fs28 = __toESM(require("fs"));
|
|
13658
13843
|
import_node_path36 = __toESM(require("path"));
|
|
13659
13844
|
init_network_claims();
|
|
@@ -13680,7 +13865,7 @@ function qualifyNetworkProviderDefinition(value, provider) {
|
|
|
13680
13865
|
if (definition.name !== "docker" || ![true, "true"].includes(agent.local) || agent.driver !== void 0 && agent.driver !== "docker" && agent.driver !== "" || docker.path !== "${DOCKER_PATH}" || docker.builder !== "${DOCKER_BUILDER}" || ![false, "false"].includes(docker.install) || (provider === "devsy" ? docker.elevation !== "${DOCKER_ELEVATION}" : docker.elevation !== void 0 && docker.elevation !== "") || env.DOCKER_HOST !== "${DOCKER_HOST}" || Object.keys(env).some((key) => key !== "DOCKER_HOST") || host.global !== true || dockerPath.default !== "docker" || actualCommand.length !== 1 || typeof actualCommand[0] !== "string" || actualCommand[0].trim() !== command || Object.keys(exec).some((key) => key !== "command") || agent.path !== void 0 && agent.path !== "" || agent.downloadURL !== void 0 && agent.downloadURL !== "") {
|
|
13681
13866
|
throw new Error("Docker provider definition is not qualified for network allocation.");
|
|
13682
13867
|
}
|
|
13683
|
-
return (0,
|
|
13868
|
+
return (0, import_node_crypto17.createHash)("sha256").update(JSON.stringify({ name: definition.name, agent, options, exec })).digest("hex");
|
|
13684
13869
|
}
|
|
13685
13870
|
function read(provider, args) {
|
|
13686
13871
|
const result = (0, import_node_child_process16.spawnSync)(provider, args, {
|
|
@@ -13772,12 +13957,12 @@ function inspectNetworkProviderBinding(input2) {
|
|
|
13772
13957
|
);
|
|
13773
13958
|
}
|
|
13774
13959
|
}
|
|
13775
|
-
var import_node_child_process16,
|
|
13960
|
+
var import_node_child_process16, import_node_crypto17;
|
|
13776
13961
|
var init_network_provider_inspect = __esm({
|
|
13777
13962
|
"src/core/network-provider-inspect.ts"() {
|
|
13778
13963
|
"use strict";
|
|
13779
13964
|
import_node_child_process16 = require("child_process");
|
|
13780
|
-
|
|
13965
|
+
import_node_crypto17 = require("crypto");
|
|
13781
13966
|
init_devpod_environment();
|
|
13782
13967
|
init_devsy_agent();
|
|
13783
13968
|
}
|
|
@@ -13853,6 +14038,7 @@ function inspectExactOwnership(devsyId, worktreePath) {
|
|
|
13853
14038
|
}
|
|
13854
14039
|
function mutateOwnedDevsyWorkspace(action2, devsyId, worktreePath) {
|
|
13855
14040
|
return withMutationLock(`Devsy ${action2}`, worktreePath, () => {
|
|
14041
|
+
restoreRecordedManagedDevcontainerConfig(worktreePath);
|
|
13856
14042
|
if (action2 === "stop") {
|
|
13857
14043
|
const stopped = stopRetainedManagedDevsyWorkspace({
|
|
13858
14044
|
repoPath: worktreePath,
|
|
@@ -14261,7 +14447,7 @@ function handleOperationRequest(state, event) {
|
|
|
14261
14447
|
if (state.phase === "stopping" || state.desired === "parked-for-capacity")
|
|
14262
14448
|
return blocked(
|
|
14263
14449
|
state,
|
|
14264
|
-
`phase is '${state.phase}' with desired '${state.desired}'; wait for the running stop to finish.`
|
|
14450
|
+
`phase is '${state.phase}' with desired '${state.desired}'; wait for the running stop to finish, or when no stop worker is running rerun 'devrouter stop <path> --delete', removing the exact provider registration first when the stop cannot prove the recorded population.`
|
|
14265
14451
|
);
|
|
14266
14452
|
if (event.kind === "exec" && (!event.runtimeRunning || state.desired !== "running" && state.intentRevision !== 0))
|
|
14267
14453
|
return blocked(
|
|
@@ -15095,14 +15281,14 @@ async function runLifecycleWorker(request2, supervision, beforeAdmission) {
|
|
|
15095
15281
|
}
|
|
15096
15282
|
}
|
|
15097
15283
|
function newLifecycleIds() {
|
|
15098
|
-
return { requestId: (0,
|
|
15284
|
+
return { requestId: (0, import_node_crypto18.randomUUID)(), operationId: (0, import_node_crypto18.randomUUID)(), workerId: (0, import_node_crypto18.randomUUID)() };
|
|
15099
15285
|
}
|
|
15100
|
-
var import_node_child_process18,
|
|
15286
|
+
var import_node_child_process18, import_node_crypto18, import_node_fs30, import_node_path38, OUTPUT_BUFFER_LIMIT, DEFAULT_OUTPUT_PAGE_BYTES, LifecycleOutput, LifecycleWorkerAdmissionBusyError;
|
|
15101
15287
|
var init_reliability_worker = __esm({
|
|
15102
15288
|
"src/core/reliability-worker.ts"() {
|
|
15103
15289
|
"use strict";
|
|
15104
15290
|
import_node_child_process18 = require("child_process");
|
|
15105
|
-
|
|
15291
|
+
import_node_crypto18 = require("crypto");
|
|
15106
15292
|
import_node_fs30 = __toESM(require("fs"));
|
|
15107
15293
|
import_node_path38 = __toESM(require("path"));
|
|
15108
15294
|
init_file_lock();
|
|
@@ -15790,7 +15976,7 @@ function readRegularFile(filePath) {
|
|
|
15790
15976
|
return readRegularFileBytes(filePath)?.toString("utf-8");
|
|
15791
15977
|
}
|
|
15792
15978
|
function adapterFingerprint(adapter) {
|
|
15793
|
-
return (0,
|
|
15979
|
+
return (0, import_node_crypto19.createHash)("sha256").update(adapter).digest("hex");
|
|
15794
15980
|
}
|
|
15795
15981
|
function resolveManagedPostStartPlan(repoPath) {
|
|
15796
15982
|
const adapterPath = import_node_path41.default.join(repoPath, MANAGED_ADAPTER_PATH);
|
|
@@ -15880,12 +16066,12 @@ function runManagedProcessAction(options) {
|
|
|
15880
16066
|
}
|
|
15881
16067
|
return "drifted";
|
|
15882
16068
|
}
|
|
15883
|
-
var import_node_child_process23,
|
|
16069
|
+
var import_node_child_process23, import_node_crypto19, import_node_fs33, import_node_path41, MANAGED_MARKER, MANAGED_ADAPTER_PATH, RUNTIME_HELPER_PATH;
|
|
15884
16070
|
var init_managed_post_start = __esm({
|
|
15885
16071
|
"src/core/managed-post-start.ts"() {
|
|
15886
16072
|
"use strict";
|
|
15887
16073
|
import_node_child_process23 = require("child_process");
|
|
15888
|
-
|
|
16074
|
+
import_node_crypto19 = require("crypto");
|
|
15889
16075
|
import_node_fs33 = __toESM(require("fs"));
|
|
15890
16076
|
import_node_path41 = __toESM(require("path"));
|
|
15891
16077
|
init_devcontainer_config();
|
|
@@ -15896,26 +16082,132 @@ var init_managed_post_start = __esm({
|
|
|
15896
16082
|
}
|
|
15897
16083
|
});
|
|
15898
16084
|
|
|
16085
|
+
// src/core/managed-mount-nesting.ts
|
|
16086
|
+
function normalizeDestination(value) {
|
|
16087
|
+
const trimmed = value.trim().replace(/\/+$/, "");
|
|
16088
|
+
return trimmed === "" ? "/" : trimmed;
|
|
16089
|
+
}
|
|
16090
|
+
function isNestedWithin(destination, candidate) {
|
|
16091
|
+
return candidate === "/" ? destination !== "/" : destination.startsWith(`${candidate}/`);
|
|
16092
|
+
}
|
|
16093
|
+
function unescapeMountField(value) {
|
|
16094
|
+
return value.replace(
|
|
16095
|
+
/\\([0-7]{3})/g,
|
|
16096
|
+
(_match, octal) => String.fromCharCode(Number.parseInt(octal, 8))
|
|
16097
|
+
);
|
|
16098
|
+
}
|
|
16099
|
+
function parseMountinfoDestinations(text4) {
|
|
16100
|
+
const destinations = /* @__PURE__ */ new Set();
|
|
16101
|
+
for (const line of text4.split("\n")) {
|
|
16102
|
+
const fields2 = line.split(" ");
|
|
16103
|
+
if (fields2.length < 5 || !/^\d+$/.test(fields2[0] ?? "")) continue;
|
|
16104
|
+
destinations.add(normalizeDestination(unescapeMountField(fields2[4] ?? "")));
|
|
16105
|
+
}
|
|
16106
|
+
return [...destinations];
|
|
16107
|
+
}
|
|
16108
|
+
function isNestedIndex(destinations, index) {
|
|
16109
|
+
return destinations.some(
|
|
16110
|
+
(candidate, other) => other !== index && isNestedWithin(destinations[index] ?? "", candidate)
|
|
16111
|
+
);
|
|
16112
|
+
}
|
|
16113
|
+
function configuredDestinations(configured) {
|
|
16114
|
+
return configured.map((mount) => normalizeDestination(mount.Destination));
|
|
16115
|
+
}
|
|
16116
|
+
function classifyManagedMountNesting(configured, effectiveDestinations, containerId) {
|
|
16117
|
+
const destinations = configuredDestinations(configured);
|
|
16118
|
+
const nested = configured.filter((_mount, index) => isNestedIndex(destinations, index));
|
|
16119
|
+
const identity2 = containerId ? { container: containerId } : {};
|
|
16120
|
+
if (nested.length === 0) {
|
|
16121
|
+
return { status: "not-applicable", checked: [], unwound: [], reason: NESTED_MOUNT_REASON };
|
|
16122
|
+
}
|
|
16123
|
+
if (effectiveDestinations === null) {
|
|
16124
|
+
return {
|
|
16125
|
+
status: "unverified",
|
|
16126
|
+
checked: [],
|
|
16127
|
+
unwound: [],
|
|
16128
|
+
...identity2,
|
|
16129
|
+
reason: UNREADABLE_MOUNT_REASON
|
|
16130
|
+
};
|
|
16131
|
+
}
|
|
16132
|
+
const effective = new Set(effectiveDestinations.map(normalizeDestination));
|
|
16133
|
+
const checked = [];
|
|
16134
|
+
const unwound = [];
|
|
16135
|
+
for (const mount of nested) {
|
|
16136
|
+
const destination = normalizeDestination(mount.Destination);
|
|
16137
|
+
if (effective.has(destination)) {
|
|
16138
|
+
checked.push(mount.Destination);
|
|
16139
|
+
continue;
|
|
16140
|
+
}
|
|
16141
|
+
const nestedWithin = destinations.filter((candidate) => isNestedWithin(destination, candidate)).sort((a, b) => a.length - b.length)[0];
|
|
16142
|
+
unwound.push({
|
|
16143
|
+
destination: mount.Destination,
|
|
16144
|
+
source: mount.Source,
|
|
16145
|
+
nestedWithin: nestedWithin ?? "/"
|
|
16146
|
+
});
|
|
16147
|
+
}
|
|
16148
|
+
return {
|
|
16149
|
+
status: unwound.length > 0 ? "unwound" : "effective",
|
|
16150
|
+
checked,
|
|
16151
|
+
unwound,
|
|
16152
|
+
...identity2
|
|
16153
|
+
};
|
|
16154
|
+
}
|
|
16155
|
+
function readContainerMountinfo(containerId, options) {
|
|
16156
|
+
const result = (0, import_node_child_process24.spawnSync)("docker", ["exec", containerId, "cat", "/proc/self/mountinfo"], {
|
|
16157
|
+
encoding: "utf-8",
|
|
16158
|
+
timeout: options.timeoutMs ?? 5e3,
|
|
16159
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
16160
|
+
...networkDockerOptions()
|
|
16161
|
+
});
|
|
16162
|
+
if (result.status !== 0 || typeof result.stdout !== "string") return null;
|
|
16163
|
+
const destinations = parseMountinfoDestinations(result.stdout);
|
|
16164
|
+
return destinations.length > 0 ? destinations : null;
|
|
16165
|
+
}
|
|
16166
|
+
function observeManagedMountNesting(container, options = {}) {
|
|
16167
|
+
const destinations = configuredDestinations(container.mounts);
|
|
16168
|
+
const effective = destinations.some((_destination, index) => isNestedIndex(destinations, index)) ? readContainerMountinfo(container.id, options) : null;
|
|
16169
|
+
return classifyManagedMountNesting(container.mounts, effective, container.id);
|
|
16170
|
+
}
|
|
16171
|
+
var import_node_child_process24, NESTED_MOUNT_REASON, UNREADABLE_MOUNT_REASON;
|
|
16172
|
+
var init_managed_mount_nesting = __esm({
|
|
16173
|
+
"src/core/managed-mount-nesting.ts"() {
|
|
16174
|
+
"use strict";
|
|
16175
|
+
import_node_child_process24 = require("child_process");
|
|
16176
|
+
init_network_effect_scope();
|
|
16177
|
+
NESTED_MOUNT_REASON = "no configured mount is nested inside another configured mount";
|
|
16178
|
+
UNREADABLE_MOUNT_REASON = "the container's own mount table could not be read";
|
|
16179
|
+
}
|
|
16180
|
+
});
|
|
16181
|
+
|
|
15899
16182
|
// src/core/managed-runtime-status.ts
|
|
16183
|
+
function recoveryPath(repoPath) {
|
|
16184
|
+
if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(repoPath)) return repoPath;
|
|
16185
|
+
return `'${repoPath.replaceAll("'", "'\\''")}'`;
|
|
16186
|
+
}
|
|
15900
16187
|
function reliabilityRecovery(reason, repoPath) {
|
|
16188
|
+
const checkout = recoveryPath(repoPath);
|
|
15901
16189
|
switch (reason) {
|
|
15902
16190
|
case "stop-incomplete":
|
|
15903
16191
|
case "operation-unknown":
|
|
15904
|
-
return [`Run: devrouter stop ${
|
|
16192
|
+
return [`Run: devrouter stop ${checkout}`, `Run: devrouter ensure ${checkout} --repair`];
|
|
15905
16193
|
case "start-refused":
|
|
15906
16194
|
return [
|
|
15907
|
-
`Run: devrouter doctor ${
|
|
15908
|
-
`Stop the holding workspace or change this repository's own published binding, then run: devrouter ensure ${
|
|
16195
|
+
`Run: devrouter doctor --repo ${checkout} to read the refused fixed host-port claim and its holder`,
|
|
16196
|
+
`Stop the holding workspace or change this repository's own published binding, then run: devrouter ensure ${checkout}`
|
|
15909
16197
|
];
|
|
15910
16198
|
case "unadmittable":
|
|
15911
16199
|
return [
|
|
15912
|
-
`Run: devrouter stop ${
|
|
15913
|
-
`Lower the requested capacity in .devrouter.yml, then run: devrouter ensure ${
|
|
16200
|
+
`Run: devrouter stop ${checkout}`,
|
|
16201
|
+
`Lower the requested capacity in .devrouter.yml, then run: devrouter ensure ${checkout}`
|
|
15914
16202
|
];
|
|
15915
16203
|
case "capacity-parked":
|
|
15916
|
-
return [
|
|
16204
|
+
return [
|
|
16205
|
+
"Parked for host capacity: the enrolled foreground controller resumes this checkout after its pressure dwell and live-consumer checks pass.",
|
|
16206
|
+
`Inspect the parked intent with: devrouter status --repo ${checkout} --json`,
|
|
16207
|
+
`'devrouter ensure' refuses while the journal stays parked; release the intent instead with: devrouter stop ${checkout}`
|
|
16208
|
+
];
|
|
15917
16209
|
case "capacity-waiting":
|
|
15918
|
-
return [`Run: devrouter ensure ${
|
|
16210
|
+
return [`Run: devrouter ensure ${checkout} (still queued until capacity frees up)`];
|
|
15919
16211
|
default:
|
|
15920
16212
|
return [];
|
|
15921
16213
|
}
|
|
@@ -16162,6 +16454,7 @@ function inspectManagedRuntime(options) {
|
|
|
16162
16454
|
(mount) => mount.Type === "bind" && sameWorkspacePath(mount.Source, repoPath)
|
|
16163
16455
|
)?.Destination;
|
|
16164
16456
|
const primaryActive = Boolean(primary?.state.Running);
|
|
16457
|
+
const mountNesting = primary && primaryActive ? observeManagedMountNesting(primary) : void 0;
|
|
16165
16458
|
if (generatedConfigMissing && (state || primaryActive || managedServicesActive)) {
|
|
16166
16459
|
drift.push("managed generated Dev Container configuration is missing");
|
|
16167
16460
|
}
|
|
@@ -16228,7 +16521,8 @@ function inspectManagedRuntime(options) {
|
|
|
16228
16521
|
processStatuses,
|
|
16229
16522
|
activeServices: sortedUnique2(activeServices),
|
|
16230
16523
|
activeProcesses: sortedUnique2(activeProcesses),
|
|
16231
|
-
drift
|
|
16524
|
+
drift,
|
|
16525
|
+
...mountNesting ? { mountNesting } : {}
|
|
16232
16526
|
};
|
|
16233
16527
|
}
|
|
16234
16528
|
function collectManagedRuntimeStatus(options) {
|
|
@@ -16376,6 +16670,7 @@ function collectManagedRuntimeStatus(options) {
|
|
|
16376
16670
|
baseServiceStatuses: inspection.baseStatuses,
|
|
16377
16671
|
processStatuses: inspection.processStatuses,
|
|
16378
16672
|
drift: sortedUnique2(drift),
|
|
16673
|
+
...inspection.mountNesting ? { mountNesting: inspection.mountNesting } : {},
|
|
16379
16674
|
...inspection.plan?.sourceConfigSha256 || state?.sourceConfigSha256 ? { sourceConfigSha256: inspection.plan?.sourceConfigSha256 ?? state?.sourceConfigSha256 } : {},
|
|
16380
16675
|
...inspection.plan?.effectiveConfigSha256 || state?.effectiveConfigSha256 ? {
|
|
16381
16676
|
effectiveConfigSha256: inspection.plan?.effectiveConfigSha256 ?? state?.effectiveConfigSha256
|
|
@@ -16390,6 +16685,7 @@ var init_managed_runtime_status = __esm({
|
|
|
16390
16685
|
init_devcontainer_profile();
|
|
16391
16686
|
init_devpod_environment();
|
|
16392
16687
|
init_host_routes();
|
|
16688
|
+
init_managed_mount_nesting();
|
|
16393
16689
|
init_managed_post_start();
|
|
16394
16690
|
init_managed_runtime_state();
|
|
16395
16691
|
init_reliability_operation_store();
|
|
@@ -16409,7 +16705,7 @@ function readDocker(endpoint, args, timeoutMs) {
|
|
|
16409
16705
|
const env = { ...process.env };
|
|
16410
16706
|
delete env.DOCKER_CONTEXT;
|
|
16411
16707
|
delete env.DOCKER_HOST;
|
|
16412
|
-
const result = (0,
|
|
16708
|
+
const result = (0, import_node_child_process25.spawnSync)("docker", ["--host", endpoint, ...args], {
|
|
16413
16709
|
env,
|
|
16414
16710
|
encoding: "utf-8",
|
|
16415
16711
|
timeout: timeoutMs,
|
|
@@ -16440,7 +16736,14 @@ function id4(value) {
|
|
|
16440
16736
|
}
|
|
16441
16737
|
function rows(output2) {
|
|
16442
16738
|
const trimmed = output2.trim();
|
|
16443
|
-
return trimmed ? trimmed.split(/\r?\n/).map((line) =>
|
|
16739
|
+
return trimmed ? trimmed.split(/\r?\n/).map((line) => parseRecord(line)) : [];
|
|
16740
|
+
}
|
|
16741
|
+
function parseRecord(line) {
|
|
16742
|
+
try {
|
|
16743
|
+
return JSON.parse(line);
|
|
16744
|
+
} catch {
|
|
16745
|
+
throw new NetworkInventoryError("Docker network inventory contains a malformed record.");
|
|
16746
|
+
}
|
|
16444
16747
|
}
|
|
16445
16748
|
function ids(output2) {
|
|
16446
16749
|
const values = output2.trim() ? output2.trim().split(/\r?\n/).map(id4) : [];
|
|
@@ -16485,7 +16788,7 @@ function collectDockerNetworkInventory(options = {}, dependencies = {}) {
|
|
|
16485
16788
|
return output2;
|
|
16486
16789
|
};
|
|
16487
16790
|
const info = record4(
|
|
16488
|
-
|
|
16791
|
+
parseRecord(
|
|
16489
16792
|
read2(["info", "--format", '{"id":{{json .ID}},"pools":{{json .DefaultAddressPools}}}'])
|
|
16490
16793
|
)
|
|
16491
16794
|
);
|
|
@@ -16564,18 +16867,18 @@ function collectDockerNetworkInventory(options = {}, dependencies = {}) {
|
|
|
16564
16867
|
}
|
|
16565
16868
|
return result;
|
|
16566
16869
|
}
|
|
16567
|
-
var
|
|
16870
|
+
var import_node_child_process25, NetworkInventoryError, MAX_IDS, MAX_OUTPUT_BYTES, FULL_ID, NETWORK_TEMPLATE, CONTAINER_TEMPLATE;
|
|
16568
16871
|
var init_network_inventory = __esm({
|
|
16569
16872
|
"src/core/network-inventory.ts"() {
|
|
16570
16873
|
"use strict";
|
|
16571
|
-
|
|
16874
|
+
import_node_child_process25 = require("child_process");
|
|
16572
16875
|
init_devpod_environment();
|
|
16573
16876
|
NetworkInventoryError = class extends Error {
|
|
16574
16877
|
};
|
|
16575
16878
|
MAX_IDS = 4096;
|
|
16576
16879
|
MAX_OUTPUT_BYTES = 2 * 1024 * 1024;
|
|
16577
16880
|
FULL_ID = /^[a-f0-9]{64}$/;
|
|
16578
|
-
NETWORK_TEMPLATE = '{"id":{{json .Id}},"name":{{json .Name}},"driver":{{json .Driver}},"ipam":{{json .IPAM.Config}},"activeEndpoints":{{len .Containers}},"project":{{json (index .Labels "com.docker.compose.project")}},"network":{{json (index .Labels "com.docker.compose.network")}}';
|
|
16881
|
+
NETWORK_TEMPLATE = '{"id":{{json .Id}},"name":{{json .Name}},"driver":{{json .Driver}},"ipam":{{json .IPAM.Config}},"activeEndpoints":{{len .Containers}},"project":{{json (index .Labels "com.docker.compose.project")}},"network":{{json (index .Labels "com.docker.compose.network")}}}';
|
|
16579
16882
|
CONTAINER_TEMPLATE = '{"id":{{json .Id}},"networks":{{json .NetworkSettings.Networks}}}';
|
|
16580
16883
|
}
|
|
16581
16884
|
});
|
|
@@ -16962,7 +17265,7 @@ function parseLinuxNetworkRoutes(output2) {
|
|
|
16962
17265
|
function collectNetworkRoutes(options) {
|
|
16963
17266
|
if ((options.platform ?? process.platform) !== "linux" || !hasLocalDockerNetworkNamespace(options.endpoint))
|
|
16964
17267
|
return { status: "unknown", routes: [] };
|
|
16965
|
-
const result = (0,
|
|
17268
|
+
const result = (0, import_node_child_process26.spawnSync)("ip", ["-j", "-4", "route", "show", "table", "all"], {
|
|
16966
17269
|
encoding: "utf8",
|
|
16967
17270
|
timeout: 5e3,
|
|
16968
17271
|
maxBuffer: 1024 * 1024
|
|
@@ -16970,11 +17273,11 @@ function collectNetworkRoutes(options) {
|
|
|
16970
17273
|
if (result.error || result.status !== 0) return { status: "unknown", routes: [] };
|
|
16971
17274
|
return parseLinuxNetworkRoutes(result.stdout);
|
|
16972
17275
|
}
|
|
16973
|
-
var
|
|
17276
|
+
var import_node_child_process26, import_node_net3;
|
|
16974
17277
|
var init_network_routes = __esm({
|
|
16975
17278
|
"src/core/network-routes.ts"() {
|
|
16976
17279
|
"use strict";
|
|
16977
|
-
|
|
17280
|
+
import_node_child_process26 = require("child_process");
|
|
16978
17281
|
import_node_net3 = require("net");
|
|
16979
17282
|
init_network_capacity();
|
|
16980
17283
|
init_network_local_daemon();
|
|
@@ -17019,11 +17322,13 @@ function networkCapacityCheck(report) {
|
|
|
17019
17322
|
(pool) => pool.candidates.some((candidate) => candidate.overlappingNetworkIds.length === 0)
|
|
17020
17323
|
);
|
|
17021
17324
|
const managedDetails = managed ? ` Managed policy: ${managed.policy.status}; /${managed.policy.requestedPrefixLength} capacity: ${managed.configuredPolicyCapacity.status}; claims: ${managed.claims.reserved} reserved, ${managed.claims.attached} attached, ${managed.claims.uncertain} uncertain.` : "";
|
|
17325
|
+
const blockers = report.allocation.blockers.slice(0, 4).map((blocker) => blocker.slice(0, 120));
|
|
17326
|
+
const blockerDetails = blockers.length > 0 ? ` Missing evidence: ${blockers.join("; ")}.` : "";
|
|
17022
17327
|
return {
|
|
17023
17328
|
id: "global.network-capacity",
|
|
17024
17329
|
level: legacyAvailable ? "ok" : "warn",
|
|
17025
17330
|
summary: exhausted ? "Docker default address pools are exhausted for new networks." : legacyAvailable ? "Docker default pools have unoccupied capacity; managed allocation is not configured." : "Network allocation readiness requires complete route and capacity evidence.",
|
|
17026
|
-
details: `${report.pools.length} pool(s); ${retained} network(s) have no active endpoints but retain container references. Allocation readiness: ${report.allocation.status}.${managedDetails}`,
|
|
17331
|
+
details: `${report.pools.length} pool(s); ${retained} network(s) have no active endpoints but retain container references. Allocation readiness: ${report.allocation.status}.${blockerDetails}${managedDetails}`,
|
|
17027
17332
|
suggestion: exhausted ? "Existing network reuse can continue. Review operator-approved route-safe pools or exact ownership-aware recovery. Stop and worktree removal do not release subnets; do not prune automatically." : "Review complete Docker, LAN, VPN and guest route evidence before allocating a new subnet. Unknown evidence does not authorize cleanup."
|
|
17028
17333
|
};
|
|
17029
17334
|
}
|
|
@@ -17041,21 +17346,21 @@ var init_network_diagnostics = __esm({
|
|
|
17041
17346
|
});
|
|
17042
17347
|
|
|
17043
17348
|
// src/core/network-compose.ts
|
|
17044
|
-
var
|
|
17349
|
+
var import_node_crypto20;
|
|
17045
17350
|
var init_network_compose = __esm({
|
|
17046
17351
|
"src/core/network-compose.ts"() {
|
|
17047
17352
|
"use strict";
|
|
17048
|
-
|
|
17353
|
+
import_node_crypto20 = require("crypto");
|
|
17049
17354
|
}
|
|
17050
17355
|
});
|
|
17051
17356
|
|
|
17052
17357
|
// src/core/network-compose-files.ts
|
|
17053
|
-
var
|
|
17358
|
+
var import_node_child_process27, import_node_crypto21, import_node_fs35, import_node_path43, import_yaml4, MAX_BYTES3;
|
|
17054
17359
|
var init_network_compose_files = __esm({
|
|
17055
17360
|
"src/core/network-compose-files.ts"() {
|
|
17056
17361
|
"use strict";
|
|
17057
|
-
|
|
17058
|
-
|
|
17362
|
+
import_node_child_process27 = require("child_process");
|
|
17363
|
+
import_node_crypto21 = require("crypto");
|
|
17059
17364
|
import_node_fs35 = __toESM(require("fs"));
|
|
17060
17365
|
import_node_path43 = __toESM(require("path"));
|
|
17061
17366
|
import_yaml4 = __toESM(require("yaml"));
|
|
@@ -17067,11 +17372,11 @@ var init_network_compose_files = __esm({
|
|
|
17067
17372
|
});
|
|
17068
17373
|
|
|
17069
17374
|
// src/core/network-connected-route.ts
|
|
17070
|
-
var
|
|
17375
|
+
var import_node_child_process28;
|
|
17071
17376
|
var init_network_connected_route = __esm({
|
|
17072
17377
|
"src/core/network-connected-route.ts"() {
|
|
17073
17378
|
"use strict";
|
|
17074
|
-
|
|
17379
|
+
import_node_child_process28 = require("child_process");
|
|
17075
17380
|
init_network_capacity();
|
|
17076
17381
|
}
|
|
17077
17382
|
});
|
|
@@ -17087,11 +17392,11 @@ var init_network_lifecycle = __esm({
|
|
|
17087
17392
|
});
|
|
17088
17393
|
|
|
17089
17394
|
// src/core/network-managed.ts
|
|
17090
|
-
var
|
|
17395
|
+
var import_node_crypto22;
|
|
17091
17396
|
var init_network_managed = __esm({
|
|
17092
17397
|
"src/core/network-managed.ts"() {
|
|
17093
17398
|
"use strict";
|
|
17094
|
-
|
|
17399
|
+
import_node_crypto22 = require("crypto");
|
|
17095
17400
|
init_devpod_environment();
|
|
17096
17401
|
init_network_capacity();
|
|
17097
17402
|
init_network_claim_lookup();
|
|
@@ -17161,11 +17466,11 @@ function resolveLinkedTarget(repoPath) {
|
|
|
17161
17466
|
gitCommonDir: resolveGitCommonDir(repoPath)
|
|
17162
17467
|
};
|
|
17163
17468
|
}
|
|
17164
|
-
var
|
|
17469
|
+
var import_node_child_process29, import_node_fs36, import_node_path44;
|
|
17165
17470
|
var init_workspace_ensure = __esm({
|
|
17166
17471
|
"src/core/workspace-ensure.ts"() {
|
|
17167
17472
|
"use strict";
|
|
17168
|
-
|
|
17473
|
+
import_node_child_process29 = require("child_process");
|
|
17169
17474
|
import_node_fs36 = __toESM(require("fs"));
|
|
17170
17475
|
import_node_path44 = __toESM(require("path"));
|
|
17171
17476
|
init_devcontainer_profile();
|
|
@@ -17445,6 +17750,44 @@ function restoreParkedIntentAfterFailedResume(input2) {
|
|
|
17445
17750
|
record5.state = transition2.state;
|
|
17446
17751
|
});
|
|
17447
17752
|
}
|
|
17753
|
+
function snapshotLifecycleStopIntent(state) {
|
|
17754
|
+
return {
|
|
17755
|
+
intentRevision: state.intentRevision,
|
|
17756
|
+
observationsAfterMs: state.observationsAfterMs,
|
|
17757
|
+
desired: state.desired,
|
|
17758
|
+
phase: state.phase,
|
|
17759
|
+
profile: state.profile,
|
|
17760
|
+
admission: state.admission,
|
|
17761
|
+
stopProof: { ...state.stopProof },
|
|
17762
|
+
requests: state.requests.map((request2) => ({ ...request2 })),
|
|
17763
|
+
observations: state.observations.map((observation) => ({ ...observation })),
|
|
17764
|
+
operation: state.operation ? { ...state.operation } : null
|
|
17765
|
+
};
|
|
17766
|
+
}
|
|
17767
|
+
function withdrawUnstartedLifecycleStop(input2) {
|
|
17768
|
+
return updateReliabilityOperation(input2.identity, (record5) => {
|
|
17769
|
+
const state = record5.state;
|
|
17770
|
+
const intent = input2.intent;
|
|
17771
|
+
if (!intent.wroteIntent) return false;
|
|
17772
|
+
if (!matchesFence(record5, intent.fence)) return false;
|
|
17773
|
+
if (record5.worker || record5.stopWorkStarted) return false;
|
|
17774
|
+
if (state.desired !== "stopped-by-user" || state.phase !== "stopping") return false;
|
|
17775
|
+
if (state.stopProof.workloadsStopped || state.stopProof.routesRemoved) return false;
|
|
17776
|
+
if (!(0, import_node_util11.isDeepStrictEqual)(state.operation, intent.recordedOperation)) return false;
|
|
17777
|
+
const prior = intent.prior;
|
|
17778
|
+
state.intentRevision = prior.intentRevision;
|
|
17779
|
+
state.observationsAfterMs = prior.observationsAfterMs;
|
|
17780
|
+
state.desired = prior.desired;
|
|
17781
|
+
state.phase = prior.phase;
|
|
17782
|
+
state.profile = prior.profile;
|
|
17783
|
+
state.admission = prior.admission;
|
|
17784
|
+
state.stopProof = { ...prior.stopProof };
|
|
17785
|
+
state.requests = prior.requests.map((request2) => ({ ...request2 }));
|
|
17786
|
+
state.observations = prior.observations.map((observation) => ({ ...observation }));
|
|
17787
|
+
state.operation = prior.operation ? { ...prior.operation } : null;
|
|
17788
|
+
return true;
|
|
17789
|
+
});
|
|
17790
|
+
}
|
|
17448
17791
|
function prepareResumeLifecycleOperation(input2) {
|
|
17449
17792
|
const ids2 = newLifecycleIds();
|
|
17450
17793
|
return updateReliabilityOperation(input2.identity, (record5) => {
|
|
@@ -17597,12 +17940,37 @@ async function superviseLifecycle(kind, repoPath, options = {}, command) {
|
|
|
17597
17940
|
const copiedOptions = { ...options };
|
|
17598
17941
|
const copiedCommand = command ? [...command] : void 0;
|
|
17599
17942
|
if (kind === "stop") {
|
|
17600
|
-
const
|
|
17943
|
+
const intent = updateReliabilityOperation(identity2, (record5) => {
|
|
17601
17944
|
reconcileDrained(record5);
|
|
17945
|
+
const prior = snapshotLifecycleStopIntent(record5.state);
|
|
17602
17946
|
stepRecord(record5, { ...reliabilityFence(record5.state), type: "stop" });
|
|
17603
|
-
return
|
|
17947
|
+
return {
|
|
17948
|
+
fence: reliabilityFence(record5.state),
|
|
17949
|
+
prior,
|
|
17950
|
+
recordedOperation: record5.state.operation ? { ...record5.state.operation } : null,
|
|
17951
|
+
wroteIntent: record5.state.intentRevision !== prior.intentRevision
|
|
17952
|
+
};
|
|
17604
17953
|
});
|
|
17605
|
-
|
|
17954
|
+
try {
|
|
17955
|
+
return await runLifecycleWorker({
|
|
17956
|
+
kind,
|
|
17957
|
+
repoPath,
|
|
17958
|
+
identity: identity2,
|
|
17959
|
+
...ids2,
|
|
17960
|
+
fence: intent.fence,
|
|
17961
|
+
options: copiedOptions
|
|
17962
|
+
});
|
|
17963
|
+
} catch (error) {
|
|
17964
|
+
try {
|
|
17965
|
+
withdrawUnstartedLifecycleStop({ identity: identity2, intent });
|
|
17966
|
+
} catch (withdrawal) {
|
|
17967
|
+
process.stderr.write(
|
|
17968
|
+
`Lifecycle stop intent could not be withdrawn: ${withdrawal instanceof Error ? withdrawal.message : String(withdrawal)}
|
|
17969
|
+
`
|
|
17970
|
+
);
|
|
17971
|
+
}
|
|
17972
|
+
throw error;
|
|
17973
|
+
}
|
|
17606
17974
|
}
|
|
17607
17975
|
const initial = readReliabilityOperation(identity2) ?? updateReliabilityOperation(identity2, (record5) => record5);
|
|
17608
17976
|
if (initial.state.executionPolicy === "capacity-managed" || capacityPolicyTargets(repoPath))
|
|
@@ -17847,7 +18215,7 @@ async function superviseThroughController(input2) {
|
|
|
17847
18215
|
try {
|
|
17848
18216
|
const bind = () => observeControllerBinding(directory, {
|
|
17849
18217
|
path: input2.repoPath,
|
|
17850
|
-
session: (0,
|
|
18218
|
+
session: (0, import_node_crypto23.randomUUID)(),
|
|
17851
18219
|
profile: input2.profile ?? "full",
|
|
17852
18220
|
// The protocol requires at least one readiness selector, and every
|
|
17853
18221
|
// supervised operation depends on runtime readiness; "runtime" is the
|
|
@@ -17998,11 +18366,11 @@ function bindLifecycleCapacity(request2, binding, directory = import_node_path45
|
|
|
17998
18366
|
stepRecord(record5, { ...request2.fence, type: "admission", result: "admitted" });
|
|
17999
18367
|
});
|
|
18000
18368
|
}
|
|
18001
|
-
var
|
|
18369
|
+
var import_node_crypto23, import_node_path45, import_node_util11, activeWorker, lockHeld, BUSY_LIFECYCLE_WAIT_MS, BUSY_LIFECYCLE_POLL_MS, CAPACITY_CLIENT_WAIT_MS, BUSY_LIFECYCLE_PROGRESS_MS;
|
|
18002
18370
|
var init_reliability_lifecycle = __esm({
|
|
18003
18371
|
"src/core/reliability-lifecycle.ts"() {
|
|
18004
18372
|
"use strict";
|
|
18005
|
-
|
|
18373
|
+
import_node_crypto23 = require("crypto");
|
|
18006
18374
|
import_node_path45 = __toESM(require("path"));
|
|
18007
18375
|
import_node_util11 = require("util");
|
|
18008
18376
|
init_capacity_accounting();
|
|
@@ -18638,7 +19006,7 @@ function createCapacityController(options) {
|
|
|
18638
19006
|
controller,
|
|
18639
19007
|
policyRevision: policy.revision
|
|
18640
19008
|
});
|
|
18641
|
-
const payloadKey = (0,
|
|
19009
|
+
const payloadKey = (0, import_node_crypto24.randomBytes)(32);
|
|
18642
19010
|
const acceptedPayloads = /* @__PURE__ */ new Map();
|
|
18643
19011
|
const settlePreparations = () => {
|
|
18644
19012
|
if (lifetime.signal.aborted) return;
|
|
@@ -18802,7 +19170,7 @@ function createCapacityController(options) {
|
|
|
18802
19170
|
{
|
|
18803
19171
|
...charge,
|
|
18804
19172
|
operationId: prepared.operationId,
|
|
18805
|
-
reservationId: (0,
|
|
19173
|
+
reservationId: (0, import_node_crypto24.randomUUID)(),
|
|
18806
19174
|
policyRevision: target.current.revision
|
|
18807
19175
|
},
|
|
18808
19176
|
{
|
|
@@ -18905,7 +19273,7 @@ function createCapacityController(options) {
|
|
|
18905
19273
|
throw error;
|
|
18906
19274
|
}
|
|
18907
19275
|
}
|
|
18908
|
-
const signature = (0,
|
|
19276
|
+
const signature = (0, import_node_crypto24.createHmac)("sha256", payloadKey).update(
|
|
18909
19277
|
JSON.stringify({
|
|
18910
19278
|
repoPath: identity2.repoPath,
|
|
18911
19279
|
profile: environment.profile,
|
|
@@ -18925,7 +19293,7 @@ function createCapacityController(options) {
|
|
|
18925
19293
|
{
|
|
18926
19294
|
...charge,
|
|
18927
19295
|
operationId: prepared.operationId,
|
|
18928
|
-
reservationId: (0,
|
|
19296
|
+
reservationId: (0, import_node_crypto24.randomUUID)(),
|
|
18929
19297
|
policyRevision: current.revision
|
|
18930
19298
|
},
|
|
18931
19299
|
{ estimates: resolved.estimates, enrollment: resolved.enrollment, pool }
|
|
@@ -19060,7 +19428,7 @@ function createCapacityController(options) {
|
|
|
19060
19428
|
// the budget module then falls back to the conservative wall duration.
|
|
19061
19429
|
activeElapsedMs: null,
|
|
19062
19430
|
profile: environment.profile,
|
|
19063
|
-
incidentId: `incident-${(0,
|
|
19431
|
+
incidentId: `incident-${(0, import_node_crypto24.randomUUID)()}`
|
|
19064
19432
|
});
|
|
19065
19433
|
} catch {
|
|
19066
19434
|
return;
|
|
@@ -19078,7 +19446,7 @@ function createCapacityController(options) {
|
|
|
19078
19446
|
{
|
|
19079
19447
|
...charge,
|
|
19080
19448
|
operationId: prepared.operationId,
|
|
19081
|
-
reservationId: (0,
|
|
19449
|
+
reservationId: (0, import_node_crypto24.randomUUID)(),
|
|
19082
19450
|
policyRevision: current.revision
|
|
19083
19451
|
},
|
|
19084
19452
|
{ estimates: resolved.estimates, enrollment: resolved.enrollment, pool }
|
|
@@ -19098,11 +19466,11 @@ function createCapacityController(options) {
|
|
|
19098
19466
|
}
|
|
19099
19467
|
};
|
|
19100
19468
|
}
|
|
19101
|
-
var
|
|
19469
|
+
var import_node_crypto24, import_node_path46, import_node_util13;
|
|
19102
19470
|
var init_capacity_controller = __esm({
|
|
19103
19471
|
"src/core/capacity-controller.ts"() {
|
|
19104
19472
|
"use strict";
|
|
19105
|
-
|
|
19473
|
+
import_node_crypto24 = require("crypto");
|
|
19106
19474
|
import_node_path46 = __toESM(require("path"));
|
|
19107
19475
|
import_node_util13 = require("util");
|
|
19108
19476
|
init_capacity_accounting();
|
|
@@ -19199,7 +19567,7 @@ printf '%s %s %s\n' "$pid" "$birth" "$fingerprint"
|
|
|
19199
19567
|
|
|
19200
19568
|
// src/core/controller-observation.ts
|
|
19201
19569
|
function digest2(value) {
|
|
19202
|
-
return (0,
|
|
19570
|
+
return (0, import_node_crypto25.createHash)("sha256").update(JSON.stringify(value)).digest("hex");
|
|
19203
19571
|
}
|
|
19204
19572
|
function readRoutes() {
|
|
19205
19573
|
return readHostRouteStateReadOnly((file) => readControllerEvidence(file, 1048576));
|
|
@@ -19283,7 +19651,7 @@ function createControllerObservationCollector(resolve, fingerprint) {
|
|
|
19283
19651
|
() => persisted.contents[3]
|
|
19284
19652
|
);
|
|
19285
19653
|
const source = parseDevcontainerConfig(persisted.contents[4], sourcePath);
|
|
19286
|
-
if (!state || state.devpodId !== environment.providerId || state.profile !== environment.profile || typeof source.service !== "string" || !source.service || (0,
|
|
19654
|
+
if (!state || state.devpodId !== environment.providerId || state.profile !== environment.profile || typeof source.service !== "string" || !source.service || (0, import_node_crypto25.createHash)("sha256").update(persisted.contents[4]).digest("hex") !== state.sourceConfigSha256 || (0, import_node_crypto25.createHash)("sha256").update(persisted.contents[5]).digest("hex") !== state.effectiveConfigSha256)
|
|
19287
19655
|
throw new ControllerObservationBindingChanged("Observation retained configuration changed.");
|
|
19288
19656
|
const identity2 = {
|
|
19289
19657
|
repoPath: environment.repoPath,
|
|
@@ -19458,11 +19826,11 @@ function createControllerObservationCollector(resolve, fingerprint) {
|
|
|
19458
19826
|
};
|
|
19459
19827
|
};
|
|
19460
19828
|
}
|
|
19461
|
-
var
|
|
19829
|
+
var import_node_crypto25, import_node_path47, OBSERVATION_INSPECT_TEMPLATE;
|
|
19462
19830
|
var init_controller_observation = __esm({
|
|
19463
19831
|
"src/core/controller-observation.ts"() {
|
|
19464
19832
|
"use strict";
|
|
19465
|
-
|
|
19833
|
+
import_node_crypto25 = require("crypto");
|
|
19466
19834
|
import_node_path47 = __toESM(require("path"));
|
|
19467
19835
|
init_controller_binding();
|
|
19468
19836
|
init_controller_monitor();
|
|
@@ -19487,11 +19855,11 @@ var init_controller_observation = __esm({
|
|
|
19487
19855
|
});
|
|
19488
19856
|
|
|
19489
19857
|
// src/core/controller-sessions.ts
|
|
19490
|
-
var
|
|
19858
|
+
var import_node_crypto26, import_node_util14, ControllerSessions;
|
|
19491
19859
|
var init_controller_sessions = __esm({
|
|
19492
19860
|
"src/core/controller-sessions.ts"() {
|
|
19493
19861
|
"use strict";
|
|
19494
|
-
|
|
19862
|
+
import_node_crypto26 = require("crypto");
|
|
19495
19863
|
import_node_util14 = require("util");
|
|
19496
19864
|
ControllerSessions = class {
|
|
19497
19865
|
constructor(store) {
|
|
@@ -19663,7 +20031,7 @@ var init_controller_sessions = __esm({
|
|
|
19663
20031
|
const session = {
|
|
19664
20032
|
id: id5,
|
|
19665
20033
|
environmentId: environment.id,
|
|
19666
|
-
generation: (0,
|
|
20034
|
+
generation: (0, import_node_crypto26.randomUUID)(),
|
|
19667
20035
|
requirements: required,
|
|
19668
20036
|
renewedAtMs: wall,
|
|
19669
20037
|
parkingConsent: "protected",
|
|
@@ -19690,7 +20058,7 @@ var init_controller_sessions = __esm({
|
|
|
19690
20058
|
const session = {
|
|
19691
20059
|
id: previous.session,
|
|
19692
20060
|
environmentId: environment.id,
|
|
19693
|
-
generation: (0,
|
|
20061
|
+
generation: (0, import_node_crypto26.randomUUID)(),
|
|
19694
20062
|
requirements: required,
|
|
19695
20063
|
renewedAtMs: wall,
|
|
19696
20064
|
parkingConsent: "protected",
|
|
@@ -21134,26 +21502,30 @@ checkout's environment is mid-transition. Wire \`devrouter harness gate\` as a
|
|
|
21134
21502
|
{
|
|
21135
21503
|
"hooks": {
|
|
21136
21504
|
"PreToolUse": [
|
|
21137
|
-
{ "matcher": "
|
|
21505
|
+
{ "matcher": ".*", "hooks": [
|
|
21138
21506
|
{ "type": "command", "command": "devrouter harness gate", "timeout": 90 }
|
|
21139
21507
|
] }
|
|
21140
21508
|
]
|
|
21141
21509
|
}
|
|
21142
21510
|
}
|
|
21143
21511
|
|
|
21144
|
-
The Codex CLI reads the same hook from \`$CODEX_HOME/hooks.json
|
|
21145
|
-
tool is named \`exec_command\`:
|
|
21512
|
+
The Codex CLI reads the same hook from \`$CODEX_HOME/hooks.json\`:
|
|
21146
21513
|
|
|
21147
21514
|
{
|
|
21148
21515
|
"hooks": {
|
|
21149
21516
|
"PreToolUse": [
|
|
21150
|
-
{ "matcher": "
|
|
21517
|
+
{ "matcher": ".*", "hooks": [
|
|
21151
21518
|
{ "type": "command", "command": "devrouter harness gate", "timeout": 180 }
|
|
21152
21519
|
] }
|
|
21153
21520
|
]
|
|
21154
21521
|
}
|
|
21155
21522
|
}
|
|
21156
21523
|
|
|
21524
|
+
\`.*\` matches every tool, including the shell, file-editing and MCP tools a model
|
|
21525
|
+
can point at the environment. The gate answers a settled checkout immediately, so
|
|
21526
|
+
the price is one short-lived process per gated call; narrow the matcher when that
|
|
21527
|
+
price matters more than covering every tool.
|
|
21528
|
+
|
|
21157
21529
|
The gate identifies the requesting harness from its payload and answers in that
|
|
21158
21530
|
harness's accepted shape: a refusal is a \`deny\` in both, while an allowed call is
|
|
21159
21531
|
\`permissionDecision: allow\` for Claude Code and Codex receives a bare completion
|
|
@@ -21849,6 +22221,13 @@ function appendManagedRuntimeRows(rows2, managedRuntime) {
|
|
|
21849
22221
|
rows2.push(["Effective config SHA-256", managedRuntime.effectiveConfigSha256 ?? "-"]);
|
|
21850
22222
|
rows2.push(["Transition phase", managedRuntime.transitionPhase ?? "-"]);
|
|
21851
22223
|
rows2.push(["Runtime drift", formatResourceNames(managedRuntime.drift)]);
|
|
22224
|
+
if (managedRuntime.mountNesting && managedRuntime.mountNesting.status !== "not-applicable") {
|
|
22225
|
+
const nesting = managedRuntime.mountNesting;
|
|
22226
|
+
rows2.push([
|
|
22227
|
+
"Mount nesting",
|
|
22228
|
+
nesting.status === "unwound" ? `unwound: ${nesting.unwound.map((entry) => entry.destination).join(", ")} (restart the container to re-apply)` : nesting.status === "unverified" ? `unverified (${nesting.reason ?? "unknown"})` : `effective (${nesting.checked.join(", ")})`
|
|
22229
|
+
]);
|
|
22230
|
+
}
|
|
21852
22231
|
if (managedRuntime.reliability) {
|
|
21853
22232
|
const reliability = managedRuntime.reliability;
|
|
21854
22233
|
rows2.push(["Lifecycle intent", reliability.desired]);
|
|
@@ -22960,6 +23339,11 @@ async function collectRouterStatus(repoPath) {
|
|
|
22960
23339
|
nextSteps.push(`Run: dev app ls --repo ${repo.path}`);
|
|
22961
23340
|
nextSteps.push("Run: dev app run <name> --repo <path> --yes");
|
|
22962
23341
|
nextSteps.push("Run: dev ls");
|
|
23342
|
+
if (repo.managedRuntime?.mountNesting?.status === "unwound") {
|
|
23343
|
+
nextSteps.push(
|
|
23344
|
+
`Run: devrouter stop ${repo.path} and then devrouter ensure ${repo.path} to re-apply the unwound nested mount`
|
|
23345
|
+
);
|
|
23346
|
+
}
|
|
22963
23347
|
}
|
|
22964
23348
|
const files = getRouterFileLayout();
|
|
22965
23349
|
if (files.missing.length > 0) {
|
|
@@ -23003,7 +23387,7 @@ function outputFromResult(result) {
|
|
|
23003
23387
|
return output2.length > 0 ? output2 : void 0;
|
|
23004
23388
|
}
|
|
23005
23389
|
function runTool(command, args = []) {
|
|
23006
|
-
const result = (0,
|
|
23390
|
+
const result = (0, import_node_child_process30.spawnSync)(command, args, {
|
|
23007
23391
|
encoding: "utf-8"
|
|
23008
23392
|
});
|
|
23009
23393
|
if (result.error) {
|
|
@@ -23194,7 +23578,7 @@ function displayPath(filePath) {
|
|
|
23194
23578
|
return `~${filePath.slice(home.length)}`;
|
|
23195
23579
|
}
|
|
23196
23580
|
function probeInstalledCliVersion(executable) {
|
|
23197
|
-
const result = (0,
|
|
23581
|
+
const result = (0, import_node_child_process30.spawnSync)(executable, ["-V"], {
|
|
23198
23582
|
encoding: "utf-8",
|
|
23199
23583
|
timeout: CLI_PATH_PROBE_TIMEOUT_MS
|
|
23200
23584
|
});
|
|
@@ -23205,7 +23589,7 @@ function probeInstalledCliVersion(executable) {
|
|
|
23205
23589
|
}
|
|
23206
23590
|
function buildCliPathCheck(options = {}) {
|
|
23207
23591
|
const id5 = "global.cli-path";
|
|
23208
|
-
const runningVersion = options.runningVersion ?? (true ? "0.1.
|
|
23592
|
+
const runningVersion = options.runningVersion ?? (true ? "0.1.3" : "0.0.0-dev");
|
|
23209
23593
|
if (runningVersion === "0.0.0-dev") {
|
|
23210
23594
|
return {
|
|
23211
23595
|
id: id5,
|
|
@@ -23380,11 +23764,11 @@ function buildGlobalToolChecksWithoutTelemetry(repoPath) {
|
|
|
23380
23764
|
checks.push(nodeToolchainCheck(repoPath));
|
|
23381
23765
|
return checks;
|
|
23382
23766
|
}
|
|
23383
|
-
var
|
|
23767
|
+
var import_node_child_process30, import_node_fs43, import_node_path54, DEVSY_DISABLE_TELEMETRY, CLI_PATH_PROBE_TIMEOUT_MS, INSTALLED_CLI_VERSION_RE;
|
|
23384
23768
|
var init_tool_diagnostics = __esm({
|
|
23385
23769
|
"src/core/tool-diagnostics.ts"() {
|
|
23386
23770
|
"use strict";
|
|
23387
|
-
|
|
23771
|
+
import_node_child_process30 = require("child_process");
|
|
23388
23772
|
import_node_fs43 = __toESM(require("fs"));
|
|
23389
23773
|
import_node_path54 = __toESM(require("path"));
|
|
23390
23774
|
init_devsy_agent();
|
|
@@ -23871,6 +24255,17 @@ function collectNextSteps(checks, statusNextSteps) {
|
|
|
23871
24255
|
}
|
|
23872
24256
|
return Array.from(steps.values());
|
|
23873
24257
|
}
|
|
24258
|
+
function capacityHistoryDetails(error) {
|
|
24259
|
+
if (!(error instanceof CapacityHistoryError)) return "capacity-history-unprovable";
|
|
24260
|
+
const parts = [error.code];
|
|
24261
|
+
if (error.cause) parts.push(error.cause);
|
|
24262
|
+
if (error.location) parts.push(`at ${error.location}`);
|
|
24263
|
+
return parts.join("; ");
|
|
24264
|
+
}
|
|
24265
|
+
function capacityHistorySuggestion(error) {
|
|
24266
|
+
const cause = error instanceof CapacityHistoryError ? error.cause : null;
|
|
24267
|
+
return (cause ? CAPACITY_RECOVERY_BY_CAUSE[cause] : void 0) ?? "Preserve ledger and lifecycle records; restore verified history before retrying admission.";
|
|
24268
|
+
}
|
|
23874
24269
|
async function buildDoctorReport(options = {}) {
|
|
23875
24270
|
const checks = [];
|
|
23876
24271
|
const fileLayout = getRouterFileLayout();
|
|
@@ -23916,8 +24311,8 @@ async function buildDoctorReport(options = {}) {
|
|
|
23916
24311
|
id: "global.capacity-ledger",
|
|
23917
24312
|
level: "error",
|
|
23918
24313
|
summary: "Capacity ledger history is unavailable for safe admission.",
|
|
23919
|
-
details: error
|
|
23920
|
-
suggestion: absent ? "Preserve ledger and lifecycle records; with every enrolled environment stopped, run: devrouter capacity reconcile --yes" :
|
|
24314
|
+
details: capacityHistoryDetails(error),
|
|
24315
|
+
suggestion: absent ? "Preserve ledger and lifecycle records; with every enrolled environment stopped, run: devrouter capacity reconcile --yes" : capacityHistorySuggestion(error)
|
|
23921
24316
|
});
|
|
23922
24317
|
}
|
|
23923
24318
|
let statusNextSteps = [];
|
|
@@ -24029,6 +24424,43 @@ async function buildDoctorReport(options = {}) {
|
|
|
24029
24424
|
...details ? { details } : {},
|
|
24030
24425
|
suggestion: managedRuntime.mode === "legacy" ? void 0 : managedRuntime.status === "failed-transition" ? `Inspect: dev status --repo ${repo.path}; resolve the reported drift before retrying ensure.` : managedRuntime.status === "ready" ? void 0 : `Run: dev ensure ${repo.path}`
|
|
24031
24426
|
});
|
|
24427
|
+
const mountNesting = managedRuntime.mountNesting;
|
|
24428
|
+
if (mountNesting && mountNesting.status !== "not-applicable") {
|
|
24429
|
+
const container = mountNesting.container ?? "unknown";
|
|
24430
|
+
const shortContainer = container === "unknown" ? container : container.slice(0, 12);
|
|
24431
|
+
if (mountNesting.status === "unwound") {
|
|
24432
|
+
const first = mountNesting.unwound[0];
|
|
24433
|
+
addCheck(checks, {
|
|
24434
|
+
id: "repo.managed-mount-nesting",
|
|
24435
|
+
level: "warn",
|
|
24436
|
+
summary: `Managed container ${shortContainer} no longer reports ${first?.destination ?? "a nested mount"} in its own mount table, so the mount underneath it is visible in the container.`,
|
|
24437
|
+
details: [
|
|
24438
|
+
`container=${container}`,
|
|
24439
|
+
...mountNesting.unwound.map(
|
|
24440
|
+
(entry) => `unwound=${entry.destination} (source ${entry.source} inside ${entry.nestedWithin})`
|
|
24441
|
+
)
|
|
24442
|
+
].join("; "),
|
|
24443
|
+
suggestion: `Run: devrouter stop ${repo.path} and then devrouter ensure ${repo.path} to restart the exact container, which re-applies the nested mount.`
|
|
24444
|
+
});
|
|
24445
|
+
} else if (mountNesting.status === "unverified") {
|
|
24446
|
+
addCheck(checks, {
|
|
24447
|
+
id: "repo.managed-mount-nesting",
|
|
24448
|
+
level: "warn",
|
|
24449
|
+
summary: `Managed container ${shortContainer} did not report its own mount table, so its nested mounts are unverified.`,
|
|
24450
|
+
details: [
|
|
24451
|
+
`container=${container}`,
|
|
24452
|
+
`reason=${mountNesting.reason ?? "unknown"}`
|
|
24453
|
+
].join("; "),
|
|
24454
|
+
suggestion: `Run: devrouter exec ${repo.path} -- cat /proc/self/mountinfo to read the container's own mount table.`
|
|
24455
|
+
});
|
|
24456
|
+
} else {
|
|
24457
|
+
addCheck(checks, {
|
|
24458
|
+
id: "repo.managed-mount-nesting",
|
|
24459
|
+
level: "ok",
|
|
24460
|
+
summary: `Managed container ${shortContainer} still reports ${mountNesting.checked.join(", ")} in its own mount table.`
|
|
24461
|
+
});
|
|
24462
|
+
}
|
|
24463
|
+
}
|
|
24032
24464
|
}
|
|
24033
24465
|
if (repo.appCount === 0) {
|
|
24034
24466
|
addCheck(checks, {
|
|
@@ -24053,7 +24485,7 @@ async function buildDoctorReport(options = {}) {
|
|
|
24053
24485
|
suggestion: `Remedy ${expansionNotice.remedy.code}: set a named default profile other than '${expansionNotice.profile}'${remedyCandidates}.`
|
|
24054
24486
|
});
|
|
24055
24487
|
}
|
|
24056
|
-
const cliVersion = true ? "0.1.
|
|
24488
|
+
const cliVersion = true ? "0.1.3" : "0.0.0-dev";
|
|
24057
24489
|
const configVersion = config.devrouter?.version;
|
|
24058
24490
|
const installedKnown = cliVersion !== "0.0.0-dev";
|
|
24059
24491
|
const versionComparison = installedKnown && configVersion ? compareSemver(configVersion, cliVersion) : void 0;
|
|
@@ -24279,7 +24711,7 @@ async function buildDoctorReport(options = {}) {
|
|
|
24279
24711
|
nextSteps
|
|
24280
24712
|
};
|
|
24281
24713
|
}
|
|
24282
|
-
var import_node_fs44, import_node_path56, import_yaml6, POSTGRES_DEFAULTS;
|
|
24714
|
+
var import_node_fs44, import_node_path56, import_yaml6, POSTGRES_DEFAULTS, CAPACITY_RECOVERY_BY_CAUSE;
|
|
24283
24715
|
var init_doctor = __esm({
|
|
24284
24716
|
"src/core/doctor.ts"() {
|
|
24285
24717
|
"use strict";
|
|
@@ -24308,6 +24740,14 @@ var init_doctor = __esm({
|
|
|
24308
24740
|
POSTGRES_PASSWORD: "prisma",
|
|
24309
24741
|
POSTGRES_DB: "prisma"
|
|
24310
24742
|
};
|
|
24743
|
+
CAPACITY_RECOVERY_BY_CAUSE = {
|
|
24744
|
+
"journal-entry-unsupported": "Move the named unrecognised entry out of the private reliability journal directory, preserving its contents; it blocks every capacity read while it stays there.",
|
|
24745
|
+
"journal-directory-unsafe": "Restore private ownership and mode 0700 on the reliability journal directory, then retry.",
|
|
24746
|
+
"journal-directory-unreadable": "Restore read access to the reliability journal directory, then retry.",
|
|
24747
|
+
"journal-invalid": "Preserve the named journal entry and restore verified history before retrying admission.",
|
|
24748
|
+
"journal-unreadable": "Preserve the named journal entry and restore verified history before retrying admission.",
|
|
24749
|
+
"journal-entry-unsafe": "Restore private ownership, mode 0600 and a bounded size on the named journal entry, then retry."
|
|
24750
|
+
};
|
|
24311
24751
|
}
|
|
24312
24752
|
});
|
|
24313
24753
|
|
|
@@ -24609,12 +25049,12 @@ function parseSsPortListeners(stdout, port) {
|
|
|
24609
25049
|
return listeners;
|
|
24610
25050
|
}
|
|
24611
25051
|
function findPortListeners(port) {
|
|
24612
|
-
const result = (0,
|
|
25052
|
+
const result = (0, import_node_child_process31.spawnSync)("lsof", ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN"], {
|
|
24613
25053
|
encoding: "utf-8"
|
|
24614
25054
|
});
|
|
24615
25055
|
if (result.error && result.error.code === "ENOENT") {
|
|
24616
25056
|
if (process.platform === "linux") {
|
|
24617
|
-
const ssResult = (0,
|
|
25057
|
+
const ssResult = (0, import_node_child_process31.spawnSync)("ss", ["-H", "-lntp", "-p"], { encoding: "utf-8" });
|
|
24618
25058
|
if (ssResult.status === 0 && ssResult.stdout) {
|
|
24619
25059
|
return parseSsPortListeners(ssResult.stdout, port);
|
|
24620
25060
|
}
|
|
@@ -24643,11 +25083,11 @@ function findPortListeners(port) {
|
|
|
24643
25083
|
};
|
|
24644
25084
|
});
|
|
24645
25085
|
}
|
|
24646
|
-
var
|
|
25086
|
+
var import_node_child_process31;
|
|
24647
25087
|
var init_ports = __esm({
|
|
24648
25088
|
"src/util/ports.ts"() {
|
|
24649
25089
|
"use strict";
|
|
24650
|
-
|
|
25090
|
+
import_node_child_process31 = require("child_process");
|
|
24651
25091
|
}
|
|
24652
25092
|
});
|
|
24653
25093
|
|
|
@@ -24916,7 +25356,7 @@ var init_status2 = __esm({
|
|
|
24916
25356
|
|
|
24917
25357
|
// src/core/harness-continuation.ts
|
|
24918
25358
|
function harnessContinuationPath(repoRoot) {
|
|
24919
|
-
const key = (0,
|
|
25359
|
+
const key = (0, import_node_crypto27.createHash)("sha256").update(comparableWorkspacePath(repoRoot)).digest("hex");
|
|
24920
25360
|
return import_node_path57.default.join(DEVROUTER_HOME, "harness", `${key}.json`);
|
|
24921
25361
|
}
|
|
24922
25362
|
function counter4(value) {
|
|
@@ -25014,11 +25454,11 @@ function settleHarnessContinuation(repoRoot, toolUseId, settlement) {
|
|
|
25014
25454
|
} catch {
|
|
25015
25455
|
}
|
|
25016
25456
|
}
|
|
25017
|
-
var
|
|
25457
|
+
var import_node_crypto27, import_node_fs45, import_node_path57, HARNESS_CONTINUATION_MAX_ENTRIES, HARNESS_CONTINUATION_TTL_MS, HARNESS_CONTINUATION_LOCK_WAIT_MS, MAX_LEDGER_BYTES, MAX_TOOL_USE_ID_LENGTH, MAX_PHASE_LENGTH;
|
|
25018
25458
|
var init_harness_continuation = __esm({
|
|
25019
25459
|
"src/core/harness-continuation.ts"() {
|
|
25020
25460
|
"use strict";
|
|
25021
|
-
|
|
25461
|
+
import_node_crypto27 = require("crypto");
|
|
25022
25462
|
import_node_fs45 = __toESM(require("fs"));
|
|
25023
25463
|
import_node_path57 = __toESM(require("path"));
|
|
25024
25464
|
init_atomic_file();
|
|
@@ -25085,17 +25525,20 @@ async function waitForHarnessGate(options) {
|
|
|
25085
25525
|
options.onObservation?.(observation, now() - started);
|
|
25086
25526
|
if (!isTransitionalHarnessPhase(observation.phase)) {
|
|
25087
25527
|
const waitedMs2 = now() - started;
|
|
25528
|
+
let reason = deferred ? "settled-after-wait" : "settled";
|
|
25529
|
+
if (observation.phase === "unknown") reason = "evidence-unavailable";
|
|
25088
25530
|
return {
|
|
25089
25531
|
version: 1,
|
|
25090
25532
|
decision: deferred ? "deferred-allow" : "allow",
|
|
25091
|
-
reason
|
|
25533
|
+
reason,
|
|
25092
25534
|
waitedMs: waitedMs2,
|
|
25093
25535
|
observations,
|
|
25094
25536
|
observedPhase: observation.phase
|
|
25095
25537
|
};
|
|
25096
25538
|
}
|
|
25097
25539
|
const waitedMs = now() - started;
|
|
25098
|
-
|
|
25540
|
+
const remainingMs = budget - waitedMs;
|
|
25541
|
+
if (remainingMs <= 0) {
|
|
25099
25542
|
return {
|
|
25100
25543
|
version: 1,
|
|
25101
25544
|
decision: "refuse",
|
|
@@ -25120,7 +25563,7 @@ async function waitForHarnessGate(options) {
|
|
|
25120
25563
|
}
|
|
25121
25564
|
}
|
|
25122
25565
|
deferred = true;
|
|
25123
|
-
await sleep3(Math.min(interval,
|
|
25566
|
+
await sleep3(Math.min(interval, remainingMs));
|
|
25124
25567
|
}
|
|
25125
25568
|
}
|
|
25126
25569
|
function parseHarnessGateBudget(value) {
|
|
@@ -25162,6 +25605,91 @@ __export(harness_exports, {
|
|
|
25162
25605
|
detectHarnessHook: () => detectHarnessHook,
|
|
25163
25606
|
runHarnessCommand: () => runHarnessCommand
|
|
25164
25607
|
});
|
|
25608
|
+
function commandSegments(command) {
|
|
25609
|
+
const segments = [];
|
|
25610
|
+
let current = "";
|
|
25611
|
+
let quote;
|
|
25612
|
+
for (const char of command) {
|
|
25613
|
+
if (quote) {
|
|
25614
|
+
current += char;
|
|
25615
|
+
if (char === quote) quote = void 0;
|
|
25616
|
+
continue;
|
|
25617
|
+
}
|
|
25618
|
+
if (char === "'" || char === '"') {
|
|
25619
|
+
quote = char;
|
|
25620
|
+
current += char;
|
|
25621
|
+
continue;
|
|
25622
|
+
}
|
|
25623
|
+
if (char === ";" || char === "\n" || char === "&" || char === "|" || char === "(" || char === ")") {
|
|
25624
|
+
segments.push(current);
|
|
25625
|
+
current = "";
|
|
25626
|
+
continue;
|
|
25627
|
+
}
|
|
25628
|
+
current += char;
|
|
25629
|
+
}
|
|
25630
|
+
segments.push(current);
|
|
25631
|
+
return segments;
|
|
25632
|
+
}
|
|
25633
|
+
function segmentWords(segment, limit) {
|
|
25634
|
+
const words = [];
|
|
25635
|
+
let current = "";
|
|
25636
|
+
let quote;
|
|
25637
|
+
const flush = () => {
|
|
25638
|
+
if (current) words.push(current);
|
|
25639
|
+
current = "";
|
|
25640
|
+
};
|
|
25641
|
+
for (const char of segment) {
|
|
25642
|
+
if (quote) {
|
|
25643
|
+
if (char === quote) {
|
|
25644
|
+
quote = void 0;
|
|
25645
|
+
continue;
|
|
25646
|
+
}
|
|
25647
|
+
current += char;
|
|
25648
|
+
continue;
|
|
25649
|
+
}
|
|
25650
|
+
if (char === "'" || char === '"') {
|
|
25651
|
+
quote = char;
|
|
25652
|
+
continue;
|
|
25653
|
+
}
|
|
25654
|
+
if (char === " " || char === " ") {
|
|
25655
|
+
flush();
|
|
25656
|
+
if (words.length >= limit) return words;
|
|
25657
|
+
continue;
|
|
25658
|
+
}
|
|
25659
|
+
current += char;
|
|
25660
|
+
}
|
|
25661
|
+
flush();
|
|
25662
|
+
return words;
|
|
25663
|
+
}
|
|
25664
|
+
function executableName(word) {
|
|
25665
|
+
return word.slice(word.lastIndexOf("/") + 1);
|
|
25666
|
+
}
|
|
25667
|
+
function commandWord(segment) {
|
|
25668
|
+
const words = segmentWords(segment, COMMAND_WORD_LIMIT);
|
|
25669
|
+
let index = 0;
|
|
25670
|
+
for (; ; ) {
|
|
25671
|
+
const word = words[index];
|
|
25672
|
+
if (word === void 0) return void 0;
|
|
25673
|
+
if (word === "env" || /^[A-Za-z_][A-Za-z0-9_]*=/u.test(word)) {
|
|
25674
|
+
index += 1;
|
|
25675
|
+
continue;
|
|
25676
|
+
}
|
|
25677
|
+
break;
|
|
25678
|
+
}
|
|
25679
|
+
const launcher = words[index];
|
|
25680
|
+
if (launcher !== void 0 && LAUNCHER_WORDS.has(executableName(launcher))) {
|
|
25681
|
+
index += 1;
|
|
25682
|
+
const subcommand = words[index];
|
|
25683
|
+
if (subcommand !== void 0 && LAUNCHER_SUBCOMMANDS.has(subcommand)) index += 1;
|
|
25684
|
+
}
|
|
25685
|
+
return words[index];
|
|
25686
|
+
}
|
|
25687
|
+
function isDevrouterLifecycleCommand(command) {
|
|
25688
|
+
return commandSegments(command).some((segment) => {
|
|
25689
|
+
const word = commandWord(segment);
|
|
25690
|
+
return word !== void 0 && DEVROUTER_EXECUTABLES.has(executableName(word));
|
|
25691
|
+
});
|
|
25692
|
+
}
|
|
25165
25693
|
function detectHarnessHook(payload) {
|
|
25166
25694
|
const turnId = payload.turn_id;
|
|
25167
25695
|
return typeof turnId === "string" && turnId.length > 0 ? "codex" : "claude";
|
|
@@ -25208,11 +25736,19 @@ function permitReason(decision) {
|
|
|
25208
25736
|
}
|
|
25209
25737
|
return `devrouter: this tool call's wait was cancelled${age}; the harness may have run it. Verify whether it ran before issuing a new call.`;
|
|
25210
25738
|
}
|
|
25211
|
-
switch (decision.
|
|
25212
|
-
case "
|
|
25739
|
+
switch (decision.reason) {
|
|
25740
|
+
case "budget-exhausted":
|
|
25213
25741
|
return `devrouter: the managed environment is still ${decision.observedPhase} after waiting ${seconds}s. Do not retry automatically; run 'devrouter status .' and continue once it settles.`;
|
|
25214
|
-
case "
|
|
25742
|
+
case "settled-after-wait":
|
|
25215
25743
|
return `devrouter: environment settled after ${seconds}s; the tool may run now.`;
|
|
25744
|
+
case "devrouter-command":
|
|
25745
|
+
return "devrouter: lifecycle command; the gate left it to the lifecycle engine and did not observe the environment.";
|
|
25746
|
+
case "unmanaged-checkout":
|
|
25747
|
+
return "devrouter: no managed checkout was found for this call; the gate did not observe environment state.";
|
|
25748
|
+
case "hook-payload-invalid":
|
|
25749
|
+
return "devrouter: the hook payload was unreadable; the gate did not observe environment state.";
|
|
25750
|
+
case "evidence-unavailable":
|
|
25751
|
+
return "devrouter: lifecycle evidence was unavailable; the gate observed no settled phase and the tool proceeds.";
|
|
25216
25752
|
default:
|
|
25217
25753
|
return "devrouter: environment settled.";
|
|
25218
25754
|
}
|
|
@@ -25280,10 +25816,9 @@ async function runHarnessCommand(method, options, repoPath, dependencies = {}) {
|
|
|
25280
25816
|
return;
|
|
25281
25817
|
}
|
|
25282
25818
|
kind = detectHarnessHook(payload);
|
|
25283
|
-
const toolName = typeof payload.tool_name === "string" ? payload.tool_name : "";
|
|
25284
25819
|
const toolInput = isRecord7(payload.tool_input) ? payload.tool_input : {};
|
|
25285
|
-
const command = typeof toolInput.command === "string" ? toolInput.command : "";
|
|
25286
|
-
if (
|
|
25820
|
+
const command = typeof toolInput.command === "string" ? toolInput.command : typeof toolInput.cmd === "string" ? toolInput.cmd : "";
|
|
25821
|
+
if (isDevrouterLifecycleCommand(command)) {
|
|
25287
25822
|
const decision2 = gateDecision("allow", "devrouter-command");
|
|
25288
25823
|
process.stdout.write(
|
|
25289
25824
|
json ? `${JSON.stringify(decision2)}
|
|
@@ -25305,7 +25840,7 @@ async function runHarnessCommand(method, options, repoPath, dependencies = {}) {
|
|
|
25305
25840
|
}
|
|
25306
25841
|
const budgetMs = parseHarnessGateBudget(options.waitBudgetMs);
|
|
25307
25842
|
const toolUseId = typeof payload.tool_use_id === "string" && payload.tool_use_id.length > 0 && payload.tool_use_id.length <= MAX_TOOL_USE_ID_LENGTH2 ? payload.tool_use_id : void 0;
|
|
25308
|
-
const payloadSha256 = (0,
|
|
25843
|
+
const payloadSha256 = (0, import_node_crypto28.createHash)("sha256").update(JSON.stringify(toolInput)).digest("hex");
|
|
25309
25844
|
const claim2 = dependencies.claim ?? ((root, input2) => {
|
|
25310
25845
|
const outcome = claimHarnessContinuation(root, input2);
|
|
25311
25846
|
if (outcome.kind === "claimed") {
|
|
@@ -25413,17 +25948,20 @@ async function runHarnessCommand(method, options, repoPath, dependencies = {}) {
|
|
|
25413
25948
|
`
|
|
25414
25949
|
);
|
|
25415
25950
|
}
|
|
25416
|
-
var
|
|
25951
|
+
var import_node_crypto28, MAX_HOOK_PAYLOAD_BYTES, STDIN_TIMEOUT_MS, MAX_TOOL_USE_ID_LENGTH2, DEVROUTER_EXECUTABLES, LAUNCHER_WORDS, LAUNCHER_SUBCOMMANDS, COMMAND_WORD_LIMIT;
|
|
25417
25952
|
var init_harness = __esm({
|
|
25418
25953
|
"src/commands/harness.ts"() {
|
|
25419
25954
|
"use strict";
|
|
25420
|
-
|
|
25955
|
+
import_node_crypto28 = require("crypto");
|
|
25421
25956
|
init_harness_continuation();
|
|
25422
25957
|
init_harness_gate();
|
|
25423
25958
|
MAX_HOOK_PAYLOAD_BYTES = 256 * 1024;
|
|
25424
25959
|
STDIN_TIMEOUT_MS = 5e3;
|
|
25425
25960
|
MAX_TOOL_USE_ID_LENGTH2 = 256;
|
|
25426
|
-
|
|
25961
|
+
DEVROUTER_EXECUTABLES = /* @__PURE__ */ new Set(["devrouter", "devrouter-process"]);
|
|
25962
|
+
LAUNCHER_WORDS = /* @__PURE__ */ new Set(["npx", "pnpm", "npm", "yarn"]);
|
|
25963
|
+
LAUNCHER_SUBCOMMANDS = /* @__PURE__ */ new Set(["exec", "dlx"]);
|
|
25964
|
+
COMMAND_WORD_LIMIT = 8;
|
|
25427
25965
|
}
|
|
25428
25966
|
});
|
|
25429
25967
|
|
|
@@ -25530,7 +26068,7 @@ async function runOpenCommand(name) {
|
|
|
25530
26068
|
);
|
|
25531
26069
|
return;
|
|
25532
26070
|
}
|
|
25533
|
-
const result = (0,
|
|
26071
|
+
const result = (0, import_node_child_process32.spawnSync)("open", [url], { encoding: "utf-8" });
|
|
25534
26072
|
if (result.status !== 0) {
|
|
25535
26073
|
const details = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
25536
26074
|
throw new Error(`Unable to open '${url}': ${details || "unknown error"}`);
|
|
@@ -25538,11 +26076,11 @@ async function runOpenCommand(name) {
|
|
|
25538
26076
|
process.stdout.write(`Opened ${url}
|
|
25539
26077
|
`);
|
|
25540
26078
|
}
|
|
25541
|
-
var
|
|
26079
|
+
var import_node_child_process32;
|
|
25542
26080
|
var init_open = __esm({
|
|
25543
26081
|
"src/commands/open.ts"() {
|
|
25544
26082
|
"use strict";
|
|
25545
|
-
|
|
26083
|
+
import_node_child_process32 = require("child_process");
|
|
25546
26084
|
init_docker();
|
|
25547
26085
|
init_host_routes();
|
|
25548
26086
|
init_repo_config();
|
|
@@ -25565,7 +26103,7 @@ async function runLogsCommand(options) {
|
|
|
25565
26103
|
const args = ["logs", "--tail", tail, ROUTER_CONTAINER_NAME];
|
|
25566
26104
|
if (options.follow) {
|
|
25567
26105
|
args.splice(1, 0, "-f");
|
|
25568
|
-
const child = (0,
|
|
26106
|
+
const child = (0, import_node_child_process33.spawn)("docker", args, { stdio: "inherit" });
|
|
25569
26107
|
const onSignal = () => {
|
|
25570
26108
|
child.kill("SIGTERM");
|
|
25571
26109
|
};
|
|
@@ -25579,17 +26117,17 @@ async function runLogsCommand(options) {
|
|
|
25579
26117
|
});
|
|
25580
26118
|
});
|
|
25581
26119
|
} else {
|
|
25582
|
-
const result = (0,
|
|
26120
|
+
const result = (0, import_node_child_process33.spawnSync)("docker", args, { stdio: "inherit" });
|
|
25583
26121
|
if (result.status !== 0) {
|
|
25584
26122
|
throw new Error("Failed to retrieve router logs.");
|
|
25585
26123
|
}
|
|
25586
26124
|
}
|
|
25587
26125
|
}
|
|
25588
|
-
var
|
|
26126
|
+
var import_node_child_process33;
|
|
25589
26127
|
var init_logs = __esm({
|
|
25590
26128
|
"src/commands/logs.ts"() {
|
|
25591
26129
|
"use strict";
|
|
25592
|
-
|
|
26130
|
+
import_node_child_process33 = require("child_process");
|
|
25593
26131
|
init_docker();
|
|
25594
26132
|
init_router();
|
|
25595
26133
|
}
|
|
@@ -27538,7 +28076,7 @@ function sanitizeRouterId(value) {
|
|
|
27538
28076
|
return value.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
27539
28077
|
}
|
|
27540
28078
|
function repoHash(repoPath) {
|
|
27541
|
-
return (0,
|
|
28079
|
+
return (0, import_node_crypto29.createHash)("sha1").update(import_node_path64.default.resolve(repoPath)).digest("hex").slice(0, 12);
|
|
27542
28080
|
}
|
|
27543
28081
|
function asDockerApp(app) {
|
|
27544
28082
|
return app.runtime === "docker";
|
|
@@ -27635,7 +28173,7 @@ function runDockerComposeUp(repoPath, composeFiles2, overlayPath, services) {
|
|
|
27635
28173
|
fileArgs.push("-f", resolved);
|
|
27636
28174
|
}
|
|
27637
28175
|
const args = ["compose", ...fileArgs, "-f", overlayPath, "up", "-d", "--wait", ...services];
|
|
27638
|
-
const result = (0,
|
|
28176
|
+
const result = (0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27639
28177
|
encoding: "utf-8",
|
|
27640
28178
|
cwd: repoPath
|
|
27641
28179
|
});
|
|
@@ -27663,7 +28201,7 @@ function queryRunningComposeServices(repoPath, composeFiles2, overlayPath, servi
|
|
|
27663
28201
|
"--services",
|
|
27664
28202
|
...services
|
|
27665
28203
|
];
|
|
27666
|
-
const result = (0,
|
|
28204
|
+
const result = (0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27667
28205
|
encoding: "utf-8",
|
|
27668
28206
|
cwd: repoPath
|
|
27669
28207
|
});
|
|
@@ -27689,7 +28227,7 @@ function runDockerComposeStop(repoPath, composeFiles2, overlayPath, services) {
|
|
|
27689
28227
|
fileArgs.push("-f", resolved);
|
|
27690
28228
|
}
|
|
27691
28229
|
const args = ["compose", ...fileArgs, "-f", overlayPath, "stop", ...services];
|
|
27692
|
-
const result = (0,
|
|
28230
|
+
const result = (0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27693
28231
|
encoding: "utf-8",
|
|
27694
28232
|
cwd: repoPath
|
|
27695
28233
|
});
|
|
@@ -27715,7 +28253,7 @@ function runDockerComposeLogs(repoPath, composeFiles2, overlayPath, services, ta
|
|
|
27715
28253
|
String(tail),
|
|
27716
28254
|
...services
|
|
27717
28255
|
];
|
|
27718
|
-
(0,
|
|
28256
|
+
(0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27719
28257
|
stdio: "inherit",
|
|
27720
28258
|
cwd: repoPath
|
|
27721
28259
|
});
|
|
@@ -27727,7 +28265,7 @@ function queryMappedPort(repoPath, composeFiles2, overlayPath, service, internal
|
|
|
27727
28265
|
fileArgs.push("-f", resolved);
|
|
27728
28266
|
}
|
|
27729
28267
|
const args = ["compose", ...fileArgs, "-f", overlayPath, "port", service, String(internalPort)];
|
|
27730
|
-
const result = (0,
|
|
28268
|
+
const result = (0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27731
28269
|
encoding: "utf-8",
|
|
27732
28270
|
cwd: repoPath
|
|
27733
28271
|
});
|
|
@@ -27741,12 +28279,12 @@ function queryMappedPort(repoPath, composeFiles2, overlayPath, service, internal
|
|
|
27741
28279
|
const port = Number(match[1]);
|
|
27742
28280
|
return Number.isInteger(port) && port > 0 ? port : void 0;
|
|
27743
28281
|
}
|
|
27744
|
-
var
|
|
28282
|
+
var import_node_child_process34, import_node_crypto29, import_node_fs51, import_node_path64, import_yaml9;
|
|
27745
28283
|
var init_docker_run = __esm({
|
|
27746
28284
|
"src/core/docker-run.ts"() {
|
|
27747
28285
|
"use strict";
|
|
27748
|
-
|
|
27749
|
-
|
|
28286
|
+
import_node_child_process34 = require("child_process");
|
|
28287
|
+
import_node_crypto29 = require("crypto");
|
|
27750
28288
|
import_node_fs51 = __toESM(require("fs"));
|
|
27751
28289
|
import_node_path64 = __toESM(require("path"));
|
|
27752
28290
|
import_yaml9 = __toESM(require("yaml"));
|
|
@@ -27838,7 +28376,7 @@ function isProcessRunning(pid) {
|
|
|
27838
28376
|
}
|
|
27839
28377
|
}
|
|
27840
28378
|
function readProcessTree(rootPid) {
|
|
27841
|
-
const result = (0,
|
|
28379
|
+
const result = (0, import_node_child_process35.spawnSync)("ps", ["-ax", "-o", "pid=,ppid="], { encoding: "utf-8" });
|
|
27842
28380
|
if (result.status !== 0) {
|
|
27843
28381
|
return [rootPid];
|
|
27844
28382
|
}
|
|
@@ -27949,12 +28487,12 @@ function detectListeningPorts(pids) {
|
|
|
27949
28487
|
if (pids.length === 0) {
|
|
27950
28488
|
return [];
|
|
27951
28489
|
}
|
|
27952
|
-
const result = (0,
|
|
28490
|
+
const result = (0, import_node_child_process35.spawnSync)("lsof", ["-nP", "-iTCP", "-sTCP:LISTEN", "-a", "-p", pids.join(",")], {
|
|
27953
28491
|
encoding: "utf-8"
|
|
27954
28492
|
});
|
|
27955
28493
|
if (result.error && result.error.code === "ENOENT") {
|
|
27956
28494
|
if (process.platform === "linux") {
|
|
27957
|
-
const ssResult = (0,
|
|
28495
|
+
const ssResult = (0, import_node_child_process35.spawnSync)("ss", ["-H", "-lntp", "-p"], { encoding: "utf-8" });
|
|
27958
28496
|
if (ssResult.status === 0 && ssResult.stdout) {
|
|
27959
28497
|
return parseSsListeningPorts(ssResult.stdout, new Set(pids));
|
|
27960
28498
|
}
|
|
@@ -28013,7 +28551,7 @@ async function runHostApp(repoPath, app, extraEnv = {}, secretManager, env, work
|
|
|
28013
28551
|
app.hostRun.command,
|
|
28014
28552
|
true
|
|
28015
28553
|
) : app.hostRun.command;
|
|
28016
|
-
const child = (0,
|
|
28554
|
+
const child = (0, import_node_child_process35.spawn)(spawnCommand, {
|
|
28017
28555
|
cwd: commandCwd,
|
|
28018
28556
|
stdio: "inherit",
|
|
28019
28557
|
shell: true,
|
|
@@ -28381,7 +28919,7 @@ async function execWithAppEnv(options) {
|
|
|
28381
28919
|
options.command[0],
|
|
28382
28920
|
true
|
|
28383
28921
|
);
|
|
28384
|
-
child = (0,
|
|
28922
|
+
child = (0, import_node_child_process35.spawn)(wrapped, {
|
|
28385
28923
|
cwd: deps.repoPath,
|
|
28386
28924
|
stdio: "inherit",
|
|
28387
28925
|
shell: true,
|
|
@@ -28395,7 +28933,7 @@ async function execWithAppEnv(options) {
|
|
|
28395
28933
|
false
|
|
28396
28934
|
);
|
|
28397
28935
|
const [cmd, ...wrappedArgs] = wrapped;
|
|
28398
|
-
child = (0,
|
|
28936
|
+
child = (0, import_node_child_process35.spawn)(cmd, wrappedArgs, {
|
|
28399
28937
|
cwd: deps.repoPath,
|
|
28400
28938
|
stdio: "inherit",
|
|
28401
28939
|
shell: false,
|
|
@@ -28403,7 +28941,7 @@ async function execWithAppEnv(options) {
|
|
|
28403
28941
|
});
|
|
28404
28942
|
}
|
|
28405
28943
|
} else if (options.shell) {
|
|
28406
|
-
child = (0,
|
|
28944
|
+
child = (0, import_node_child_process35.spawn)(options.command[0], {
|
|
28407
28945
|
cwd: deps.repoPath,
|
|
28408
28946
|
stdio: "inherit",
|
|
28409
28947
|
shell: true,
|
|
@@ -28411,7 +28949,7 @@ async function execWithAppEnv(options) {
|
|
|
28411
28949
|
});
|
|
28412
28950
|
} else {
|
|
28413
28951
|
const [command, ...args] = options.command;
|
|
28414
|
-
child = (0,
|
|
28952
|
+
child = (0, import_node_child_process35.spawn)(command, args, {
|
|
28415
28953
|
cwd: deps.repoPath,
|
|
28416
28954
|
stdio: "inherit",
|
|
28417
28955
|
shell: false,
|
|
@@ -28432,11 +28970,11 @@ async function execWithAppEnv(options) {
|
|
|
28432
28970
|
deps.stopDeps();
|
|
28433
28971
|
}
|
|
28434
28972
|
}
|
|
28435
|
-
var
|
|
28973
|
+
var import_node_child_process35, import_node_net5, import_node_process, import_promises, POLL_INTERVAL_MS, DEFAULT_PORT_TIMEOUT_MS, PROCESS_TERMINATION_GRACE_MS;
|
|
28436
28974
|
var init_app_run = __esm({
|
|
28437
28975
|
"src/core/app-run.ts"() {
|
|
28438
28976
|
"use strict";
|
|
28439
|
-
|
|
28977
|
+
import_node_child_process35 = require("child_process");
|
|
28440
28978
|
import_node_net5 = __toESM(require("net"));
|
|
28441
28979
|
import_node_process = require("process");
|
|
28442
28980
|
import_promises = require("readline/promises");
|
|
@@ -29360,11 +29898,11 @@ function buildWorkspaceCleanupReport(options = {}, dependencies = {}) {
|
|
|
29360
29898
|
networkCapacity: (dependencies.inspectNetworkCapacity ?? inspectNetworkCapacity)()
|
|
29361
29899
|
};
|
|
29362
29900
|
}
|
|
29363
|
-
var
|
|
29901
|
+
var import_node_child_process36, import_node_fs53, DEFAULT_INACTIVE_FOR, READ_ONLY_GIT_ENV2, ACTIVITY_SOURCES, defaultCommandRunner;
|
|
29364
29902
|
var init_workspace_cleanup = __esm({
|
|
29365
29903
|
"src/core/workspace-cleanup.ts"() {
|
|
29366
29904
|
"use strict";
|
|
29367
|
-
|
|
29905
|
+
import_node_child_process36 = require("child_process");
|
|
29368
29906
|
import_node_fs53 = __toESM(require("fs"));
|
|
29369
29907
|
init_devpod_workspaces();
|
|
29370
29908
|
init_host_routes();
|
|
@@ -29383,7 +29921,7 @@ var init_workspace_cleanup = __esm({
|
|
|
29383
29921
|
];
|
|
29384
29922
|
defaultCommandRunner = (command, args, input2) => {
|
|
29385
29923
|
const environment = command === "git" ? READ_ONLY_GIT_ENV2 : { ...process.env, LC_ALL: "C" };
|
|
29386
|
-
const result = (0,
|
|
29924
|
+
const result = (0, import_node_child_process36.spawnSync)(command, args, {
|
|
29387
29925
|
encoding: "utf-8",
|
|
29388
29926
|
env: environment,
|
|
29389
29927
|
...input2 === void 0 ? {} : { input: input2 }
|
|
@@ -29480,7 +30018,7 @@ function defaultWorktreePath(mainRepo, ws) {
|
|
|
29480
30018
|
return import_node_path66.default.join(mainRepo, "trees", ws);
|
|
29481
30019
|
}
|
|
29482
30020
|
function assertDefaultWorktreeRootIgnored(mainRepo) {
|
|
29483
|
-
const ignored = (0,
|
|
30021
|
+
const ignored = (0, import_node_child_process37.spawnSync)("git", ["-C", mainRepo, "check-ignore", "-q", "--no-index", "trees/"], {
|
|
29484
30022
|
encoding: "utf-8"
|
|
29485
30023
|
});
|
|
29486
30024
|
if (ignored.status !== 0) {
|
|
@@ -29608,7 +30146,7 @@ function assertFullDownPreflight(mainRepo, target) {
|
|
|
29608
30146
|
`Worktree '${target.worktreePath}' is locked; unlock it before workspace down.`
|
|
29609
30147
|
);
|
|
29610
30148
|
}
|
|
29611
|
-
const status = (0,
|
|
30149
|
+
const status = (0, import_node_child_process37.spawnSync)(
|
|
29612
30150
|
"git",
|
|
29613
30151
|
["-C", target.worktreePath, "status", "--porcelain", "--untracked-files=normal"],
|
|
29614
30152
|
{ encoding: "utf-8" }
|
|
@@ -29672,11 +30210,11 @@ async function workspaceUp(branch, opts = {}) {
|
|
|
29672
30210
|
return selectedPath;
|
|
29673
30211
|
}
|
|
29674
30212
|
if (!opts.path) assertDefaultWorktreeRootIgnored(mainRepo);
|
|
29675
|
-
const add = (0,
|
|
30213
|
+
const add = (0, import_node_child_process37.spawnSync)("git", ["-C", mainRepo, "worktree", "add", selectedPath, branch], {
|
|
29676
30214
|
encoding: "utf-8"
|
|
29677
30215
|
});
|
|
29678
30216
|
if (add.status !== 0) {
|
|
29679
|
-
const addNew = (0,
|
|
30217
|
+
const addNew = (0, import_node_child_process37.spawnSync)(
|
|
29680
30218
|
"git",
|
|
29681
30219
|
["-C", mainRepo, "worktree", "add", "-b", branch, selectedPath],
|
|
29682
30220
|
{ encoding: "utf-8" }
|
|
@@ -29817,7 +30355,7 @@ async function runWorkspaceLifecycle(action2, target, opts = {}) {
|
|
|
29817
30355
|
const result = await mutateWorkspaceRuntime("delete", resolved, worktrees, opts.quiet);
|
|
29818
30356
|
if (removeWorktree) {
|
|
29819
30357
|
if (resolved.worktree && !resolved.worktree.prunable && import_node_fs54.default.existsSync(resolved.worktreePath)) {
|
|
29820
|
-
const rm = (0,
|
|
30358
|
+
const rm = (0, import_node_child_process37.spawnSync)("git", ["-C", mainRepo, "worktree", "remove", resolved.worktreePath], {
|
|
29821
30359
|
encoding: "utf-8"
|
|
29822
30360
|
});
|
|
29823
30361
|
if (rm.status !== 0) {
|
|
@@ -29843,11 +30381,11 @@ async function workspaceStop(target, opts = {}) {
|
|
|
29843
30381
|
async function workspaceDown(target, opts = {}) {
|
|
29844
30382
|
return runWorkspaceLifecycle("down", target, opts);
|
|
29845
30383
|
}
|
|
29846
|
-
var
|
|
30384
|
+
var import_node_child_process37, import_node_fs54, import_node_path66, WORKSPACE_ALLOCATION_LOCK_WAIT_MS;
|
|
29847
30385
|
var init_workspace_lifecycle = __esm({
|
|
29848
30386
|
"src/core/workspace-lifecycle.ts"() {
|
|
29849
30387
|
"use strict";
|
|
29850
|
-
|
|
30388
|
+
import_node_child_process37 = require("child_process");
|
|
29851
30389
|
import_node_fs54 = __toESM(require("fs"));
|
|
29852
30390
|
import_node_path66 = __toESM(require("path"));
|
|
29853
30391
|
init_devpod_mutation();
|
|
@@ -30033,7 +30571,7 @@ var init_version = __esm({
|
|
|
30033
30571
|
|
|
30034
30572
|
// src/cli.ts
|
|
30035
30573
|
var import_commander = require("commander");
|
|
30036
|
-
var CLI_VERSION = true ? "0.1.
|
|
30574
|
+
var CLI_VERSION = true ? "0.1.3" : "0.0.0-dev";
|
|
30037
30575
|
var VERSION_FLAGS = /* @__PURE__ */ new Set(["-V", "--version"]);
|
|
30038
30576
|
function withErrorHandling(action2) {
|
|
30039
30577
|
return async (...args) => {
|