@orkestrel/scaffold 0.0.16 → 0.0.18
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/README.md +13 -3
- package/dist/bin/scaffold.js +67 -31
- package/dist/bin/scaffold.js.map +1 -1
- package/dist/host/claude/agents/orkestrel.md +14 -14
- package/dist/host/guides/src/scaffold.md +55 -18
- package/dist/host/tests/setupPolicy.ts +4 -3
- package/dist/src/core/index.cjs +196 -62
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +3 -3
- package/dist/src/core/index.d.ts +3 -3
- package/dist/src/core/index.js +196 -62
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +51 -33
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +10 -6
- package/dist/src/server/index.d.ts +10 -6
- package/dist/src/server/index.js +49 -31
- package/dist/src/server/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -787,13 +787,13 @@ export declare function readFileHex(root: string, path: string, code: ScaffoldEr
|
|
|
787
787
|
export declare function readFileText(root: string, path: string, code: ScaffoldErrorCode, boundary: string, limit?: number): string;
|
|
788
788
|
|
|
789
789
|
/**
|
|
790
|
-
* Read bounded physical local guide mirrors for
|
|
790
|
+
* Read bounded physical local guide mirrors for package names.
|
|
791
791
|
*
|
|
792
792
|
* @param target - The package root.
|
|
793
|
-
* @param
|
|
794
|
-
* @returns Existing guide content keyed by
|
|
793
|
+
* @param names - The package names whose mirrors are eligible.
|
|
794
|
+
* @returns Existing guide content keyed by package name.
|
|
795
795
|
*/
|
|
796
|
-
export declare function readGuideReferences(target: string,
|
|
796
|
+
export declare function readGuideReferences(target: string, names: readonly string[]): Readonly<Record<string, string>>;
|
|
797
797
|
|
|
798
798
|
/**
|
|
799
799
|
* Read and validate a vendored host root's `manifest.json`, when present.
|
|
@@ -1028,8 +1028,10 @@ export declare function storagePath(path: string): string;
|
|
|
1028
1028
|
* map, a fetched guide byte-equal to its entry verdicts `current`, anything
|
|
1029
1029
|
* differing or absent from the map verdicts `behind`; WITHOUT the map, every
|
|
1030
1030
|
* successful fetch verdicts `behind` (no reference means it needs syncing).
|
|
1031
|
-
* `pull` builds that map itself from the TARGET's
|
|
1032
|
-
*
|
|
1031
|
+
* `pull` builds that map itself from the TARGET's declared dependency mirrors;
|
|
1032
|
+
* `mirror` builds it from the registry's exact organization package list,
|
|
1033
|
+
* excluding the target's own guide and issuing no registry version reads. Both
|
|
1034
|
+
* verdicts are target-relative; `write` commits only the
|
|
1033
1035
|
* `behind` guides (never `current`, `missing`, or `failed`, which carries no
|
|
1034
1036
|
* trustworthy content) under the same realpath-anchored containment law
|
|
1035
1037
|
* `Materializer` enforces. After `destroy()` every method throws `DESTROYED`;
|
|
@@ -1080,6 +1082,7 @@ export declare class Sync implements SyncInterface {
|
|
|
1080
1082
|
*/
|
|
1081
1083
|
catalog(): Promise<readonly CatalogEntry[]>;
|
|
1082
1084
|
pull(target: string, dependencies?: readonly Dependency[]): Promise<SyncReport>;
|
|
1085
|
+
mirror(target: string): Promise<SyncReport>;
|
|
1083
1086
|
write(report: SyncReport, target: string): Promise<readonly string[]>;
|
|
1084
1087
|
destroy(): void;
|
|
1085
1088
|
}
|
|
@@ -1135,6 +1138,7 @@ export declare interface SyncInterface {
|
|
|
1135
1138
|
versions(deps: readonly Dependency[]): Promise<readonly VersionSync[]>;
|
|
1136
1139
|
catalog(): Promise<readonly CatalogEntry[]>;
|
|
1137
1140
|
pull(target: string, dependencies?: readonly Dependency[]): Promise<SyncReport>;
|
|
1141
|
+
mirror(target: string): Promise<SyncReport>;
|
|
1138
1142
|
write(report: SyncReport, target: string): Promise<readonly string[]>;
|
|
1139
1143
|
destroy(): void;
|
|
1140
1144
|
}
|
|
@@ -787,13 +787,13 @@ export declare function readFileHex(root: string, path: string, code: ScaffoldEr
|
|
|
787
787
|
export declare function readFileText(root: string, path: string, code: ScaffoldErrorCode, boundary: string, limit?: number): string;
|
|
788
788
|
|
|
789
789
|
/**
|
|
790
|
-
* Read bounded physical local guide mirrors for
|
|
790
|
+
* Read bounded physical local guide mirrors for package names.
|
|
791
791
|
*
|
|
792
792
|
* @param target - The package root.
|
|
793
|
-
* @param
|
|
794
|
-
* @returns Existing guide content keyed by
|
|
793
|
+
* @param names - The package names whose mirrors are eligible.
|
|
794
|
+
* @returns Existing guide content keyed by package name.
|
|
795
795
|
*/
|
|
796
|
-
export declare function readGuideReferences(target: string,
|
|
796
|
+
export declare function readGuideReferences(target: string, names: readonly string[]): Readonly<Record<string, string>>;
|
|
797
797
|
|
|
798
798
|
/**
|
|
799
799
|
* Read and validate a vendored host root's `manifest.json`, when present.
|
|
@@ -1028,8 +1028,10 @@ export declare function storagePath(path: string): string;
|
|
|
1028
1028
|
* map, a fetched guide byte-equal to its entry verdicts `current`, anything
|
|
1029
1029
|
* differing or absent from the map verdicts `behind`; WITHOUT the map, every
|
|
1030
1030
|
* successful fetch verdicts `behind` (no reference means it needs syncing).
|
|
1031
|
-
* `pull` builds that map itself from the TARGET's
|
|
1032
|
-
*
|
|
1031
|
+
* `pull` builds that map itself from the TARGET's declared dependency mirrors;
|
|
1032
|
+
* `mirror` builds it from the registry's exact organization package list,
|
|
1033
|
+
* excluding the target's own guide and issuing no registry version reads. Both
|
|
1034
|
+
* verdicts are target-relative; `write` commits only the
|
|
1033
1035
|
* `behind` guides (never `current`, `missing`, or `failed`, which carries no
|
|
1034
1036
|
* trustworthy content) under the same realpath-anchored containment law
|
|
1035
1037
|
* `Materializer` enforces. After `destroy()` every method throws `DESTROYED`;
|
|
@@ -1080,6 +1082,7 @@ export declare class Sync implements SyncInterface {
|
|
|
1080
1082
|
*/
|
|
1081
1083
|
catalog(): Promise<readonly CatalogEntry[]>;
|
|
1082
1084
|
pull(target: string, dependencies?: readonly Dependency[]): Promise<SyncReport>;
|
|
1085
|
+
mirror(target: string): Promise<SyncReport>;
|
|
1083
1086
|
write(report: SyncReport, target: string): Promise<readonly string[]>;
|
|
1084
1087
|
destroy(): void;
|
|
1085
1088
|
}
|
|
@@ -1135,6 +1138,7 @@ export declare interface SyncInterface {
|
|
|
1135
1138
|
versions(deps: readonly Dependency[]): Promise<readonly VersionSync[]>;
|
|
1136
1139
|
catalog(): Promise<readonly CatalogEntry[]>;
|
|
1137
1140
|
pull(target: string, dependencies?: readonly Dependency[]): Promise<SyncReport>;
|
|
1141
|
+
mirror(target: string): Promise<SyncReport>;
|
|
1138
1142
|
write(report: SyncReport, target: string): Promise<readonly string[]>;
|
|
1139
1143
|
destroy(): void;
|
|
1140
1144
|
}
|
package/dist/src/server/index.js
CHANGED
|
@@ -956,16 +956,16 @@ function packageShortName(name) {
|
|
|
956
956
|
return name.startsWith("@orkestrel/") ? name.slice(11) : name;
|
|
957
957
|
}
|
|
958
958
|
/**
|
|
959
|
-
* Read bounded physical local guide mirrors for
|
|
959
|
+
* Read bounded physical local guide mirrors for package names.
|
|
960
960
|
*
|
|
961
961
|
* @param target - The package root.
|
|
962
|
-
* @param
|
|
963
|
-
* @returns Existing guide content keyed by
|
|
962
|
+
* @param names - The package names whose mirrors are eligible.
|
|
963
|
+
* @returns Existing guide content keyed by package name.
|
|
964
964
|
*/
|
|
965
|
-
function readGuideReferences(target,
|
|
965
|
+
function readGuideReferences(target, names) {
|
|
966
966
|
const current = {};
|
|
967
|
-
for (const
|
|
968
|
-
const path = `guides/src/${packageShortName(
|
|
967
|
+
for (const name of names) {
|
|
968
|
+
const path = `guides/src/${packageShortName(name)}.md`;
|
|
969
969
|
const full = resolvePhysicalPath(target, path, "TARGET", "target");
|
|
970
970
|
const status = attempt(() => lstatSync(full));
|
|
971
971
|
if (!status.success) {
|
|
@@ -976,7 +976,7 @@ function readGuideReferences(target, dependencies) {
|
|
|
976
976
|
});
|
|
977
977
|
}
|
|
978
978
|
if (!status.value.isFile() || status.value.isSymbolicLink() || status.value.nlink !== 1) throw new ScaffoldError("TARGET", `Local guide is not a physical file at ${path}`, { path });
|
|
979
|
-
current[
|
|
979
|
+
current[name] = readFileText(target, path, "TARGET", "target");
|
|
980
980
|
}
|
|
981
981
|
return Object.freeze(current);
|
|
982
982
|
}
|
|
@@ -3515,8 +3515,10 @@ var Materializer = class {
|
|
|
3515
3515
|
* map, a fetched guide byte-equal to its entry verdicts `current`, anything
|
|
3516
3516
|
* differing or absent from the map verdicts `behind`; WITHOUT the map, every
|
|
3517
3517
|
* successful fetch verdicts `behind` (no reference means it needs syncing).
|
|
3518
|
-
* `pull` builds that map itself from the TARGET's
|
|
3519
|
-
*
|
|
3518
|
+
* `pull` builds that map itself from the TARGET's declared dependency mirrors;
|
|
3519
|
+
* `mirror` builds it from the registry's exact organization package list,
|
|
3520
|
+
* excluding the target's own guide and issuing no registry version reads. Both
|
|
3521
|
+
* verdicts are target-relative; `write` commits only the
|
|
3520
3522
|
* `behind` guides (never `current`, `missing`, or `failed`, which carries no
|
|
3521
3523
|
* trustworthy content) under the same realpath-anchored containment law
|
|
3522
3524
|
* `Materializer` enforces. After `destroy()` every method throws `DESTROYED`;
|
|
@@ -3574,29 +3576,30 @@ var Sync = class Sync {
|
|
|
3574
3576
|
}
|
|
3575
3577
|
async guides(deps, current) {
|
|
3576
3578
|
this.#ensureAlive();
|
|
3577
|
-
|
|
3579
|
+
const parsed = parseSyncDependencies(deps, false);
|
|
3580
|
+
return this.#guides(parsed.map((dependency) => dependency.name), current, Float64Array.of(this.#budget));
|
|
3578
3581
|
}
|
|
3579
3582
|
async versions(deps) {
|
|
3580
3583
|
this.#ensureAlive();
|
|
3581
3584
|
return this.#versions(deps, Float64Array.of(this.#budget));
|
|
3582
3585
|
}
|
|
3583
|
-
#guides(
|
|
3584
|
-
const parsed =
|
|
3586
|
+
#guides(names, current, allowance) {
|
|
3587
|
+
const parsed = parseSyncNames(names);
|
|
3585
3588
|
if (parsed.length > this.#items) throw new ScaffoldError("INVALID", "Sync dependency count exceeds its item limit", {
|
|
3586
3589
|
items: parsed.length,
|
|
3587
3590
|
limit: this.#items
|
|
3588
3591
|
});
|
|
3589
|
-
const reference = parseSyncCurrent(current, parsed
|
|
3590
|
-
return Sync.#runPool(parsed, this.#concurrency, async (
|
|
3591
|
-
const short = packageShortName(
|
|
3592
|
+
const reference = parseSyncCurrent(current, parsed, this.#budget);
|
|
3593
|
+
return Sync.#runPool(parsed, this.#concurrency, async (name) => {
|
|
3594
|
+
const short = packageShortName(name);
|
|
3592
3595
|
const url = this.#guideUrl(short);
|
|
3593
3596
|
const outcome = await Sync.#fetchText(url, this.#guidesTimeout, this.#retries, this.#limit, allowance, this.#controller.signal);
|
|
3594
|
-
const guide = Sync.#toGuideSync(
|
|
3597
|
+
const guide = Sync.#toGuideSync(name, short, outcome, reference);
|
|
3595
3598
|
if (outcome.kind === "failed") this.#emitter.emit("error", outcome.error);
|
|
3596
|
-
this.#emitter.emit("guide",
|
|
3599
|
+
this.#emitter.emit("guide", name);
|
|
3597
3600
|
if (this.#strict && (guide.freshness === "missing" || guide.freshness === "failed")) throw new ScaffoldError("FETCH", `Failed to fetch guide at ${url}`, {
|
|
3598
3601
|
url,
|
|
3599
|
-
name
|
|
3602
|
+
name
|
|
3600
3603
|
});
|
|
3601
3604
|
return guide;
|
|
3602
3605
|
});
|
|
@@ -3660,16 +3663,9 @@ var Sync = class Sync {
|
|
|
3660
3663
|
*/
|
|
3661
3664
|
async catalog() {
|
|
3662
3665
|
this.#ensureAlive();
|
|
3663
|
-
const orgUrl = this.#orgUrl();
|
|
3664
3666
|
const allowance = Float64Array.of(this.#budget);
|
|
3665
|
-
const
|
|
3666
|
-
|
|
3667
|
-
if (names.length > this.#items) throw new ScaffoldError("FETCH", `Package list at ${orgUrl} exceeds the item limit`, {
|
|
3668
|
-
url: orgUrl,
|
|
3669
|
-
items: names.length,
|
|
3670
|
-
limit: this.#items
|
|
3671
|
-
});
|
|
3672
|
-
return [...await Sync.#runPool(names, this.#concurrency, async (name) => {
|
|
3667
|
+
const names = await this.#packages(allowance);
|
|
3668
|
+
return await Sync.#runPool(names, this.#concurrency, async (name) => {
|
|
3673
3669
|
const packumentOutcome = await Sync.#fetchText(this.#registryUrl(name), this.#registryTimeout, this.#retries, this.#limit, allowance, this.#controller.signal);
|
|
3674
3670
|
const packument = Sync.#toPackument(packumentOutcome);
|
|
3675
3671
|
const short = packageShortName(name);
|
|
@@ -3685,7 +3681,7 @@ var Sync = class Sync {
|
|
|
3685
3681
|
version: packument.version,
|
|
3686
3682
|
description
|
|
3687
3683
|
};
|
|
3688
|
-
})
|
|
3684
|
+
});
|
|
3689
3685
|
}
|
|
3690
3686
|
async pull(target, dependencies) {
|
|
3691
3687
|
this.#ensureAlive();
|
|
@@ -3694,10 +3690,21 @@ var Sync = class Sync {
|
|
|
3694
3690
|
const deps = dependencies === void 0 ? declared : parseSyncDependencies(dependencies, false);
|
|
3695
3691
|
if (dependencies !== void 0 && deps.some((dependency) => !declared.some((candidate) => candidate.name === dependency.name && candidate.range === dependency.range))) throw new ScaffoldError("INVALID", "Sync pull selection is not declared by the target");
|
|
3696
3692
|
const name = manifestToName(manifest);
|
|
3697
|
-
const
|
|
3698
|
-
const current = readGuideReferences(target,
|
|
3693
|
+
const guideNames = deps.map((dependency) => dependency.name).filter((dependency) => dependency !== name);
|
|
3694
|
+
const current = readGuideReferences(target, guideNames);
|
|
3699
3695
|
const allowance = Float64Array.of(this.#budget);
|
|
3700
|
-
const report = syncReportOf(target, await this.#guides(
|
|
3696
|
+
const report = syncReportOf(target, await this.#guides(guideNames, current, allowance), await this.#versions(deps, allowance));
|
|
3697
|
+
this.#emitter.emit("done", report);
|
|
3698
|
+
return report;
|
|
3699
|
+
}
|
|
3700
|
+
async mirror(target) {
|
|
3701
|
+
this.#ensureAlive();
|
|
3702
|
+
const manifest = readManifest(target);
|
|
3703
|
+
const name = manifestToName(manifest);
|
|
3704
|
+
const allowance = Float64Array.of(this.#budget);
|
|
3705
|
+
const names = (await this.#packages(allowance)).filter((candidate) => candidate !== name);
|
|
3706
|
+
const current = readGuideReferences(target, names);
|
|
3707
|
+
const report = syncReportOf(target, await this.#guides(names, current, allowance), []);
|
|
3701
3708
|
this.#emitter.emit("done", report);
|
|
3702
3709
|
return report;
|
|
3703
3710
|
}
|
|
@@ -3790,6 +3797,17 @@ var Sync = class Sync {
|
|
|
3790
3797
|
#orgUrl() {
|
|
3791
3798
|
return `${this.#registryBase}/-/org/orkestrel/package`;
|
|
3792
3799
|
}
|
|
3800
|
+
async #packages(allowance) {
|
|
3801
|
+
const url = this.#orgUrl();
|
|
3802
|
+
const outcome = await Sync.#fetchText(url, this.#registryTimeout, this.#retries, this.#limit, allowance, this.#controller.signal);
|
|
3803
|
+
const names = Sync.#toOrgPackages(outcome, url);
|
|
3804
|
+
if (names.length > this.#items) throw new ScaffoldError("FETCH", `Package list at ${url} exceeds the item limit`, {
|
|
3805
|
+
url,
|
|
3806
|
+
items: names.length,
|
|
3807
|
+
limit: this.#items
|
|
3808
|
+
});
|
|
3809
|
+
return [...names].sort((left, right) => left < right ? -1 : left > right ? 1 : 0);
|
|
3810
|
+
}
|
|
3793
3811
|
static async #runPool(items, concurrency, worker) {
|
|
3794
3812
|
const results = new Array(items.length);
|
|
3795
3813
|
const state = {
|