@wairon/cli 5.1.1-dev.92 → 5.1.1-dev.93
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/cli/index.js +552 -64
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +214 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3621,6 +3621,7 @@ __export(src_exports, {
|
|
|
3621
3621
|
getRequestParentReach: () => getRequestParentReach,
|
|
3622
3622
|
getRequestProjectRoot: () => getRequestProjectRoot,
|
|
3623
3623
|
getStatusReport: () => getStatusReport,
|
|
3624
|
+
getWriteReach: () => getWriteReach,
|
|
3624
3625
|
globalGuideFilePath: () => globalGuideFilePath,
|
|
3625
3626
|
globalPacksDir: () => globalPacksDir,
|
|
3626
3627
|
globalPacksEnabled: () => globalPacksEnabled,
|
|
@@ -3792,6 +3793,8 @@ __export(src_exports, {
|
|
|
3792
3793
|
writeFileIfChanged: () => writeFileIfChanged,
|
|
3793
3794
|
writeJsonFile: () => writeJsonFile,
|
|
3794
3795
|
writeLockRecord: () => writeLockRecord,
|
|
3796
|
+
writeReachDenials: () => writeReachDenials,
|
|
3797
|
+
writeReachPermits: () => writeReachPermits,
|
|
3795
3798
|
writeRootGuideDelegator: () => writeRootGuideDelegator,
|
|
3796
3799
|
writeYamlFile: () => writeYamlFile
|
|
3797
3800
|
});
|
|
@@ -3861,6 +3864,18 @@ function listFilesRecursive(dirPath, ext) {
|
|
|
3861
3864
|
return files;
|
|
3862
3865
|
}
|
|
3863
3866
|
var projectRootOverride = null;
|
|
3867
|
+
var sameRoot = (a, b) => path.resolve(a) === path.resolve(b);
|
|
3868
|
+
function writeReachPermits(reach2, root, subsystemId) {
|
|
3869
|
+
const own = subsystemId === null ? void 0 : reach2.subsystems.find((s) => s.subsystemId === subsystemId && sameRoot(s.root, root));
|
|
3870
|
+
if (own) return own.writable;
|
|
3871
|
+
return !reach2.unwritableRoots.some((r) => sameRoot(r, root));
|
|
3872
|
+
}
|
|
3873
|
+
function writeReachDenials(reach2, root) {
|
|
3874
|
+
return reach2.subsystems.filter((s) => !s.writable && sameRoot(s.root, root));
|
|
3875
|
+
}
|
|
3876
|
+
function getWriteReach() {
|
|
3877
|
+
return requestRootStore.getStore()?.writeReach ?? null;
|
|
3878
|
+
}
|
|
3864
3879
|
var requestRootStore = new import_node_async_hooks.AsyncLocalStorage();
|
|
3865
3880
|
function currentRootBinding() {
|
|
3866
3881
|
return requestRootStore.getStore();
|
|
@@ -3876,7 +3891,8 @@ function runWithProjectBinding(dir, reach2, fn) {
|
|
|
3876
3891
|
parentReach: reach2.parentReach,
|
|
3877
3892
|
...reach2.narrowed ? { narrowed: true } : {},
|
|
3878
3893
|
...reach2.unwritableRoots ? { unwritableRoots: reach2.unwritableRoots.map((r) => path.resolve(r)) } : {},
|
|
3879
|
-
...reach2.hostedLookup ? { hostedLookup: reach2.hostedLookup } : {}
|
|
3894
|
+
...reach2.hostedLookup ? { hostedLookup: reach2.hostedLookup } : {},
|
|
3895
|
+
...reach2.writeReach ? { writeReach: reach2.writeReach } : {}
|
|
3880
3896
|
},
|
|
3881
3897
|
fn
|
|
3882
3898
|
);
|
|
@@ -15081,7 +15097,7 @@ function defaultTargetConfig(type) {
|
|
|
15081
15097
|
enabled: true
|
|
15082
15098
|
};
|
|
15083
15099
|
}
|
|
15084
|
-
var WAIRON_VERSION = "5.1.1-dev.
|
|
15100
|
+
var WAIRON_VERSION = "5.1.1-dev.93";
|
|
15085
15101
|
var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
15086
15102
|
var ARCHITECT_AGENT_ID = "agent-architect";
|
|
15087
15103
|
var ARCHITECT_TEMPLATE_ID = "architect";
|
|
@@ -26846,6 +26862,34 @@ var PartReadOnly = class extends WaironError {
|
|
|
26846
26862
|
this.name = "PartReadOnly";
|
|
26847
26863
|
}
|
|
26848
26864
|
};
|
|
26865
|
+
var SubsystemWriteDenied = class extends WaironError {
|
|
26866
|
+
constructor(message) {
|
|
26867
|
+
super(message);
|
|
26868
|
+
this.name = "SubsystemWriteDenied";
|
|
26869
|
+
}
|
|
26870
|
+
};
|
|
26871
|
+
function deniedOwners(reach2, owners) {
|
|
26872
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26873
|
+
const denied = [];
|
|
26874
|
+
for (const o of owners) {
|
|
26875
|
+
const key = `${path21.resolve(o.root)}|${o.subsystemId ?? ""}`;
|
|
26876
|
+
if (seen.has(key)) continue;
|
|
26877
|
+
seen.add(key);
|
|
26878
|
+
if (writeReachPermits(reach2, o.root, o.subsystemId)) continue;
|
|
26879
|
+
const rule = o.subsystemId === null ? void 0 : reach2.subsystems.find((s) => s.subsystemId === o.subsystemId && path21.resolve(s.root) === path21.resolve(o.root));
|
|
26880
|
+
denied.push(o.subsystemId === null ? `project "${o.project}" itself (a spec of no subsystem, decided at the project rung)` : `subsystem "${o.subsystemId}" of project "${o.project}" (decided by ${rule?.decidedBy ?? "the project rung"})`);
|
|
26881
|
+
}
|
|
26882
|
+
return denied;
|
|
26883
|
+
}
|
|
26884
|
+
function assertSpecWritesPermitted(owners, what) {
|
|
26885
|
+
const reach2 = getWriteReach();
|
|
26886
|
+
if (!reach2) return;
|
|
26887
|
+
const denied = deniedOwners(reach2, owners);
|
|
26888
|
+
if (denied.length === 0) return;
|
|
26889
|
+
throw new SubsystemWriteDenied(
|
|
26890
|
+
`SubsystemWriteDenied: ${what} would change ${denied.length === 1 ? "a spec" : "specs"} this request may not change \u2014 ${denied.join("; ")}. Nothing was written.`
|
|
26891
|
+
);
|
|
26892
|
+
}
|
|
26849
26893
|
function unknownKeysIn(raw, parsed, at, out) {
|
|
26850
26894
|
if (Array.isArray(raw)) {
|
|
26851
26895
|
if (!Array.isArray(parsed) || parsed.length !== raw.length) return;
|
|
@@ -28856,6 +28900,92 @@ var SpecWorkspace = class {
|
|
|
28856
28900
|
`The spec file ${file} belongs to the part "${held.part.alias}", fetched from git (${held.source?.git ?? "its repository"} at ${held.part.commit ?? "its pinned commit"}): a git part is read-only here. Edit it in its own repository, commit it there, and take it in with \`wairon member update ${held.part.alias}\`. Nothing was written.`
|
|
28857
28901
|
);
|
|
28858
28902
|
}
|
|
28903
|
+
/**
|
|
28904
|
+
* spec_registry.save step 5 / delete step 2: inside a hosted request, may the
|
|
28905
|
+
* request change this spec? Judged against the request's write reach with the
|
|
28906
|
+
* home's project root and the spec's owning subsystem — the document written
|
|
28907
|
+
* and, when a stored document is replaced or removed, the one stored (a
|
|
28908
|
+
* component moved out of a subsystem changes that subsystem too). Outside a
|
|
28909
|
+
* hosted request nothing is judged.
|
|
28910
|
+
*/
|
|
28911
|
+
assertHomeInReach(file, kind, document) {
|
|
28912
|
+
if (!getWriteReach()) return;
|
|
28913
|
+
const raw = this.homeRootOf(file);
|
|
28914
|
+
const owners = [];
|
|
28915
|
+
if (document !== null) owners.push(this.documentOwner(raw, kind, document));
|
|
28916
|
+
if (pathExists(file)) {
|
|
28917
|
+
try {
|
|
28918
|
+
owners.push(this.documentOwner(raw, kind, readSpecFile(file)));
|
|
28919
|
+
} catch {
|
|
28920
|
+
}
|
|
28921
|
+
}
|
|
28922
|
+
assertSpecWritesPermitted(owners, `writing ${kind} spec ${path21.basename(path21.dirname(file))}/${path21.basename(file)}`);
|
|
28923
|
+
}
|
|
28924
|
+
/** The project root a spec file is homed under: the root whose specs folder, or one of whose parts' folders, holds it (deepest wins). */
|
|
28925
|
+
homeRootOf(file) {
|
|
28926
|
+
this.scanAll();
|
|
28927
|
+
let best;
|
|
28928
|
+
let depth = -1;
|
|
28929
|
+
for (const raw of this.cachedRawRoots) {
|
|
28930
|
+
const homes = [aiPathsAt(raw.dir).specsDir(), ...raw.record.parts.map((p) => p.directory).filter((d) => d !== void 0)];
|
|
28931
|
+
for (const home of homes) {
|
|
28932
|
+
if (isWithin(home, file) && path21.resolve(home).length > depth) {
|
|
28933
|
+
best = raw;
|
|
28934
|
+
depth = path21.resolve(home).length;
|
|
28935
|
+
}
|
|
28936
|
+
}
|
|
28937
|
+
}
|
|
28938
|
+
if (!best) return { dir: this.rootDir, namespace: "", project: path21.basename(this.rootDir) };
|
|
28939
|
+
return { dir: best.dir, namespace: best.record.namespace, project: idOf(best) ?? (best.record.namespace || path21.basename(best.dir)) };
|
|
28940
|
+
}
|
|
28941
|
+
/**
|
|
28942
|
+
* The owner of one spec DOCUMENT as stored in its root (its references local
|
|
28943
|
+
* to that root): a subsystem is its own, a component or type names its
|
|
28944
|
+
* subsystem, an interface or implementation follows its component; the L0, a
|
|
28945
|
+
* system-level type and a type group belong to no subsystem.
|
|
28946
|
+
*/
|
|
28947
|
+
documentOwner(root, kind, document) {
|
|
28948
|
+
const doc = document ?? {};
|
|
28949
|
+
const local = (v) => typeof v === "string" && v ? splitNamespace(v).localId : null;
|
|
28950
|
+
const key = (v) => typeof v === "string" && v ? keyIn(root.namespace, splitNamespace(v).localId) : null;
|
|
28951
|
+
let subsystemId = null;
|
|
28952
|
+
if (kind === "subsystem") subsystemId = local(doc.id);
|
|
28953
|
+
else if (kind === "component" || kind === "type") subsystemId = local(doc.subsystem);
|
|
28954
|
+
else if (kind === "interface") subsystemId = this.componentSubsystem(key(doc.component));
|
|
28955
|
+
else if (kind === "implementation") {
|
|
28956
|
+
const contract = key(doc.contract);
|
|
28957
|
+
subsystemId = this.componentSubsystem(contract ? this.loadInterfaceSpec(contract)?.component ?? null : null);
|
|
28958
|
+
}
|
|
28959
|
+
return { root: root.dir, project: root.project, subsystemId };
|
|
28960
|
+
}
|
|
28961
|
+
/** The local id of a component's subsystem, by the component's key; null when no such component is stored. */
|
|
28962
|
+
componentSubsystem(componentKey) {
|
|
28963
|
+
if (!componentKey) return null;
|
|
28964
|
+
const subsystem = this.loadComponentSpec(componentKey)?.subsystem;
|
|
28965
|
+
return subsystem ? splitNamespace(subsystem).localId : null;
|
|
28966
|
+
}
|
|
28967
|
+
/**
|
|
28968
|
+
* The owner of one IN-MEMORY spec (its references keys, as the loader binds
|
|
28969
|
+
* them) — what a multi-spec write (a rename, a method move) judges before its
|
|
28970
|
+
* first write. `staged` answers a spec the write itself creates.
|
|
28971
|
+
*/
|
|
28972
|
+
specOwner(kind, spec, staged) {
|
|
28973
|
+
this.scanAll();
|
|
28974
|
+
const id = kind === "system" ? "" : String(spec?.id ?? "");
|
|
28975
|
+
const namespace = (kind === "system" ? "" : this.ownerKeyOf(id)) ?? "";
|
|
28976
|
+
const raw = this.cachedRawRoots.find((r) => r.record.namespace === namespace);
|
|
28977
|
+
const root = raw ? { dir: raw.dir, project: idOf(raw) ?? (namespace || path21.basename(raw.dir)) } : { dir: this.rootDir, project: path21.basename(this.rootDir) };
|
|
28978
|
+
const localOfKey = (v) => v ? splitNamespace(v).localId : null;
|
|
28979
|
+
let subsystemId = null;
|
|
28980
|
+
if (kind === "subsystem") subsystemId = localOfKey(id);
|
|
28981
|
+
else if (kind === "component" || kind === "type") subsystemId = localOfKey(spec?.subsystem);
|
|
28982
|
+
else if (kind === "interface") subsystemId = this.componentSubsystem(spec?.component ?? null);
|
|
28983
|
+
else if (kind === "implementation" && spec?.contract) {
|
|
28984
|
+
const component = this.loadInterfaceSpec(spec.contract)?.component ?? staged?.("interface", spec.contract)?.component ?? null;
|
|
28985
|
+
subsystemId = this.componentSubsystem(component);
|
|
28986
|
+
}
|
|
28987
|
+
return { root: root.dir, project: root.project, subsystemId };
|
|
28988
|
+
}
|
|
28859
28989
|
/**
|
|
28860
28990
|
* The key one spec file is approved under (stage 8): its path from the bound
|
|
28861
28991
|
* root, POSIX — or, for a part's file, `members/<alias>/<path inside the
|
|
@@ -28866,13 +28996,15 @@ var SpecWorkspace = class {
|
|
|
28866
28996
|
return approvalKeyIn(file, this.rootDir, this.cachedRoots[0]?.parts ?? []);
|
|
28867
28997
|
}
|
|
28868
28998
|
/** The file store's write, at a home the writer resolved — a part's folder included, a git part's refused. */
|
|
28869
|
-
writeHome(file, document) {
|
|
28999
|
+
writeHome(file, document, kind) {
|
|
28870
29000
|
this.assertHomeWritable(file);
|
|
29001
|
+
this.assertHomeInReach(file, kind, document);
|
|
28871
29002
|
writeSpecFile(file, document);
|
|
28872
29003
|
}
|
|
28873
29004
|
/** The file store's delete, pruning up to the specs folder the file lives in (its part's, for a part's file). */
|
|
28874
|
-
removeHome(file) {
|
|
29005
|
+
removeHome(file, kind) {
|
|
28875
29006
|
this.assertHomeWritable(file);
|
|
29007
|
+
this.assertHomeInReach(file, kind, null);
|
|
28876
29008
|
const part = this.partHolding(file)?.part;
|
|
28877
29009
|
return removeSpecFile(file, part?.directory ? aiPathsAt(part.directory).specsDir() : this.paths.specsDir());
|
|
28878
29010
|
}
|
|
@@ -29223,6 +29355,7 @@ var SpecWorkspace = class {
|
|
|
29223
29355
|
}
|
|
29224
29356
|
saveSystemSpec(spec) {
|
|
29225
29357
|
const p = this.paths.specsSystem();
|
|
29358
|
+
this.assertHomeInReach(p, "system", spec);
|
|
29226
29359
|
ensureDir(path21.dirname(p));
|
|
29227
29360
|
writeSpecFile(p, parseOrThrow(SystemSpecSchema, spec, "system", spec.name));
|
|
29228
29361
|
invalidateSpecCache();
|
|
@@ -29373,12 +29506,12 @@ var SpecWorkspace = class {
|
|
|
29373
29506
|
}
|
|
29374
29507
|
}
|
|
29375
29508
|
specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
29376
|
-
this.writeHome(p, parseOrThrow(SubsystemSpecSchema, specToWrite, "subsystem", spec.id));
|
|
29509
|
+
this.writeHome(p, parseOrThrow(SubsystemSpecSchema, specToWrite, "subsystem", spec.id), "subsystem");
|
|
29377
29510
|
invalidateSpecCache();
|
|
29378
29511
|
}
|
|
29379
29512
|
deleteSubsystemSpec(id) {
|
|
29380
29513
|
const p = this.getSubsystemPath(id);
|
|
29381
|
-
if (!this.removeHome(p)) return false;
|
|
29514
|
+
if (!this.removeHome(p, "subsystem")) return false;
|
|
29382
29515
|
invalidateSpecCache();
|
|
29383
29516
|
return true;
|
|
29384
29517
|
}
|
|
@@ -29433,14 +29566,14 @@ var SpecWorkspace = class {
|
|
|
29433
29566
|
);
|
|
29434
29567
|
}
|
|
29435
29568
|
specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
29436
|
-
this.writeHome(p, parseOrThrow(ComponentSpecSchema, specToWrite, "component", spec.id));
|
|
29569
|
+
this.writeHome(p, parseOrThrow(ComponentSpecSchema, specToWrite, "component", spec.id), "component");
|
|
29437
29570
|
invalidateSpecCache();
|
|
29438
29571
|
this.normalizeComponentLayout();
|
|
29439
29572
|
return notices;
|
|
29440
29573
|
}
|
|
29441
29574
|
deleteComponentSpec(id) {
|
|
29442
29575
|
const p = this.getComponentPath(id);
|
|
29443
|
-
if (!this.removeHome(p)) return false;
|
|
29576
|
+
if (!this.removeHome(p, "component")) return false;
|
|
29444
29577
|
invalidateSpecCache();
|
|
29445
29578
|
return true;
|
|
29446
29579
|
}
|
|
@@ -29562,13 +29695,13 @@ var SpecWorkspace = class {
|
|
|
29562
29695
|
}
|
|
29563
29696
|
}
|
|
29564
29697
|
specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
29565
|
-
this.writeHome(p, parseOrThrow(InterfaceSpecSchema, specToWrite, "interface", spec.id));
|
|
29698
|
+
this.writeHome(p, parseOrThrow(InterfaceSpecSchema, specToWrite, "interface", spec.id), "interface");
|
|
29566
29699
|
invalidateSpecCache();
|
|
29567
29700
|
return notices;
|
|
29568
29701
|
}
|
|
29569
29702
|
deleteInterfaceSpec(id) {
|
|
29570
29703
|
const p = this.getInterfacePath(id);
|
|
29571
|
-
if (!this.removeHome(p)) return false;
|
|
29704
|
+
if (!this.removeHome(p, "interface")) return false;
|
|
29572
29705
|
invalidateSpecCache();
|
|
29573
29706
|
return true;
|
|
29574
29707
|
}
|
|
@@ -29618,13 +29751,13 @@ var SpecWorkspace = class {
|
|
|
29618
29751
|
}
|
|
29619
29752
|
}
|
|
29620
29753
|
specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
29621
|
-
this.writeHome(p, parseOrThrow(ImplementationSpecSchema, specToWrite, "implementation", spec.id));
|
|
29754
|
+
this.writeHome(p, parseOrThrow(ImplementationSpecSchema, specToWrite, "implementation", spec.id), "implementation");
|
|
29622
29755
|
invalidateSpecCache();
|
|
29623
29756
|
return notices;
|
|
29624
29757
|
}
|
|
29625
29758
|
deleteImplementationSpec(id) {
|
|
29626
29759
|
const p = this.getImplementationPath(id);
|
|
29627
|
-
if (!this.removeHome(p)) return false;
|
|
29760
|
+
if (!this.removeHome(p, "implementation")) return false;
|
|
29628
29761
|
invalidateSpecCache();
|
|
29629
29762
|
return true;
|
|
29630
29763
|
}
|
|
@@ -29670,14 +29803,14 @@ var SpecWorkspace = class {
|
|
|
29670
29803
|
}
|
|
29671
29804
|
}
|
|
29672
29805
|
specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
29673
|
-
this.writeHome(p, parseOrThrow(TypeSpecSchema, specToWrite, "type", spec.id));
|
|
29806
|
+
this.writeHome(p, parseOrThrow(TypeSpecSchema, specToWrite, "type", spec.id), "type");
|
|
29674
29807
|
invalidateSpecCache();
|
|
29675
29808
|
return notices;
|
|
29676
29809
|
}
|
|
29677
29810
|
deleteTypeSpec(id) {
|
|
29678
29811
|
const spec = this.loadTypeSpec(id);
|
|
29679
29812
|
const p = this.getTypePath(id, spec?.subsystem, spec?.group);
|
|
29680
|
-
if (!this.removeHome(p)) return false;
|
|
29813
|
+
if (!this.removeHome(p, "type")) return false;
|
|
29681
29814
|
invalidateSpecCache();
|
|
29682
29815
|
return true;
|
|
29683
29816
|
}
|
|
@@ -29700,12 +29833,12 @@ var SpecWorkspace = class {
|
|
|
29700
29833
|
specToWrite.createdAt = existing.createdAt;
|
|
29701
29834
|
}
|
|
29702
29835
|
specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
29703
|
-
this.writeHome(p, parseOrThrow(GroupSpecSchema, specToWrite, "group", spec.id));
|
|
29836
|
+
this.writeHome(p, parseOrThrow(GroupSpecSchema, specToWrite, "group", spec.id), "group");
|
|
29704
29837
|
invalidateSpecCache();
|
|
29705
29838
|
}
|
|
29706
29839
|
deleteGroupSpec(id) {
|
|
29707
29840
|
const p = this.getGroupPath(id);
|
|
29708
|
-
if (!this.removeHome(p)) return false;
|
|
29841
|
+
if (!this.removeHome(p, "group")) return false;
|
|
29709
29842
|
invalidateSpecCache();
|
|
29710
29843
|
return true;
|
|
29711
29844
|
}
|
|
@@ -29903,7 +30036,7 @@ var SpecWorkspace = class {
|
|
|
29903
30036
|
);
|
|
29904
30037
|
}
|
|
29905
30038
|
if (JSON.stringify(document) === JSON.stringify(stored)) return false;
|
|
29906
|
-
this.writeHome(file, document);
|
|
30039
|
+
this.writeHome(file, document, kind);
|
|
29907
30040
|
invalidateSpecCache();
|
|
29908
30041
|
return true;
|
|
29909
30042
|
}
|
|
@@ -30817,6 +30950,7 @@ var SpecWorkspace = class {
|
|
|
30817
30950
|
}
|
|
30818
30951
|
}
|
|
30819
30952
|
const carried = projectConfigRepository.rekeyCarried(rename, true);
|
|
30953
|
+
this.assertMoveInReach(from, to, plan6, carried.length > 0);
|
|
30820
30954
|
if (dryRun) {
|
|
30821
30955
|
const edits2 = moveChangeReports([...plan6.edits.values()], true);
|
|
30822
30956
|
return {
|
|
@@ -30856,6 +30990,14 @@ var SpecWorkspace = class {
|
|
|
30856
30990
|
carried
|
|
30857
30991
|
};
|
|
30858
30992
|
}
|
|
30993
|
+
/** Refuse a method move, naming every subsystem it may not change, before anything is written. */
|
|
30994
|
+
assertMoveInReach(from, to, plan6, rekeysRegister) {
|
|
30995
|
+
if (!getWriteReach()) return;
|
|
30996
|
+
const staged = (kind, id) => plan6.edits.get(`${kind}:${id}`)?.after;
|
|
30997
|
+
const owners = [...plan6.edits.values()].flatMap((e) => [e.before, e.after].filter((s) => s !== null && s !== void 0).map((s) => this.specOwner(e.kind, s, staged)));
|
|
30998
|
+
if (rekeysRegister) owners.push(this.specOwner("system", null));
|
|
30999
|
+
assertSpecWritesPermitted(owners, `moving methods from "${from}" to "${to}"`);
|
|
31000
|
+
}
|
|
30859
31001
|
/**
|
|
30860
31002
|
* Rekey every lint allow keyed on a moved method, staging each spec it
|
|
30861
31003
|
* changes like any other reference the move follows. An allow anchored at a
|
|
@@ -31586,6 +31728,14 @@ function normalizeReferences(kind, id) {
|
|
|
31586
31728
|
function rewriteReferences(kind, id, edits) {
|
|
31587
31729
|
return current().respellReferences(kind, id, edits);
|
|
31588
31730
|
}
|
|
31731
|
+
function assertSpecsInReach(targets, what, projectRung = false) {
|
|
31732
|
+
if (!getWriteReach()) return;
|
|
31733
|
+
const ws = current();
|
|
31734
|
+
const writable = ["system", "subsystem", "component", "interface", "implementation", "type"];
|
|
31735
|
+
const owners = targets.map((t) => ws.specOwner(t.kind, t.kind === "system" ? null : (writable.includes(t.kind) ? ws.load(t.kind, t.id) : null) ?? { id: t.id }));
|
|
31736
|
+
if (projectRung) owners.push(ws.specOwner("system", null));
|
|
31737
|
+
assertSpecWritesPermitted(owners, what);
|
|
31738
|
+
}
|
|
31589
31739
|
function moveMethods(from, to, methods, hooks, dryRun) {
|
|
31590
31740
|
return current().moveMethods(from, to, methods, hooks, dryRun);
|
|
31591
31741
|
}
|
|
@@ -33151,7 +33301,7 @@ function restateReExports(from, to) {
|
|
|
33151
33301
|
publicInterfaces: entries.map((e) => e.from === from ? { ...e, from: to } : e)
|
|
33152
33302
|
});
|
|
33153
33303
|
}
|
|
33154
|
-
function rewriteRefFields(specsDir, remap, excludeDir) {
|
|
33304
|
+
function rewriteRefFields(specsDir, remap, excludeDir, dryRun = false) {
|
|
33155
33305
|
const rewritten = [];
|
|
33156
33306
|
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
33157
33307
|
if (excludeDir && isWithinDir2(excludeDir, file)) continue;
|
|
@@ -33164,12 +33314,12 @@ function rewriteRefFields(specsDir, remap, excludeDir) {
|
|
|
33164
33314
|
if (!raw || typeof raw !== "object") continue;
|
|
33165
33315
|
const kind = specKind(raw);
|
|
33166
33316
|
if (!rewriteSpecRefs(raw, remap) || !kind) continue;
|
|
33167
|
-
writeYamlFile(file, raw);
|
|
33317
|
+
if (!dryRun) writeYamlFile(file, raw);
|
|
33168
33318
|
rewritten.push({ kind, id: kind === "system" ? "system" : String(raw.id) });
|
|
33169
33319
|
}
|
|
33170
33320
|
return rewritten;
|
|
33171
33321
|
}
|
|
33172
|
-
function rekeyLintAllows(specsDir, rename) {
|
|
33322
|
+
function rekeyLintAllows(specsDir, rename, dryRun = false) {
|
|
33173
33323
|
const rewritten = [];
|
|
33174
33324
|
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
33175
33325
|
let raw;
|
|
@@ -33200,7 +33350,7 @@ function rekeyLintAllows(specsDir, rename) {
|
|
|
33200
33350
|
}
|
|
33201
33351
|
}
|
|
33202
33352
|
if (!changed) continue;
|
|
33203
|
-
writeYamlFile(file, raw);
|
|
33353
|
+
if (!dryRun) writeYamlFile(file, raw);
|
|
33204
33354
|
rewritten.push({ kind, id: specId });
|
|
33205
33355
|
}
|
|
33206
33356
|
return rewritten;
|
|
@@ -33278,15 +33428,22 @@ function renameComponent(componentId, newId) {
|
|
|
33278
33428
|
specs: renamed.map(({ from, to }) => ({ from, to })),
|
|
33279
33429
|
components: [{ from: componentId, to: newId }]
|
|
33280
33430
|
};
|
|
33281
|
-
projectConfigRepository.rekeyCarried(rename, true);
|
|
33282
|
-
const
|
|
33431
|
+
const registerEdits = projectConfigRepository.rekeyCarried(rename, true);
|
|
33432
|
+
const remap = (ref, position) => {
|
|
33283
33433
|
if (position === "component" || position === "entity-class" || position === "auth-source") {
|
|
33284
33434
|
return ref === componentId ? newId : ref;
|
|
33285
33435
|
}
|
|
33286
33436
|
if (position === "interface" && ref === movingInterface?.id) return interfaceId;
|
|
33287
33437
|
return ref;
|
|
33288
|
-
}
|
|
33289
|
-
const
|
|
33438
|
+
};
|
|
33439
|
+
const specsDir = aiPathsAt(getProjectRoot()).specsDir();
|
|
33440
|
+
assertSpecsInReach(
|
|
33441
|
+
[...renamed.map(({ kind, from }) => ({ kind, id: from })), ...rewriteRefFields(specsDir, remap, void 0, true), ...rekeyLintAllows(specsDir, rename, true)],
|
|
33442
|
+
`renaming component "${componentId}"`,
|
|
33443
|
+
Array.isArray(registerEdits) && registerEdits.length > 0
|
|
33444
|
+
);
|
|
33445
|
+
const rewrittenRefs = rewriteRefFields(specsDir, remap);
|
|
33446
|
+
const allowsRekeyed = rekeyLintAllows(specsDir, rename);
|
|
33290
33447
|
const rewritten = [...new Set([...rewrittenRefs, ...allowsRekeyed].filter((spec) => !renamed.some((moved) => moved.kind === spec.kind && moved.from === spec.id)).map((spec) => spec.id))];
|
|
33291
33448
|
invalidateSpecCache();
|
|
33292
33449
|
moveRenamedSpecs(componentId, newId, component, movingInterface, movingImplementation);
|
|
@@ -33376,7 +33533,18 @@ function renameMethod(componentId, methodName, newName, pinSymbol) {
|
|
|
33376
33533
|
]
|
|
33377
33534
|
}]
|
|
33378
33535
|
};
|
|
33379
|
-
projectConfigRepository.rekeyCarried(rename, true);
|
|
33536
|
+
const registerEdits = projectConfigRepository.rekeyCarried(rename, true);
|
|
33537
|
+
const methodRemap = (ref, position, owner) => position === "method" && owner === componentId && ref === methodName ? newName : ref;
|
|
33538
|
+
const reachDir = aiPathsAt(getProjectRoot()).specsDir();
|
|
33539
|
+
assertSpecsInReach(
|
|
33540
|
+
[
|
|
33541
|
+
...(rename.methods?.[0]?.specs ?? []).map((id) => ({ kind: moving.some((i) => i.id === id) ? "interface" : "implementation", id })),
|
|
33542
|
+
...rewriteRefFields(reachDir, methodRemap, void 0, true),
|
|
33543
|
+
...rekeyLintAllows(reachDir, rename, true)
|
|
33544
|
+
],
|
|
33545
|
+
`renaming method "${componentId}.${methodName}"`,
|
|
33546
|
+
Array.isArray(registerEdits) && registerEdits.length > 0
|
|
33547
|
+
);
|
|
33380
33548
|
for (const contract of moving) {
|
|
33381
33549
|
saveInterfaceSpec({
|
|
33382
33550
|
...contract,
|
|
@@ -33399,7 +33567,7 @@ function renameMethod(componentId, methodName, newName, pinSymbol) {
|
|
|
33399
33567
|
}
|
|
33400
33568
|
invalidateSpecCache();
|
|
33401
33569
|
const specsDir = aiPathsAt(getProjectRoot()).specsDir();
|
|
33402
|
-
const retargeted = rewriteRefFields(specsDir,
|
|
33570
|
+
const retargeted = rewriteRefFields(specsDir, methodRemap);
|
|
33403
33571
|
const allowsRekeyed = rekeyLintAllows(specsDir, rename);
|
|
33404
33572
|
const rewritten = [...new Set([...retargeted, ...allowsRekeyed].map((spec) => spec.id))];
|
|
33405
33573
|
const mentions = collectMentions(specsDir, methodName, moving);
|
|
@@ -39438,10 +39606,13 @@ function rehearse2(plan6) {
|
|
|
39438
39606
|
return { ...plan6, refusals: [...plan6.refusals, { code: `${plan6.request.verb}-refused`, project: "", detail }] };
|
|
39439
39607
|
}
|
|
39440
39608
|
const changes = diff(rehearsal);
|
|
39441
|
-
const
|
|
39442
|
-
|
|
39609
|
+
const refused2 = [
|
|
39610
|
+
...unwritableOwners(changes).map((o) => ({ code: "family-partial", project: o, detail: `the plan must write ${o}, which this request may not write` })),
|
|
39611
|
+
...deniedSubsystems(changes)
|
|
39612
|
+
];
|
|
39613
|
+
if (refused2.length > 0) {
|
|
39443
39614
|
discard(rehearsal);
|
|
39444
|
-
return { ...plan6, refusals: [...plan6.refusals, ...
|
|
39615
|
+
return { ...plan6, refusals: [...plan6.refusals, ...refused2] };
|
|
39445
39616
|
}
|
|
39446
39617
|
return { ...plan6, rehearsal, changes, relock: relockOf(plan6, changes) };
|
|
39447
39618
|
}
|
|
@@ -39485,6 +39656,16 @@ function unwritableOwners(changes) {
|
|
|
39485
39656
|
const owners = [...new Set(changes.map((c) => path47.resolve(c.project)))];
|
|
39486
39657
|
return owners.filter((o) => denied.includes(o));
|
|
39487
39658
|
}
|
|
39659
|
+
function deniedSubsystems(changes) {
|
|
39660
|
+
const reach2 = getWriteReach();
|
|
39661
|
+
if (!reach2) return [];
|
|
39662
|
+
const owners = [...new Set(changes.map((c) => path47.resolve(c.project)))];
|
|
39663
|
+
return owners.flatMap((o) => writeReachDenials(reach2, o).map((s) => ({
|
|
39664
|
+
code: "subsystem-denied",
|
|
39665
|
+
project: o,
|
|
39666
|
+
detail: `the plan must change ${o}, which holds subsystem "${s.subsystemId}" this request may not change (decided by ${s.decidedBy}); a family migration reshapes its projects whole, so it needs write on every subsystem of every project it changes`
|
|
39667
|
+
})));
|
|
39668
|
+
}
|
|
39488
39669
|
function pathProducers(plan6, family) {
|
|
39489
39670
|
const inside = (dir) => {
|
|
39490
39671
|
const rel2 = path47.relative(plan6.familyRoot, dir);
|
|
@@ -41845,6 +42026,7 @@ function loadProjectConfig3() {
|
|
|
41845
42026
|
getRequestParentReach,
|
|
41846
42027
|
getRequestProjectRoot,
|
|
41847
42028
|
getStatusReport,
|
|
42029
|
+
getWriteReach,
|
|
41848
42030
|
globalGuideFilePath,
|
|
41849
42031
|
globalPacksDir,
|
|
41850
42032
|
globalPacksEnabled,
|
|
@@ -42016,6 +42198,8 @@ function loadProjectConfig3() {
|
|
|
42016
42198
|
writeFileIfChanged,
|
|
42017
42199
|
writeJsonFile,
|
|
42018
42200
|
writeLockRecord,
|
|
42201
|
+
writeReachDenials,
|
|
42202
|
+
writeReachPermits,
|
|
42019
42203
|
writeRootGuideDelegator,
|
|
42020
42204
|
writeYamlFile
|
|
42021
42205
|
});
|