@orkestrel/scaffold 0.0.47 → 0.0.49
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/bin/main.js +271 -53
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/orchestration.md +7 -0
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +4 -0
- package/dist/host/claude/rules/quality.md +4 -1
- package/dist/host/configs/policy.ts +4 -1
- package/dist/host/guides/scaffold.md +150 -65
- package/dist/host/manifest.json +217 -109
- package/dist/host/tests/config.test.ts +126 -1
- package/dist/src/core/index.cjs +33 -5
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +65 -8
- package/dist/src/core/index.d.ts +65 -8
- package/dist/src/core/index.js +32 -6
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +769 -137
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +681 -376
- package/dist/src/server/index.d.ts +681 -376
- package/dist/src/server/index.js +766 -141
- package/dist/src/server/index.js.map +1 -1
- package/package.json +4 -3
package/dist/bin/main.js
CHANGED
|
@@ -3,8 +3,8 @@ import { align, renderTable, strip, stripControls, width } from "@orkestrel/cons
|
|
|
3
3
|
import { attempt, isRecord, isString, parseJSON } from "@orkestrel/contract";
|
|
4
4
|
import { createMarkdown, flattenText, isTableNode } from "@orkestrel/markdown";
|
|
5
5
|
import { executeSync } from "@orkestrel/process/server";
|
|
6
|
-
import { BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFORMANCE_TEST_PATH, Compiler, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENVIRONMENTS, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, INTEGRATION_TEST_PATH, MAX_MANIFEST_BYTES, SERVICE_SETUP_PATH, SHOWCASE_CONFIG_PATH, ScaffoldError, blueprintToDevDependencies, blueprintToRootVite, blueprintToScripts, compareVersions, createBlueprint, extractRangeMajor, extractVersion, isScaffoldError, manifestToDependencies, manifestToName, nameToGuide, replacePlanRanges } from "../src/core/index.js";
|
|
7
|
-
import { Materializer, Upstream, isExactCaseFile, isPhysicalDirectory,
|
|
6
|
+
import { BIN_ENTRY_PATH, CATALOG_AGENT_PATH, CONFORMANCE_TEST_PATH, Compiler, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENVIRONMENTS, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, INTEGRATION_TEST_PATH, MAX_MANIFEST_BYTES, SERVICE_SETUP_PATH, SHOWCASE_CONFIG_PATH, ScaffoldError, blueprintToDevDependencies, blueprintToRootVite, blueprintToScripts, compareVersions, createBlueprint, extractRangeMajor, extractVersion, isDeferredPath, isScaffoldError, manifestToDependencies, manifestToName, nameToGuide, replacePlanRanges } from "../src/core/index.js";
|
|
7
|
+
import { Materializer, Upstream, filesToHost, isExactCaseFile, isPhysicalDirectory, isWorktree, listFiles, readFileText, readHostFloor, readSnapshot, resolveContainedPath } from "../src/server/index.js";
|
|
8
8
|
import { parseArgs } from "node:util";
|
|
9
9
|
//#region src/bin/constants.ts
|
|
10
10
|
/**
|
|
@@ -86,6 +86,7 @@ var COMMAND_OPTIONS = Object.freeze({
|
|
|
86
86
|
groups: Object.freeze({ type: "string" }),
|
|
87
87
|
all: Object.freeze({ type: "boolean" }),
|
|
88
88
|
dirty: Object.freeze({ type: "boolean" }),
|
|
89
|
+
offline: Object.freeze({ type: "boolean" }),
|
|
89
90
|
from: Object.freeze({
|
|
90
91
|
type: "string",
|
|
91
92
|
multiple: true
|
|
@@ -109,10 +110,12 @@ var OPTION_SUMMARY = Object.freeze({
|
|
|
109
110
|
"--groups <list>": "the artifact groups to cover; every group when absent",
|
|
110
111
|
"--all": "fetch a guide for every package the organization publishes, not the declared ones alone",
|
|
111
112
|
"--dirty": "delete from a tree carrying uncommitted changes",
|
|
113
|
+
"--offline": "use the distributed dependency and vendored-host floors without reading upstream",
|
|
112
114
|
"--from <path>": "read the data root from a local path instead of the bundled one; catalog alone accepts it more than once",
|
|
113
115
|
"--target <path>": "the directory the verb operates on; the working directory when absent",
|
|
114
116
|
"--json": "emit one machine-readable value instead of a report",
|
|
115
|
-
ORKESTREL_SCAFFOLD_REGISTRY: "the registry base mapped to upstream.registry.base"
|
|
117
|
+
ORKESTREL_SCAFFOLD_REGISTRY: "the registry base mapped to upstream.registry.base",
|
|
118
|
+
ORKESTREL_SCAFFOLD_REPOSITORY: "the repository base mapped to upstream.repository.base"
|
|
116
119
|
});
|
|
117
120
|
/**
|
|
118
121
|
* The options each verb takes, in usage order, frozen.
|
|
@@ -129,18 +132,21 @@ var VERB_OPTIONS = Object.freeze({
|
|
|
129
132
|
"--app <list>",
|
|
130
133
|
"--bin",
|
|
131
134
|
"--deps <list>",
|
|
135
|
+
"--offline",
|
|
132
136
|
"--from <path>",
|
|
133
137
|
"--target <path>",
|
|
134
138
|
"--json"
|
|
135
139
|
]),
|
|
136
140
|
audit: Object.freeze([
|
|
137
141
|
"--groups <list>",
|
|
142
|
+
"--offline",
|
|
138
143
|
"--from <path>",
|
|
139
144
|
"--target <path>",
|
|
140
145
|
"--json"
|
|
141
146
|
]),
|
|
142
147
|
repair: Object.freeze([
|
|
143
148
|
"--groups <list>",
|
|
149
|
+
"--offline",
|
|
144
150
|
"--from <path>",
|
|
145
151
|
"--target <path>",
|
|
146
152
|
"--json"
|
|
@@ -154,6 +160,7 @@ var VERB_OPTIONS = Object.freeze({
|
|
|
154
160
|
overwrite: Object.freeze([
|
|
155
161
|
"--groups <list>",
|
|
156
162
|
"--dirty",
|
|
163
|
+
"--offline",
|
|
157
164
|
"--from <path>",
|
|
158
165
|
"--target <path>",
|
|
159
166
|
"--json"
|
|
@@ -256,6 +263,22 @@ function optionToName(option) {
|
|
|
256
263
|
return token.startsWith("--") ? token.slice(2) : token;
|
|
257
264
|
}
|
|
258
265
|
/**
|
|
266
|
+
* Project process environment endpoints into upstream reader options.
|
|
267
|
+
*
|
|
268
|
+
* @param environment - The process environment to read.
|
|
269
|
+
* @returns The configured endpoint groups, or `undefined` when neither endpoint
|
|
270
|
+
* is configured.
|
|
271
|
+
*/
|
|
272
|
+
function environmentToUpstream(environment) {
|
|
273
|
+
const registry = environment.ORKESTREL_SCAFFOLD_REGISTRY;
|
|
274
|
+
const repository = environment.ORKESTREL_SCAFFOLD_REPOSITORY;
|
|
275
|
+
if (registry === void 0 && repository === void 0) return void 0;
|
|
276
|
+
return {
|
|
277
|
+
...registry === void 0 ? {} : { registry: { base: registry } },
|
|
278
|
+
...repository === void 0 ? {} : { repository: { base: repository } }
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
259
282
|
* Render one verb's synopsis.
|
|
260
283
|
*
|
|
261
284
|
* @param verb - The verb to describe.
|
|
@@ -355,6 +378,7 @@ function argvToCommand(argv) {
|
|
|
355
378
|
const src = typeof values.src === "string" ? values.src : void 0;
|
|
356
379
|
const app = typeof values.app === "string" ? values.app : void 0;
|
|
357
380
|
const bin = values.bin === true;
|
|
381
|
+
const offline = values.offline === true;
|
|
358
382
|
const dependencies = typeof values.deps === "string" ? values.deps : void 0;
|
|
359
383
|
const target = typeof values.target === "string" ? values.target : void 0;
|
|
360
384
|
const json = values.json === true;
|
|
@@ -374,6 +398,7 @@ function argvToCommand(argv) {
|
|
|
374
398
|
...src === void 0 ? {} : { src },
|
|
375
399
|
...app === void 0 ? {} : { app },
|
|
376
400
|
...bin ? { bin } : {},
|
|
401
|
+
...offline ? { offline } : {},
|
|
377
402
|
...dependencies === void 0 ? {} : { dependencies }
|
|
378
403
|
};
|
|
379
404
|
case "audit": return {
|
|
@@ -381,14 +406,16 @@ function argvToCommand(argv) {
|
|
|
381
406
|
json,
|
|
382
407
|
...location,
|
|
383
408
|
...source,
|
|
384
|
-
...selection
|
|
409
|
+
...selection,
|
|
410
|
+
...offline ? { offline } : {}
|
|
385
411
|
};
|
|
386
412
|
case "repair": return {
|
|
387
413
|
verb,
|
|
388
414
|
json,
|
|
389
415
|
...location,
|
|
390
416
|
...source,
|
|
391
|
-
...selection
|
|
417
|
+
...selection,
|
|
418
|
+
...offline ? { offline } : {}
|
|
392
419
|
};
|
|
393
420
|
case "catalog": return {
|
|
394
421
|
verb,
|
|
@@ -401,6 +428,7 @@ function argvToCommand(argv) {
|
|
|
401
428
|
verb,
|
|
402
429
|
json,
|
|
403
430
|
dirty: values.dirty === true,
|
|
431
|
+
...offline ? { offline } : {},
|
|
404
432
|
...location,
|
|
405
433
|
...source,
|
|
406
434
|
...selection
|
|
@@ -467,6 +495,26 @@ function dependenciesToFleet(dependencies) {
|
|
|
467
495
|
return dependencies.filter((dependency) => dependency.name.startsWith("@orkestrel/"));
|
|
468
496
|
}
|
|
469
497
|
/**
|
|
498
|
+
* Project declared concrete ranges to their distributed release floors.
|
|
499
|
+
*
|
|
500
|
+
* @param dependencies - The declarations whose floor versions to read.
|
|
501
|
+
* @returns One found floor per declaration, or `undefined` when any range names
|
|
502
|
+
* no concrete version.
|
|
503
|
+
*/
|
|
504
|
+
function dependenciesToFloors(dependencies) {
|
|
505
|
+
const releases = [];
|
|
506
|
+
for (const dependency of dependencies) {
|
|
507
|
+
const version = dependency.range.startsWith("^") || dependency.range.startsWith("~") ? dependency.range.slice(1) : dependency.range;
|
|
508
|
+
if (extractVersion(version) === void 0) return void 0;
|
|
509
|
+
releases.push({
|
|
510
|
+
...dependency,
|
|
511
|
+
lookup: "found",
|
|
512
|
+
latest: version
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
return releases;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
470
518
|
* Read the exit code registry release evidence earns.
|
|
471
519
|
*
|
|
472
520
|
* @param releases - The release verdicts to measure.
|
|
@@ -682,48 +730,64 @@ var CLI = class CLI {
|
|
|
682
730
|
const plan = this.#compile(blueprint);
|
|
683
731
|
const manifest = plan.artifacts.find((artifact) => artifact.path === "package.json" && artifact.origin !== "host");
|
|
684
732
|
if (manifest === void 0 || manifest.origin === "host") throw new ScaffoldError("BLOCKED", "The compiled plan carries no replaceable manifest.");
|
|
685
|
-
const
|
|
686
|
-
|
|
733
|
+
const versions = await this.#versions(dependenciesToFleet(manifestToDependencies(manifest.content)), command.offline === true);
|
|
734
|
+
this.#assertVersions(versions);
|
|
735
|
+
const resolved = replacePlanRanges(plan, versions.pins);
|
|
687
736
|
if (resolved === void 0) throw new ScaffoldError("BLOCKED", "The compiled plan ranges could not be replaced.");
|
|
688
|
-
const
|
|
737
|
+
const host = await this.#host(command.from, void 0, command.offline === true);
|
|
689
738
|
try {
|
|
690
|
-
const result = materializer.materialize(resolved, target);
|
|
691
|
-
|
|
739
|
+
const result = host.materializer.materialize(resolved, target);
|
|
740
|
+
const outcome = {
|
|
741
|
+
...result,
|
|
742
|
+
provenance: {
|
|
743
|
+
...versions.baseline === void 0 ? {} : { versions: versions.baseline },
|
|
744
|
+
...host.baseline === void 0 ? {} : { host: host.baseline }
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
if (command.json === true) this.#report(outcome);
|
|
692
748
|
else {
|
|
693
749
|
this.#say(`Scaffolded ${blueprint.name} into ${result.target}.`);
|
|
694
750
|
this.#say(this.#tally(result));
|
|
695
751
|
}
|
|
752
|
+
if (versions.forced || host.forced) this.#reportBaselines(outcome.provenance);
|
|
696
753
|
return 0;
|
|
697
754
|
} finally {
|
|
698
|
-
materializer.destroy();
|
|
755
|
+
host.materializer.destroy();
|
|
699
756
|
}
|
|
700
757
|
}
|
|
701
758
|
async #inspect(command) {
|
|
702
759
|
const target = command.target ?? ".";
|
|
703
760
|
const manifest = this.#manifest(target);
|
|
704
761
|
const blueprint = this.#derive(target);
|
|
762
|
+
const groups = this.#groups(command.groups);
|
|
705
763
|
const declared = manifestToPlannedDependencies(manifest, blueprint);
|
|
706
|
-
const
|
|
707
|
-
const questions = [...this.#targetQuestions(target, blueprint), ...releasesToQuestions(releases)];
|
|
708
|
-
const
|
|
764
|
+
const versions = await this.#versions(declared, command.offline === true);
|
|
765
|
+
const questions = [...this.#targetQuestions(target, blueprint), ...releasesToQuestions(versions.releases)];
|
|
766
|
+
const host = await this.#host(command.from, target, command.offline === true);
|
|
709
767
|
try {
|
|
710
|
-
const [measured] = this.#survey(materializer, blueprint, target,
|
|
768
|
+
const [measured] = this.#survey(host.materializer, blueprint, target, groups);
|
|
711
769
|
const audit = questions.length === 0 ? measured : {
|
|
712
770
|
...measured,
|
|
713
771
|
questions: [...measured.questions, ...questions]
|
|
714
772
|
};
|
|
715
773
|
const outcome = {
|
|
716
774
|
...audit,
|
|
717
|
-
releases
|
|
775
|
+
releases: versions.releases,
|
|
776
|
+
provenance: {
|
|
777
|
+
...versions.baseline === void 0 ? {} : { versions: versions.baseline },
|
|
778
|
+
...host.baseline === void 0 ? {} : { host: host.baseline }
|
|
779
|
+
}
|
|
718
780
|
};
|
|
719
781
|
if (command.json === true) this.#report(outcome);
|
|
720
782
|
else {
|
|
721
783
|
this.#present(audit);
|
|
722
|
-
this.#reportReleases(releases);
|
|
784
|
+
if (command.offline !== true) this.#reportReleases(versions.releases);
|
|
723
785
|
}
|
|
724
|
-
|
|
786
|
+
if (versions.forced || host.forced) this.#reportBaselines(outcome.provenance);
|
|
787
|
+
if (command.offline === true) return auditToExit(audit);
|
|
788
|
+
return Math.max(auditToExit(audit), releasesToExit(versions.releases), versions.forced || host.forced ? 1 : 0);
|
|
725
789
|
} finally {
|
|
726
|
-
materializer.destroy();
|
|
790
|
+
host.materializer.destroy();
|
|
727
791
|
}
|
|
728
792
|
}
|
|
729
793
|
async #restore(command) {
|
|
@@ -731,22 +795,29 @@ var CLI = class CLI {
|
|
|
731
795
|
const groups = this.#groups(command.groups);
|
|
732
796
|
const blueprint = this.#derive(target);
|
|
733
797
|
this.#assertTarget(target, blueprint);
|
|
734
|
-
const
|
|
798
|
+
const host = await this.#host(command.from, target, command.offline === true);
|
|
735
799
|
try {
|
|
736
|
-
const [audit, plan] = this.#survey(materializer, blueprint, target, groups);
|
|
800
|
+
const [audit, plan] = this.#survey(host.materializer, blueprint, target, groups);
|
|
737
801
|
if (plan === void 0) {
|
|
738
|
-
if (command.json === true) this.#report(
|
|
802
|
+
if (command.json === true) this.#report({
|
|
803
|
+
...audit,
|
|
804
|
+
provenance: { ...host.baseline === void 0 ? {} : { host: host.baseline } }
|
|
805
|
+
});
|
|
739
806
|
else this.#present(audit);
|
|
740
807
|
return 1;
|
|
741
808
|
}
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
const result = this.#merge(materializer.repair(plan, audit, target), materializer.declare(pins, target));
|
|
745
|
-
const [terminal] = this.#survey(materializer, this.#derive(target), target, groups);
|
|
809
|
+
const versions = await this.#versions(manifestToPlannedDependencies(this.#manifest(target), blueprint), command.offline === true);
|
|
810
|
+
this.#assertVersions(versions);
|
|
811
|
+
const result = this.#merge(host.materializer.repair(plan, audit, target), host.materializer.declare(versions.pins, target));
|
|
812
|
+
const [terminal] = this.#survey(host.materializer, this.#derive(target), target, groups);
|
|
746
813
|
const outcome = {
|
|
747
814
|
...result,
|
|
748
815
|
audit: terminal,
|
|
749
|
-
releases
|
|
816
|
+
releases: versions.releases,
|
|
817
|
+
provenance: {
|
|
818
|
+
...versions.baseline === void 0 ? {} : { versions: versions.baseline },
|
|
819
|
+
...host.baseline === void 0 ? {} : { host: host.baseline }
|
|
820
|
+
}
|
|
750
821
|
};
|
|
751
822
|
if (command.json === true) this.#report(outcome);
|
|
752
823
|
else {
|
|
@@ -754,9 +825,11 @@ var CLI = class CLI {
|
|
|
754
825
|
this.#reportReplacements(audit, terminal);
|
|
755
826
|
this.#say(this.#tally(result));
|
|
756
827
|
}
|
|
828
|
+
if (versions.forced || host.forced) this.#reportBaselines(outcome.provenance);
|
|
829
|
+
if (command.offline !== true && (versions.forced || host.forced)) return 1;
|
|
757
830
|
return auditToExit(terminal);
|
|
758
831
|
} finally {
|
|
759
|
-
materializer.destroy();
|
|
832
|
+
host.materializer.destroy();
|
|
760
833
|
}
|
|
761
834
|
}
|
|
762
835
|
async #refresh(command) {
|
|
@@ -768,7 +841,8 @@ var CLI = class CLI {
|
|
|
768
841
|
const releases = this.#catalogReleases(dependenciesToFleet(manifestToDependencies(this.#manifest(target))), fetched.entries);
|
|
769
842
|
const pins = this.#pin(releases);
|
|
770
843
|
this.#assertFetched(fetched.entries, fetched.mirrors);
|
|
771
|
-
const
|
|
844
|
+
const guides = fetched.mirrors.length === 0 ? void 0 : fetched.mirrors.some((mirror) => mirror.lookup === "failed") ? "floor" : "live";
|
|
845
|
+
const materializer = new Materializer({ host: host ?? readHostFloor() });
|
|
772
846
|
let result;
|
|
773
847
|
try {
|
|
774
848
|
result = this.#merge(this.#publish(materializer, target, fetched.entries, fetched.mirrors), materializer.declare(pins, target));
|
|
@@ -780,38 +854,46 @@ var CLI = class CLI {
|
|
|
780
854
|
entries: fetched.entries,
|
|
781
855
|
mirrors: fetched.mirrors,
|
|
782
856
|
dropped: previous.filter((name) => !fetched.entries.some((entry) => entry.name === name)),
|
|
783
|
-
releases
|
|
857
|
+
releases,
|
|
858
|
+
provenance: {
|
|
859
|
+
versions: "live",
|
|
860
|
+
...guides === void 0 ? {} : { guides }
|
|
861
|
+
}
|
|
784
862
|
};
|
|
785
863
|
if (command.json === true) this.#report(outcome);
|
|
786
864
|
else this.#recount(outcome);
|
|
787
|
-
return 0;
|
|
865
|
+
return guides === "floor" ? 1 : 0;
|
|
788
866
|
}
|
|
789
867
|
async #replace(command) {
|
|
790
868
|
const target = command.target ?? ".";
|
|
791
869
|
const groups = this.#groups(command.groups);
|
|
792
870
|
const blueprint = this.#derive(target);
|
|
793
871
|
this.#assertTarget(target, blueprint);
|
|
794
|
-
const
|
|
795
|
-
if (
|
|
872
|
+
const worktree = this.#worktree(target);
|
|
873
|
+
if (worktree.dirty.length > 0 && command.dirty !== true) throw new ScaffoldError("TARGET", `The target at ${target} carries ${String(worktree.dirty.length)} uncommitted change${worktree.dirty.length === 1 ? "" : "s"}. Commit them, or pass --dirty to waive the refusal.`, {
|
|
796
874
|
target,
|
|
797
|
-
dirty:
|
|
875
|
+
dirty: worktree.dirty.length
|
|
798
876
|
});
|
|
799
|
-
const
|
|
877
|
+
const host = await this.#host(command.from, target, command.offline === true);
|
|
800
878
|
try {
|
|
801
|
-
const [audit, plan] = this.#survey(materializer, blueprint, target, groups);
|
|
879
|
+
const [audit, plan] = this.#survey(host.materializer, blueprint, target, groups);
|
|
802
880
|
if (plan === void 0) {
|
|
803
|
-
if (command.json === true) this.#report(
|
|
881
|
+
if (command.json === true) this.#report({
|
|
882
|
+
...audit,
|
|
883
|
+
provenance: { ...host.baseline === void 0 ? {} : { host: host.baseline } }
|
|
884
|
+
});
|
|
804
885
|
else this.#present(audit);
|
|
805
886
|
return 1;
|
|
806
887
|
}
|
|
807
|
-
const
|
|
808
|
-
const
|
|
809
|
-
|
|
888
|
+
const declared = manifestToPlannedDependencies(this.#manifest(target), blueprint);
|
|
889
|
+
const repaired = host.materializer.repair(plan, audit, target);
|
|
890
|
+
const removed = host.materializer.remove(plan, audit, command.dirty === true ? {
|
|
891
|
+
tracked: worktree.tracked,
|
|
810
892
|
dirty: []
|
|
811
|
-
} :
|
|
893
|
+
} : worktree, target);
|
|
812
894
|
const offline = this.#merge(repaired, removed);
|
|
813
|
-
const online = await this.#
|
|
814
|
-
const [terminal] = this.#survey(materializer, blueprint, target, groups);
|
|
895
|
+
const online = command.offline === true ? await this.#offline(host.materializer, target, declared, host.baseline) : await this.#reconcile(host.materializer, target, declared, host.baseline, host.forced);
|
|
896
|
+
const [terminal] = this.#survey(host.materializer, blueprint, target, groups);
|
|
815
897
|
const outcome = {
|
|
816
898
|
...online,
|
|
817
899
|
...this.#merge(offline, online),
|
|
@@ -827,23 +909,58 @@ var CLI = class CLI {
|
|
|
827
909
|
if (online.note !== void 0) return 1;
|
|
828
910
|
return auditToExit(terminal);
|
|
829
911
|
} finally {
|
|
830
|
-
materializer.destroy();
|
|
912
|
+
host.materializer.destroy();
|
|
831
913
|
}
|
|
832
914
|
}
|
|
833
|
-
async #
|
|
915
|
+
async #offline(materializer, target, declared, host) {
|
|
916
|
+
const versions = await this.#versions(declared, true);
|
|
917
|
+
this.#assertVersions(versions);
|
|
918
|
+
return {
|
|
919
|
+
...materializer.declare(versions.pins, target),
|
|
920
|
+
entries: [],
|
|
921
|
+
mirrors: [],
|
|
922
|
+
dropped: [],
|
|
923
|
+
releases: versions.releases,
|
|
924
|
+
provenance: {
|
|
925
|
+
...versions.baseline === void 0 ? {} : { versions: versions.baseline },
|
|
926
|
+
...host === void 0 ? {} : { host }
|
|
927
|
+
},
|
|
928
|
+
note: "The catalog step did not complete: USAGE: 'catalog' does not take --offline."
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
async #reconcile(materializer, target, declared, host, hostForced) {
|
|
834
932
|
const previous = this.#previous(target);
|
|
835
933
|
let releases = [];
|
|
934
|
+
let provenance = { ...host === void 0 ? {} : { host } };
|
|
836
935
|
try {
|
|
837
|
-
|
|
838
|
-
|
|
936
|
+
const versions = await this.#versions(declared, false);
|
|
937
|
+
releases = versions.releases;
|
|
938
|
+
provenance = {
|
|
939
|
+
...versions.baseline === void 0 ? {} : { versions: versions.baseline },
|
|
940
|
+
...host === void 0 ? {} : { host }
|
|
941
|
+
};
|
|
942
|
+
this.#assertVersions(versions);
|
|
839
943
|
const fetched = await this.#fetch(target, false);
|
|
840
944
|
this.#assertFetched(fetched.entries, fetched.mirrors);
|
|
945
|
+
const guides = fetched.mirrors.length === 0 ? void 0 : fetched.mirrors.some((mirror) => mirror.lookup === "failed") ? "floor" : "live";
|
|
946
|
+
provenance = {
|
|
947
|
+
...versions.baseline === void 0 ? {} : { versions: versions.baseline },
|
|
948
|
+
...guides === void 0 ? {} : { guides },
|
|
949
|
+
...host === void 0 ? {} : { host }
|
|
950
|
+
};
|
|
951
|
+
const written = this.#merge(this.#publish(materializer, target, fetched.entries, fetched.mirrors), materializer.declare(versions.pins, target));
|
|
952
|
+
const floors = [];
|
|
953
|
+
if (hostForced) floors.push("host");
|
|
954
|
+
if (versions.forced) floors.push("versions");
|
|
955
|
+
if (guides === "floor") floors.push("guides");
|
|
841
956
|
return {
|
|
842
|
-
...
|
|
957
|
+
...written,
|
|
843
958
|
entries: fetched.entries,
|
|
844
959
|
mirrors: fetched.mirrors,
|
|
845
960
|
dropped: previous.filter((name) => !fetched.entries.some((entry) => entry.name === name)),
|
|
846
|
-
releases
|
|
961
|
+
releases,
|
|
962
|
+
provenance,
|
|
963
|
+
...floors.length === 0 ? {} : { note: `The ${floors.join(", ")} step used the distributed floor after its upstream read did not complete.` }
|
|
847
964
|
};
|
|
848
965
|
} catch (error) {
|
|
849
966
|
return {
|
|
@@ -855,10 +972,104 @@ var CLI = class CLI {
|
|
|
855
972
|
mirrors: [],
|
|
856
973
|
dropped: [],
|
|
857
974
|
releases,
|
|
975
|
+
provenance,
|
|
858
976
|
note: `The catalog step did not complete: ${errorToEnvelope(error).error.message}`
|
|
859
977
|
};
|
|
860
978
|
}
|
|
861
979
|
}
|
|
980
|
+
async #host(from, target, offline) {
|
|
981
|
+
if (from !== void 0) return {
|
|
982
|
+
materializer: new Materializer({ host: from }),
|
|
983
|
+
forced: false
|
|
984
|
+
};
|
|
985
|
+
const floor = readHostFloor();
|
|
986
|
+
if (offline) return {
|
|
987
|
+
materializer: new Materializer({ host: floor }),
|
|
988
|
+
baseline: "floor",
|
|
989
|
+
forced: false
|
|
990
|
+
};
|
|
991
|
+
const paths = floor.manifest.entries.filter((entry) => !isDeferredPath(entry.destination)).map((entry) => entry.destination);
|
|
992
|
+
const current = target === void 0 ? floor.bytes : readSnapshot(target, paths);
|
|
993
|
+
const upstream = new Upstream(this.#upstream);
|
|
994
|
+
try {
|
|
995
|
+
const files = await upstream.read(paths, current);
|
|
996
|
+
const live = filesToHost(files, floor);
|
|
997
|
+
return {
|
|
998
|
+
materializer: new Materializer({ host: live ?? floor }),
|
|
999
|
+
baseline: live === void 0 ? "floor" : "live",
|
|
1000
|
+
forced: live === void 0
|
|
1001
|
+
};
|
|
1002
|
+
} finally {
|
|
1003
|
+
upstream.destroy();
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
async #versions(declared, offline) {
|
|
1007
|
+
if (declared.length === 0) return {
|
|
1008
|
+
releases: [],
|
|
1009
|
+
pins: [],
|
|
1010
|
+
forced: false,
|
|
1011
|
+
complete: true
|
|
1012
|
+
};
|
|
1013
|
+
const floors = dependenciesToFloors(declared);
|
|
1014
|
+
if (offline) {
|
|
1015
|
+
if (floors === void 0) return {
|
|
1016
|
+
releases: [],
|
|
1017
|
+
pins: [],
|
|
1018
|
+
baseline: "floor",
|
|
1019
|
+
forced: false,
|
|
1020
|
+
complete: false
|
|
1021
|
+
};
|
|
1022
|
+
return {
|
|
1023
|
+
releases: floors,
|
|
1024
|
+
pins: floors.map((release) => ({
|
|
1025
|
+
name: release.name,
|
|
1026
|
+
range: release.range
|
|
1027
|
+
})),
|
|
1028
|
+
baseline: "floor",
|
|
1029
|
+
forced: false,
|
|
1030
|
+
complete: true
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
const releases = await this.#lookup(declared);
|
|
1034
|
+
if (releases.filter((release) => release.lookup === "missing" || release.lookup === "unmatched").length > 0) return {
|
|
1035
|
+
releases,
|
|
1036
|
+
pins: [],
|
|
1037
|
+
baseline: "live",
|
|
1038
|
+
forced: false,
|
|
1039
|
+
complete: false
|
|
1040
|
+
};
|
|
1041
|
+
if (releases.some((release) => release.lookup === "failed")) {
|
|
1042
|
+
if (floors === void 0) return {
|
|
1043
|
+
releases,
|
|
1044
|
+
pins: [],
|
|
1045
|
+
baseline: "floor",
|
|
1046
|
+
forced: true,
|
|
1047
|
+
complete: false
|
|
1048
|
+
};
|
|
1049
|
+
return {
|
|
1050
|
+
releases,
|
|
1051
|
+
pins: floors.map((release) => ({
|
|
1052
|
+
name: release.name,
|
|
1053
|
+
range: release.range
|
|
1054
|
+
})),
|
|
1055
|
+
baseline: "floor",
|
|
1056
|
+
forced: true,
|
|
1057
|
+
complete: true
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
return {
|
|
1061
|
+
releases,
|
|
1062
|
+
pins: this.#pin(releases),
|
|
1063
|
+
baseline: "live",
|
|
1064
|
+
forced: false,
|
|
1065
|
+
complete: true
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
#assertVersions(versions) {
|
|
1069
|
+
if (versions.complete) return;
|
|
1070
|
+
const names = versions.releases.filter((release) => release.lookup !== "found").map((release) => release.name);
|
|
1071
|
+
throw new ScaffoldError("FETCH", names.length === 0 ? "A declared dependency names no concrete floor." : `The registry named no release for ${names.join(", ")}.`, { names: names.length });
|
|
1072
|
+
}
|
|
862
1073
|
async #lookup(declared) {
|
|
863
1074
|
if (declared.length === 0) return [];
|
|
864
1075
|
const upstream = new Upstream(this.#upstream);
|
|
@@ -921,7 +1132,7 @@ var CLI = class CLI {
|
|
|
921
1132
|
});
|
|
922
1133
|
}
|
|
923
1134
|
#assertFetched(entries, mirrors) {
|
|
924
|
-
const failed = [...entries.filter((entry) => entry.lookup !== "found").map((entry) => entry.name), ...mirrors.filter((mirror) => mirror.lookup !== "found").map((mirror) => mirror.name)];
|
|
1135
|
+
const failed = [...entries.filter((entry) => entry.lookup !== "found").map((entry) => entry.name), ...mirrors.filter((mirror) => mirror.lookup !== "found" && mirror.lookup !== "failed").map((mirror) => mirror.name)];
|
|
925
1136
|
if (failed.length === 0) return;
|
|
926
1137
|
throw new ScaffoldError("FETCH", `Upstream produced no complete catalog answer for ${failed.join(", ")}.`, { names: failed.length });
|
|
927
1138
|
}
|
|
@@ -1255,7 +1466,7 @@ var CLI = class CLI {
|
|
|
1255
1466
|
}
|
|
1256
1467
|
return names;
|
|
1257
1468
|
}
|
|
1258
|
-
#
|
|
1469
|
+
#worktree(target) {
|
|
1259
1470
|
const tracked = this.#inventory(target, ["ls-files", "-z"]);
|
|
1260
1471
|
const dirty = this.#inventory(target, [
|
|
1261
1472
|
"status",
|
|
@@ -1267,7 +1478,7 @@ var CLI = class CLI {
|
|
|
1267
1478
|
tracked,
|
|
1268
1479
|
dirty
|
|
1269
1480
|
};
|
|
1270
|
-
if (!
|
|
1481
|
+
if (!isWorktree(state)) throw new ScaffoldError("TARGET", `The git state at ${target} is not a readable inventory.`, {
|
|
1271
1482
|
target,
|
|
1272
1483
|
tracked: tracked.length,
|
|
1273
1484
|
dirty: dirty.length
|
|
@@ -1315,6 +1526,13 @@ var CLI = class CLI {
|
|
|
1315
1526
|
removed: [...first.removed, ...second.removed]
|
|
1316
1527
|
};
|
|
1317
1528
|
}
|
|
1529
|
+
#reportBaselines(provenance) {
|
|
1530
|
+
const baselines = [];
|
|
1531
|
+
if (provenance.versions !== void 0) baselines.push(`versions=${provenance.versions}`);
|
|
1532
|
+
if (provenance.guides !== void 0) baselines.push(`guides=${provenance.guides}`);
|
|
1533
|
+
if (provenance.host !== void 0) baselines.push(`host=${provenance.host}`);
|
|
1534
|
+
this.#warn(`Upstream fallback selected the distributed baseline: ${baselines.join(", ")}.`);
|
|
1535
|
+
}
|
|
1318
1536
|
#present(audit) {
|
|
1319
1537
|
for (const question of audit.questions) this.#warn(`${question.field}: ${question.message}`);
|
|
1320
1538
|
const rows = audit.findings.filter((finding) => finding.drift !== "aligned").map((finding) => [
|
|
@@ -1393,7 +1611,7 @@ process.stdout.on("error", (error) => {
|
|
|
1393
1611
|
if ("code" in error && error.code === "EPIPE") return;
|
|
1394
1612
|
throw error;
|
|
1395
1613
|
});
|
|
1396
|
-
process.exitCode = await new CLI(
|
|
1614
|
+
process.exitCode = await new CLI({ upstream: environmentToUpstream(process.env) }).execute(process.argv.slice(2));
|
|
1397
1615
|
//#endregion
|
|
1398
1616
|
|
|
1399
1617
|
//# sourceMappingURL=main.js.map
|