@orkestrel/scaffold 0.0.44 → 0.0.45
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 +10 -10
- package/dist/bin/main.js +31 -31
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +7 -2
- package/dist/host/agents/orchestration.md +232 -56
- package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +7 -7
- package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +11 -9
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +3 -3
- package/dist/host/agents/skills/enterprise-bootstrap/references/frontend-design.md +3 -3
- package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +1 -1
- package/dist/host/agents/skills/orkestrel-align-packages/SKILL.md +1 -1
- package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +2 -2
- package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +8 -8
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +16 -14
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +3 -3
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +14 -14
- package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +1 -1
- package/dist/host/agents/skills/orkestrel-human-journey/SKILL.md +3 -3
- package/dist/host/agents/skills/orkestrel-human-journey/references/captures.md +3 -3
- package/dist/host/agents/skills/orkestrel-human-journey/references/layer.md +3 -3
- package/dist/host/agents/skills/orkestrel-polish-surface/SKILL.md +3 -3
- package/dist/host/claude/agents/analyst.md +2 -2
- package/dist/host/claude/agents/checker.md +2 -2
- package/dist/host/claude/agents/codex.md +5 -5
- package/dist/host/claude/agents/orkestrel.md +9 -8
- package/dist/host/claude/agents/planner.md +1 -1
- package/dist/host/claude/agents/researcher.md +2 -2
- package/dist/host/claude/agents/reviewer.md +1 -1
- package/dist/host/claude/agents/scout.md +2 -2
- package/dist/host/claude/agents/sol.md +3 -3
- package/dist/host/claude/agents/verifier.md +8 -0
- package/dist/host/claude/rules/application.md +7 -7
- package/dist/host/claude/rules/architecture.md +6 -6
- package/dist/host/claude/rules/documentation.md +1 -0
- package/dist/host/claude/rules/patterns.md +3 -3
- package/dist/host/claude/rules/quality.md +3 -3
- package/dist/host/claude/rules/tests.md +9 -2
- package/dist/host/claude/rules/workspace.md +7 -7
- package/dist/host/claude/rules/writing.md +12 -2
- package/dist/host/codex/agents/planner.toml +1 -1
- package/dist/host/configs/helpers.ts +21 -1
- package/dist/host/cursor/rules/orchestration.mdc +1 -1
- package/dist/host/dotfiles/gitignore +4 -1
- package/dist/host/guides/scaffold.md +134 -119
- package/dist/host/scripts/codex.sh +0 -0
- package/dist/host/scripts/cursor.sh +0 -0
- package/dist/host/scripts/deps.sh +0 -0
- package/dist/host/scripts/ollama.sh +0 -0
- package/dist/host/tests/config.test.ts +40 -1
- package/dist/host/tests/policy.test.ts +2 -2
- package/dist/host/tests/setupPolicy.ts +8 -5
- package/dist/src/core/index.cjs +143 -149
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +1624 -1643
- package/dist/src/core/index.d.ts +1624 -1643
- package/dist/src/core/index.js +144 -149
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +82 -97
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +1844 -1871
- package/dist/src/server/index.d.ts +1844 -1871
- package/dist/src/server/index.js +83 -96
- package/dist/src/server/index.js.map +1 -1
- package/package.json +3 -3
package/dist/src/server/index.js
CHANGED
|
@@ -38,7 +38,7 @@ var RESERVED_SEGMENT_PATTERN = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9]|conin\$|co
|
|
|
38
38
|
*
|
|
39
39
|
* @remarks
|
|
40
40
|
* Fixed length, unlike the core byte encoding, because a digest is one value of
|
|
41
|
-
* one algorithm rather than a variable run of bytes. Lowercase only, so
|
|
41
|
+
* one algorithm rather than a variable run of bytes. Lowercase only, so separate
|
|
42
42
|
* spellings of one digest can never compare unequal.
|
|
43
43
|
*/
|
|
44
44
|
var DIGEST_PATTERN = /^[0-9a-f]{64}$/;
|
|
@@ -130,7 +130,7 @@ var MANIFEST_NAME = "manifest.json";
|
|
|
130
130
|
* the byte ceiling. The character ceiling is read first so an oversized string is
|
|
131
131
|
* refused before it is split.
|
|
132
132
|
*
|
|
133
|
-
* The
|
|
133
|
+
* The spellings of an empty segment are answered differently. A trailing
|
|
134
134
|
* separator terminates a directory rather than opening a segment, and every
|
|
135
135
|
* supported filesystem and every Node path API reads `project/` and `project` as
|
|
136
136
|
* one location, so it is admitted. A doubled separator is a genuine empty
|
|
@@ -198,7 +198,7 @@ var isDigest = stringOf({ pattern: DIGEST_PATTERN });
|
|
|
198
198
|
* composed, and for the same reason: the item count is settled before anything
|
|
199
199
|
* walks the items, and a hostile `length` accessor answers `false` rather than
|
|
200
200
|
* escaping as a throw. It exists beside that guard rather than reusing it
|
|
201
|
-
* because
|
|
201
|
+
* because they bound different things — one bounds what a caller may hand a
|
|
202
202
|
* public method, this one bounds what a checkout may contain.
|
|
203
203
|
*
|
|
204
204
|
* @example
|
|
@@ -366,8 +366,8 @@ var isMaterializerOptions = recordOf({
|
|
|
366
366
|
* Narrow a value to the upstream reader's initial listener record.
|
|
367
367
|
*
|
|
368
368
|
* @remarks
|
|
369
|
-
* Closed to the reader's own
|
|
370
|
-
* record is closed to its
|
|
369
|
+
* Closed to the reader's own events for the same reason the materializer's
|
|
370
|
+
* record is closed to its own.
|
|
371
371
|
*/
|
|
372
372
|
var isUpstreamHooks = recordOf({
|
|
373
373
|
release: isFunction,
|
|
@@ -383,7 +383,7 @@ var isUpstreamHooks = recordOf({
|
|
|
383
383
|
* the wrong entity is refused rather than ignored. Every numeric leaf is a whole
|
|
384
384
|
* number inside a ceiling: an unbounded concurrency, retry count, response
|
|
385
385
|
* limit, or call budget is a way to exhaust the caller, so the ceiling is stated
|
|
386
|
-
* here rather than left to the reader. The
|
|
386
|
+
* here rather than left to the reader. The byte ceilings are the core
|
|
387
387
|
* artifact and total-artifact limits, because a fetched guide is an artifact and
|
|
388
388
|
* a whole call retains no more than a whole plan.
|
|
389
389
|
*
|
|
@@ -423,7 +423,7 @@ var isUpstreamOptions = recordOf({
|
|
|
423
423
|
* @remarks
|
|
424
424
|
* The one place absence is told apart from failure. Every read here answers
|
|
425
425
|
* `undefined` or an empty result for a path that is not there and reports a path
|
|
426
|
-
* that is there but unreadable, so
|
|
426
|
+
* that is there but unreadable, so they must never be read from the same
|
|
427
427
|
* caught value by eye. Total for any caught value, including a hostile one.
|
|
428
428
|
*
|
|
429
429
|
* @example
|
|
@@ -444,7 +444,7 @@ function matchesMissingPath(error) {
|
|
|
444
444
|
* @returns `true` for `.git` and for anything beneath it.
|
|
445
445
|
*
|
|
446
446
|
* @remarks
|
|
447
|
-
* The one home of the `.git` membership rule, read
|
|
447
|
+
* The one home of the `.git` membership rule, read in either direction. A target
|
|
448
448
|
* holding nothing but this directory is still vacant, because a checkout of an
|
|
449
449
|
* empty repository is where a fresh workspace legitimately starts. A path
|
|
450
450
|
* beneath it is never removed and never vendored, because deleting a target's
|
|
@@ -471,11 +471,13 @@ function matchesGitPath(path) {
|
|
|
471
471
|
* @remarks
|
|
472
472
|
* The deletion deny-list, stated as a rule over paths rather than as a list of
|
|
473
473
|
* directories. It is the inversion the contract asks for: the candidate set
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
* because losing history is not a repair,
|
|
477
|
-
*
|
|
478
|
-
*
|
|
474
|
+
* is re-derived from the plan and narrowed by what git tracks, and the audit
|
|
475
|
+
* must agree with that derivation rather than supply the set itself.
|
|
476
|
+
* Repository metadata is protected because losing history is not a repair,
|
|
477
|
+
* and a target's own `src` and `app` trees are protected because a
|
|
478
|
+
* workspace's source is the one thing scaffold never plans and never owns. A
|
|
479
|
+
* plan the compiler emits never maps a protected root, so this guard exists
|
|
480
|
+
* for the caller-authored plan a consumer can still supply.
|
|
479
481
|
*
|
|
480
482
|
* @example
|
|
481
483
|
* ```ts
|
|
@@ -610,7 +612,7 @@ function computeDigest(content) {
|
|
|
610
612
|
* detect a membership edit that did not update it. Order is part of the claim
|
|
611
613
|
* rather than normalized away, because a staged manifest sorts its entries and
|
|
612
614
|
* roots once and a reordered copy is a different file. Each entry is projected
|
|
613
|
-
* to exactly the
|
|
615
|
+
* to exactly the declared fields, so a hand-added property cannot ride
|
|
614
616
|
* into the digest and cannot change it either.
|
|
615
617
|
*
|
|
616
618
|
* @example
|
|
@@ -699,8 +701,8 @@ function isExactCaseFile(path) {
|
|
|
699
701
|
* @returns `true` only for a directory that is not a link.
|
|
700
702
|
*
|
|
701
703
|
* @remarks
|
|
702
|
-
* A junction and a directory symbolic link both report as directories
|
|
703
|
-
* followed, so the inspection deliberately does not follow: a redirected
|
|
704
|
+
* A junction and a directory symbolic link both report as directories after
|
|
705
|
+
* they are followed, so the inspection deliberately does not follow: a redirected
|
|
704
706
|
* directory is refused here rather than silently accepted as the one the caller
|
|
705
707
|
* named.
|
|
706
708
|
*
|
|
@@ -1124,7 +1126,7 @@ function listDirectories(root) {
|
|
|
1124
1126
|
* snapshot all compare as the same digits. The file's identity and size are
|
|
1125
1127
|
* measured before and after the read, and one extra byte is requested past the
|
|
1126
1128
|
* declared size, so a file that grew or was replaced mid-read answers
|
|
1127
|
-
* `undefined` rather than half of
|
|
1129
|
+
* `undefined` rather than half of one file and half of another.
|
|
1128
1130
|
*
|
|
1129
1131
|
* @example
|
|
1130
1132
|
* ```ts
|
|
@@ -1213,7 +1215,7 @@ function readFileText(root, path, limit = MAX_ARTIFACT_BYTES) {
|
|
|
1213
1215
|
* The one door from a real directory into the vocabulary an audit compares in.
|
|
1214
1216
|
* Absence is omission rather than an empty value, because core reads a missing
|
|
1215
1217
|
* key as a missing destination and an empty string as a present directory; the
|
|
1216
|
-
*
|
|
1218
|
+
* they are different verdicts. A path that is there but unreadable throws instead
|
|
1217
1219
|
* of being omitted, because omission would report it as missing and a repair
|
|
1218
1220
|
* would then overwrite whatever is actually sitting there.
|
|
1219
1221
|
*
|
|
@@ -1273,7 +1275,7 @@ function readSnapshot(target, paths) {
|
|
|
1273
1275
|
* read, is not the declared shape, or does not match its own membership.
|
|
1274
1276
|
*
|
|
1275
1277
|
* @remarks
|
|
1276
|
-
* The
|
|
1278
|
+
* The failures are held apart deliberately. A host with no manifest is a
|
|
1277
1279
|
* raw checkout, and a caller reads it by mapping each path one to one. A host
|
|
1278
1280
|
* with a manifest that does not verify is a staged host that has been edited,
|
|
1279
1281
|
* and answering `undefined` there would degrade it to that same one-to-one
|
|
@@ -1321,8 +1323,8 @@ function readHostManifest(host) {
|
|
|
1321
1323
|
* package will vendor or carries more bytes than one artifact may.
|
|
1322
1324
|
*
|
|
1323
1325
|
* @remarks
|
|
1324
|
-
* The one place the
|
|
1325
|
-
*
|
|
1326
|
+
* The one place the declared fields are decided together, because they are
|
|
1327
|
+
* readings of one path: {@link pathToStorage} decides where it is stored,
|
|
1326
1328
|
* the destination is the path it answers for, and {@link matchesExecutablePath}
|
|
1327
1329
|
* decides whether a target receives it executable.
|
|
1328
1330
|
*
|
|
@@ -1371,7 +1373,7 @@ function readManifestEntry(destination, source) {
|
|
|
1371
1373
|
* every destination to what the caller observed, and rolls a failed commit back.
|
|
1372
1374
|
* This reads this package's own checkout at build time and fills its own build
|
|
1373
1375
|
* output. Different direction, different lifetime, no consumer target involved,
|
|
1374
|
-
* so
|
|
1376
|
+
* so they do not overlap and neither one belongs inside the other.
|
|
1375
1377
|
*
|
|
1376
1378
|
* Staging is plain rather than transactional for the same reason. A
|
|
1377
1379
|
* `WriteTransaction` exists to hold a directory that already holds work
|
|
@@ -1545,7 +1547,7 @@ function readAnchor(path) {
|
|
|
1545
1547
|
* @remarks
|
|
1546
1548
|
* This binds location rather than history. `true` means the path still resolves
|
|
1547
1549
|
* to the same physical directory on the same device, so the next write lands
|
|
1548
|
-
* where the last one did. A path
|
|
1550
|
+
* where the last one did. A path holding nothing, a file, or a symlink
|
|
1549
1551
|
* answers `false`; a directory swapped in by `rename` also answers `false`
|
|
1550
1552
|
* because the replacement carries its own inode. A directory deleted and made
|
|
1551
1553
|
* again under the same name can receive the old inode back and answers `true`,
|
|
@@ -1616,7 +1618,7 @@ function readExpectation(path) {
|
|
|
1616
1618
|
* Test whether a destination still holds what was captured of it.
|
|
1617
1619
|
*
|
|
1618
1620
|
* @param expectation - The state captured earlier.
|
|
1619
|
-
* @returns `true` when re-reading the destination
|
|
1621
|
+
* @returns `true` when re-reading the destination produces that same state.
|
|
1620
1622
|
*
|
|
1621
1623
|
* @remarks
|
|
1622
1624
|
* Compared field for field against a fresh {@link readExpectation}, so an
|
|
@@ -1677,7 +1679,7 @@ function matchesPrecondition(precondition) {
|
|
|
1677
1679
|
* has not touched the target at all. Commit is the only step that mutates the
|
|
1678
1680
|
* target, and it is the only step that can need rolling back.
|
|
1679
1681
|
*
|
|
1680
|
-
*
|
|
1682
|
+
* A precondition and an expectation hold a destination still. A **precondition** is what the caller
|
|
1681
1683
|
* observed earlier and is checked once, at construction, so a target that moved
|
|
1682
1684
|
* between the caller's read and this transaction fails before anything is
|
|
1683
1685
|
* created. An **expectation** is captured here, at construction, and re-checked
|
|
@@ -1701,7 +1703,7 @@ function matchesPrecondition(precondition) {
|
|
|
1701
1703
|
* elsewhere, or nothing is refused. An ancestor deleted and recreated under
|
|
1702
1704
|
* the same name can receive its old inode back and is indistinguishable here
|
|
1703
1705
|
* from one that never moved.
|
|
1704
|
-
* - **No crash atomicity across destinations.** A process killed between
|
|
1706
|
+
* - **No crash atomicity across destinations.** A process killed between
|
|
1705
1707
|
* promotions leaves the target holding some new files and some old ones, and
|
|
1706
1708
|
* leaves the private root behind. Nothing here is a journal, and the private
|
|
1707
1709
|
* root's name is the only record a later run could read.
|
|
@@ -1834,7 +1836,7 @@ var WriteTransaction = class {
|
|
|
1834
1836
|
* Stage one text file.
|
|
1835
1837
|
*
|
|
1836
1838
|
* @param path - The target-relative path to write.
|
|
1837
|
-
* @param content - The exact UTF-8 text the destination
|
|
1839
|
+
* @param content - The exact UTF-8 text the destination must hold.
|
|
1838
1840
|
* @returns Nothing.
|
|
1839
1841
|
* @throws {@link ScaffoldError} coded `INVALID` when the path is not one this
|
|
1840
1842
|
* transaction opened or is already staged, `TARGET` when the destination holds
|
|
@@ -1866,7 +1868,7 @@ var WriteTransaction = class {
|
|
|
1866
1868
|
*
|
|
1867
1869
|
* @param path - The target-relative path to write.
|
|
1868
1870
|
* @param source - The resolved absolute path to copy the bytes from.
|
|
1869
|
-
* @param executable -
|
|
1871
|
+
* @param executable - If `true`, the destination carries the executable bit; if `false`, it does not.
|
|
1870
1872
|
* @returns Nothing.
|
|
1871
1873
|
* @throws {@link ScaffoldError} coded `INVALID` when the path is not one this
|
|
1872
1874
|
* transaction opened or is already staged, `TARGET` when the destination holds
|
|
@@ -1916,7 +1918,7 @@ var WriteTransaction = class {
|
|
|
1916
1918
|
* created segment is captured by device and inode, so a segment swapped
|
|
1917
1919
|
* underneath the transaction is detected rather than written into.
|
|
1918
1920
|
*/
|
|
1919
|
-
|
|
1921
|
+
establish(path) {
|
|
1920
1922
|
this.#assertOpen();
|
|
1921
1923
|
if (this.#expectation(path).shape === "file") throw new ScaffoldError("TARGET", `The destination at ${path} holds a file.`, { path });
|
|
1922
1924
|
const established = attempt(() => this.#establish(this.#resolve(this.#target, path)));
|
|
@@ -2179,7 +2181,7 @@ var WriteTransaction = class {
|
|
|
2179
2181
|
* The mutation spine: read the vendored host, re-derive the target, stage, swap.
|
|
2180
2182
|
*
|
|
2181
2183
|
* @remarks
|
|
2182
|
-
* Every verb runs the same
|
|
2184
|
+
* Every verb runs the same steps. It snapshots each caller-supplied value
|
|
2183
2185
|
* and guards the snapshot, so a property backed by an accessor never reaches a
|
|
2184
2186
|
* decision. It re-derives what it is about to touch and compares that against
|
|
2185
2187
|
* the observation the caller handed in, refusing the whole call when anything
|
|
@@ -2402,7 +2404,7 @@ var Materializer = class Materializer {
|
|
|
2402
2404
|
/**
|
|
2403
2405
|
* Rewrite the marker-bounded package table in the target's catalog agent file.
|
|
2404
2406
|
*
|
|
2405
|
-
* @param entries - The published packages the table
|
|
2407
|
+
* @param entries - The published packages the table must list.
|
|
2406
2408
|
* @param target - The directory to write into.
|
|
2407
2409
|
* @returns The catalog path, written when the region's bytes moved and skipped otherwise.
|
|
2408
2410
|
* @throws {@link ScaffoldError} coded `INVALID` when an argument is not the
|
|
@@ -2411,7 +2413,7 @@ var Materializer = class Materializer {
|
|
|
2411
2413
|
* `DESTROYED` after teardown.
|
|
2412
2414
|
*
|
|
2413
2415
|
* @remarks
|
|
2414
|
-
* Only the text between the
|
|
2416
|
+
* Only the text between the markers is replaced, so every word a consumer
|
|
2415
2417
|
* wrote around the table survives the call. A row whose lookup produced no
|
|
2416
2418
|
* version prints the cause it carries instead, because dropping the row would
|
|
2417
2419
|
* hide a package the organization publishes behind one failed request.
|
|
@@ -2425,7 +2427,7 @@ var Materializer = class Materializer {
|
|
|
2425
2427
|
/**
|
|
2426
2428
|
* Rewrite the `@orkestrel/*` range set in the target's manifest.
|
|
2427
2429
|
*
|
|
2428
|
-
* @param dependencies - The names and ranges the manifest
|
|
2430
|
+
* @param dependencies - The names and ranges the manifest must declare.
|
|
2429
2431
|
* @param target - The directory to write into.
|
|
2430
2432
|
* @returns The manifest path, written when a declared range moved and skipped otherwise.
|
|
2431
2433
|
* @throws {@link ScaffoldError} coded `INVALID` when an argument is not the
|
|
@@ -2447,9 +2449,10 @@ var Materializer = class Materializer {
|
|
|
2447
2449
|
return this.#rewrite(directory, "package.json", MAX_MANIFEST_BYTES, this.#redeclare(accepted));
|
|
2448
2450
|
}
|
|
2449
2451
|
/**
|
|
2450
|
-
*
|
|
2452
|
+
* Re-derive and delete the tracked files the plan does not own.
|
|
2451
2453
|
*
|
|
2452
|
-
* @param
|
|
2454
|
+
* @param plan - The compiled plan that decides which paths are foreign.
|
|
2455
|
+
* @param audit - The preview returned by this materializer's `audit` method; it must agree with the candidate set this call re-derives.
|
|
2453
2456
|
* @param repository - The target's git state; only a tracked path is ever deleted.
|
|
2454
2457
|
* @param target - The directory to delete from.
|
|
2455
2458
|
* @returns The paths removed.
|
|
@@ -2466,9 +2469,14 @@ var Materializer = class Materializer {
|
|
|
2466
2469
|
* the audit reports, and neither is anything git does not track: git is the
|
|
2467
2470
|
* recovery mechanism, so a path it cannot restore is not one this verb takes.
|
|
2468
2471
|
* A tree carrying uncommitted work is refused whole for the same reason.
|
|
2472
|
+
*
|
|
2473
|
+
* The whole call refuses when the preview disagrees with the re-derivation on
|
|
2474
|
+
* any foreign finding, including one the deletion itself would skip, because a
|
|
2475
|
+
* preview stale anywhere is stale evidence.
|
|
2469
2476
|
*/
|
|
2470
|
-
remove(audit, repository, target) {
|
|
2477
|
+
remove(plan, audit, repository, target) {
|
|
2471
2478
|
this.#assertAlive();
|
|
2479
|
+
const accepted = this.#accept(plan, isPlan, "plan");
|
|
2472
2480
|
const preview = this.#accept(audit, isAudit, "audit");
|
|
2473
2481
|
const state = this.#accept(repository, isRepository, "repository");
|
|
2474
2482
|
const directory = this.#accept(target, isFilesystemPath, "target");
|
|
@@ -2476,28 +2484,21 @@ var Materializer = class Materializer {
|
|
|
2476
2484
|
target: directory,
|
|
2477
2485
|
dirty: state.dirty.length
|
|
2478
2486
|
});
|
|
2487
|
+
const derived = this.#derive(accepted, directory);
|
|
2488
|
+
this.#reconfirmCandidates(derived.findings, preview.findings, directory);
|
|
2479
2489
|
const tracked = new Set(state.tracked);
|
|
2480
|
-
const observed = /* @__PURE__ */ new Map();
|
|
2481
2490
|
const removals = [];
|
|
2482
2491
|
const skipped = [];
|
|
2483
|
-
for (const finding of
|
|
2492
|
+
for (const finding of derived.findings) {
|
|
2484
2493
|
if (finding.drift !== "foreign") continue;
|
|
2485
2494
|
if (!tracked.has(finding.path) || matchesProtectedPath(finding.path)) {
|
|
2486
2495
|
skipped.push(finding.path);
|
|
2487
2496
|
continue;
|
|
2488
2497
|
}
|
|
2489
|
-
observed.set(finding.path, finding.observed);
|
|
2490
2498
|
removals.push(finding.path);
|
|
2491
2499
|
}
|
|
2492
|
-
const current = readSnapshot(directory, removals);
|
|
2493
2500
|
const preconditions = [];
|
|
2494
|
-
for (const path of removals)
|
|
2495
|
-
if (current[path] !== observed.get(path)) throw this.#error("TARGET", `The path ${path} moved since its audit.`, {
|
|
2496
|
-
target: directory,
|
|
2497
|
-
path
|
|
2498
|
-
});
|
|
2499
|
-
preconditions.push(this.#bind(directory, path, false));
|
|
2500
|
-
}
|
|
2501
|
+
for (const path of removals) preconditions.push(this.#bind(directory, path, false));
|
|
2501
2502
|
return this.#purge(directory, removals, skipped, preconditions);
|
|
2502
2503
|
}
|
|
2503
2504
|
/**
|
|
@@ -2728,6 +2729,35 @@ var Materializer = class Materializer {
|
|
|
2728
2729
|
});
|
|
2729
2730
|
}
|
|
2730
2731
|
}
|
|
2732
|
+
#reconfirmCandidates(derived, preview, target) {
|
|
2733
|
+
const current = derived.filter((finding) => finding.drift === "foreign");
|
|
2734
|
+
const supplied = preview.filter((finding) => finding.drift === "foreign");
|
|
2735
|
+
const candidates = new Map(current.map((finding) => [finding.path, finding]));
|
|
2736
|
+
const previewed = new Map(supplied.map((finding) => [finding.path, finding]));
|
|
2737
|
+
if (candidates.size !== current.length || previewed.size !== supplied.length) throw this.#error("TARGET", "The audit repeats a deletion candidate.", { target });
|
|
2738
|
+
for (const finding of supplied) {
|
|
2739
|
+
const candidate = candidates.get(finding.path);
|
|
2740
|
+
if (candidate === void 0) throw this.#error("TARGET", `The path ${finding.path} is not a deletion candidate for this plan.`, {
|
|
2741
|
+
target,
|
|
2742
|
+
path: finding.path
|
|
2743
|
+
});
|
|
2744
|
+
if (candidate.group !== finding.group) throw this.#error("TARGET", `The path ${finding.path} carries a group this plan does not derive.`, {
|
|
2745
|
+
target,
|
|
2746
|
+
path: finding.path
|
|
2747
|
+
});
|
|
2748
|
+
if (candidate.observed !== finding.observed) throw this.#error("TARGET", `The path ${finding.path} moved since its audit.`, {
|
|
2749
|
+
target,
|
|
2750
|
+
path: finding.path
|
|
2751
|
+
});
|
|
2752
|
+
}
|
|
2753
|
+
for (const finding of current) {
|
|
2754
|
+
if (previewed.has(finding.path)) continue;
|
|
2755
|
+
throw this.#error("TARGET", `The path ${finding.path} is not covered by its audit.`, {
|
|
2756
|
+
target,
|
|
2757
|
+
path: finding.path
|
|
2758
|
+
});
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2731
2761
|
#bind(target, path, absent) {
|
|
2732
2762
|
const destination = resolveContainedPath(target, path);
|
|
2733
2763
|
if (destination === void 0) throw this.#error("INVALID", `The path ${path} is off contract or leaves its target.`, {
|
|
@@ -2782,7 +2812,7 @@ var Materializer = class Materializer {
|
|
|
2782
2812
|
const staged = attempt(() => {
|
|
2783
2813
|
for (const artifact of writes) if (artifact.origin === "host") this.#copy(transaction, artifact);
|
|
2784
2814
|
else transaction.write(artifact.path, artifact.content);
|
|
2785
|
-
for (const path of directories) transaction.
|
|
2815
|
+
for (const path of directories) transaction.establish(path);
|
|
2786
2816
|
});
|
|
2787
2817
|
const written = this.#close(transaction, staged, target);
|
|
2788
2818
|
for (const path of written) this.#emitter.emit("write", path);
|
|
@@ -2960,7 +2990,7 @@ var Materializer = class Materializer {
|
|
|
2960
2990
|
* This is the package's only network reader, and it never writes. Every call
|
|
2961
2991
|
* opens one byte allowance and spends it across every read the call makes, so a
|
|
2962
2992
|
* caller is bounded twice over: `limit` refuses one oversized answer and
|
|
2963
|
-
* `budget` refuses many small ones.
|
|
2993
|
+
* `budget` refuses many small ones. They are separate exhaustion routes and
|
|
2964
2994
|
* neither bound covers the other.
|
|
2965
2995
|
*
|
|
2966
2996
|
* A per-package failure never escapes as a throw. It is projected into the
|
|
@@ -3016,7 +3046,7 @@ var Upstream = class Upstream {
|
|
|
3016
3046
|
/**
|
|
3017
3047
|
* Construct a reader over one guide host and one registry.
|
|
3018
3048
|
*
|
|
3019
|
-
* @param options - The
|
|
3049
|
+
* @param options - The endpoints, the request bounds, the initial
|
|
3020
3050
|
* listeners, and the listener-error handler.
|
|
3021
3051
|
* @throws {@link ScaffoldError} coded `INVALID` when `options` is present but
|
|
3022
3052
|
* is not an option bag this reader accepts, or when either endpoint names a
|
|
@@ -3026,7 +3056,7 @@ var Upstream = class Upstream {
|
|
|
3026
3056
|
* `isEndpoint` bounds an endpoint's length and nothing else, so the scheme and
|
|
3027
3057
|
* host law is settled here, where a refusal can say which endpoint was refused
|
|
3028
3058
|
* and why. An endpoint must be HTTPS, or HTTP to a loopback host — the one
|
|
3029
|
-
* place an unencrypted request has no network between
|
|
3059
|
+
* place an unencrypted request has no network between its ends. That
|
|
3030
3060
|
* refuses `file:`, `data:`, and plain HTTP to a real host, and it is what
|
|
3031
3061
|
* keeps a fixture reachable without weakening transport security anywhere a
|
|
3032
3062
|
* real request goes. An endpoint carrying credentials, a query, or a fragment
|
|
@@ -3098,7 +3128,7 @@ var Upstream = class Upstream {
|
|
|
3098
3128
|
* always answers for the file it names. `observed` is carried through from
|
|
3099
3129
|
* `current` whatever the lookup produced, because it is the precondition the
|
|
3100
3130
|
* later write is held to and a failed fetch does not change what the target
|
|
3101
|
-
*
|
|
3131
|
+
* holds.
|
|
3102
3132
|
*
|
|
3103
3133
|
* @example
|
|
3104
3134
|
* ```ts
|
|
@@ -3458,49 +3488,6 @@ var Upstream = class Upstream {
|
|
|
3458
3488
|
}
|
|
3459
3489
|
};
|
|
3460
3490
|
//#endregion
|
|
3461
|
-
|
|
3462
|
-
/**
|
|
3463
|
-
* Construct a {@link Materializer}.
|
|
3464
|
-
*
|
|
3465
|
-
* @param options - The vendored host root, the initial listeners, and the listener-error handler.
|
|
3466
|
-
* @returns The materializer, typed as the contract consumers program against.
|
|
3467
|
-
* @throws {@link ScaffoldError} coded `INVALID` when `options` is present but is
|
|
3468
|
-
* not an option bag the materializer accepts, and `TARGET` when the host carries
|
|
3469
|
-
* a manifest that cannot be read or does not match what it stores.
|
|
3470
|
-
*
|
|
3471
|
-
* @example
|
|
3472
|
-
* ```ts
|
|
3473
|
-
* import { createMaterializer } from '@orkestrel/scaffold/server'
|
|
3474
|
-
*
|
|
3475
|
-
* const materializer = createMaterializer({ host: './dist/host' })
|
|
3476
|
-
* materializer.destroy()
|
|
3477
|
-
* ```
|
|
3478
|
-
*/
|
|
3479
|
-
function createMaterializer(options) {
|
|
3480
|
-
return new Materializer(options);
|
|
3481
|
-
}
|
|
3482
|
-
/**
|
|
3483
|
-
* Construct an {@link Upstream}.
|
|
3484
|
-
*
|
|
3485
|
-
* @param options - The two endpoints, the request bounds, the initial listeners,
|
|
3486
|
-
* and the listener-error handler.
|
|
3487
|
-
* @returns The reader, typed as the contract consumers program against.
|
|
3488
|
-
* @throws {@link ScaffoldError} coded `INVALID` when `options` is present but is
|
|
3489
|
-
* not an option bag the reader accepts, or when either endpoint names a scheme,
|
|
3490
|
-
* host, or form the reader will not request.
|
|
3491
|
-
*
|
|
3492
|
-
* @example
|
|
3493
|
-
* ```ts
|
|
3494
|
-
* import { createUpstream } from '@orkestrel/scaffold/server'
|
|
3495
|
-
*
|
|
3496
|
-
* const upstream = createUpstream({ guides: { branch: 'main' } })
|
|
3497
|
-
* upstream.destroy()
|
|
3498
|
-
* ```
|
|
3499
|
-
*/
|
|
3500
|
-
function createUpstream(options) {
|
|
3501
|
-
return new Upstream(options);
|
|
3502
|
-
}
|
|
3503
|
-
//#endregion
|
|
3504
|
-
export { BRANCH_PATTERN, DIGEST_PATTERN, DRIVE_PATTERN, INVALID_SEGMENT_CHARACTER_PATTERN, MANIFEST_NAME, MAX_BRANCH_LENGTH, MAX_ENDPOINT_LENGTH, MAX_INVENTORY_PATHS, MAX_PATH_DEPTH, MAX_PATH_SEGMENT_BYTES, MAX_UPSTREAM_CONCURRENCY, MAX_UPSTREAM_RETRIES, MAX_UPSTREAM_TIMEOUT, Materializer, RESERVED_SEGMENT_PATTERN, Upstream, WriteTransaction, computeDigest, computeFileDigest, computeManifestDigest, createMaterializer, createUpstream, isBranch, isCatalogEntries, isDependencies, isDependencyNames, isDigest, isEndpoint, isExactCaseFile, isFilesystemPath, isHostManifest, isInventory, isManifestEntry, isMaterializerHooks, isMaterializerOptions, isMirrors, isPhysicalDirectory, isPhysicalFile, isRepository, isTimeout, isUpstreamHooks, isUpstreamOptions, isVacant, listDirectories, listFiles, matchesAnchor, matchesExecutablePath, matchesExpectation, matchesGitPath, matchesMissingPath, matchesPrecondition, matchesProtectedPath, matchesSensitivePath, pathToStorage, readAnchor, readExpectation, readFileHex, readFileText, readHostManifest, readManifestEntry, readSnapshot, resolveContainedPath, resolveRealPath, stageHost };
|
|
3491
|
+
export { BRANCH_PATTERN, DIGEST_PATTERN, DRIVE_PATTERN, INVALID_SEGMENT_CHARACTER_PATTERN, MANIFEST_NAME, MAX_BRANCH_LENGTH, MAX_ENDPOINT_LENGTH, MAX_INVENTORY_PATHS, MAX_PATH_DEPTH, MAX_PATH_SEGMENT_BYTES, MAX_UPSTREAM_CONCURRENCY, MAX_UPSTREAM_RETRIES, MAX_UPSTREAM_TIMEOUT, Materializer, RESERVED_SEGMENT_PATTERN, Upstream, WriteTransaction, computeDigest, computeFileDigest, computeManifestDigest, isBranch, isCatalogEntries, isDependencies, isDependencyNames, isDigest, isEndpoint, isExactCaseFile, isFilesystemPath, isHostManifest, isInventory, isManifestEntry, isMaterializerHooks, isMaterializerOptions, isMirrors, isPhysicalDirectory, isPhysicalFile, isRepository, isTimeout, isUpstreamHooks, isUpstreamOptions, isVacant, listDirectories, listFiles, matchesAnchor, matchesExecutablePath, matchesExpectation, matchesGitPath, matchesMissingPath, matchesPrecondition, matchesProtectedPath, matchesSensitivePath, pathToStorage, readAnchor, readExpectation, readFileHex, readFileText, readHostManifest, readManifestEntry, readSnapshot, resolveContainedPath, resolveRealPath, stageHost };
|
|
3505
3492
|
|
|
3506
3493
|
//# sourceMappingURL=index.js.map
|