@orkestrel/scaffold 0.0.103 → 0.0.104
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/agents/skills/orkestrel-dispatch/scripts/helpers.js +84 -1
- package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +21 -6
- package/dist/agents/skills/orkestrel-harden/scripts/titles.js +338 -0
- package/dist/agents/skills/orkestrel-publish/scripts/swap.js +3 -39
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +433 -47
- package/dist/agents/skills/orkestrel-publish/scripts/window.js +2 -1
- package/dist/bin/main.js +16 -9
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/orchestration.md +3 -3
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +2 -2
- package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +1 -1
- package/dist/host/agents/skills/orkestrel-build/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +3 -3
- package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +10 -10
- package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +1 -0
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +100 -1
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +27 -6
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +4 -4
- package/dist/host/agents/skills/orkestrel-falsify/agents/openai.yaml +1 -1
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +8 -7
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +6 -6
- package/dist/host/agents/skills/orkestrel-harden/SKILL.md +6 -1
- package/dist/host/agents/skills/orkestrel-harden/references/bindings.md +1700 -0
- package/dist/host/agents/skills/orkestrel-harden/references/contract.md +2 -2
- package/dist/host/agents/skills/orkestrel-harden/references/equivalence.md +48 -0
- package/dist/host/agents/skills/orkestrel-harden/references/hardening.md +4 -2
- package/dist/host/agents/skills/orkestrel-harden/scripts/titles.ts +425 -0
- package/dist/host/agents/skills/orkestrel-journey/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-journey/references/captures.md +9 -8
- package/dist/host/agents/skills/orkestrel-polish/SKILL.md +3 -3
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-publish/references/release.md +1 -0
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +56 -13
- package/dist/host/agents/skills/orkestrel-publish/references/window.md +6 -6
- package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +5 -49
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +646 -49
- package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +2 -1
- package/dist/host/agents/transports/codex.md +1 -1
- package/dist/host/claude/agents/orkestrel.md +54 -53
- package/dist/host/claude/agents/reviewer.md +4 -4
- package/dist/host/claude/rules/documentation.md +2 -1
- package/dist/host/claude/rules/patterns.md +1 -1
- package/dist/host/claude/rules/quality.md +2 -2
- package/dist/host/claude/rules/styles.md +1 -1
- package/dist/host/claude/rules/tests.md +34 -8
- package/dist/host/claude/rules/typescript.md +29 -0
- package/dist/host/claude/rules/workspace.md +32 -22
- package/dist/host/claude/rules/writing.md +34 -26
- package/dist/host/claude/settings.json +2 -0
- package/dist/host/claude/skills/orkestrel-debrief/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-falsify/SKILL.md +1 -1
- package/dist/host/codex/agents/analyst.toml +3 -3
- package/dist/host/codex/agents/reviewer.toml +4 -4
- package/dist/host/configs/policy.ts +13 -2
- package/dist/host/dotfiles/editorconfig +0 -1
- package/dist/host/dotfiles/gitattributes +0 -1
- package/dist/host/dotfiles/gitignore +0 -1
- package/dist/host/dotfiles/oxlintrc.json +24 -0
- package/dist/host/guides/agent.md +1638 -598
- package/dist/host/guides/budget.md +89 -29
- package/dist/host/guides/form.md +477 -91
- package/dist/host/guides/mcp.md +14 -2
- package/dist/host/guides/ollama.md +97 -73
- package/dist/host/guides/probe.md +1 -1
- package/dist/host/guides/scaffold.md +158 -101
- package/dist/host/guides/study.md +2635 -0
- package/dist/host/guides/table.md +225 -15
- package/dist/host/guides/terminal.md +22 -20
- package/dist/host/guides/test.md +689 -255
- package/dist/host/manifest.json +87 -63
- package/dist/host/tests/config.test.ts +136 -82
- package/dist/host/tests/policy.test.ts +39 -1
- package/dist/host/tests/setupPolicy.ts +86 -28
- package/dist/src/core/index.cjs +1387 -611
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +35 -20
- package/dist/src/core/index.d.ts +35 -20
- package/dist/src/core/index.js +1385 -612
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +12 -12
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +12 -12
- package/dist/src/server/index.d.ts +12 -12
- package/dist/src/server/index.js +12 -12
- package/dist/src/server/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -9,10 +9,20 @@ prepare the next.
|
|
|
9
9
|
|
|
10
10
|
`scripts/wave.ts --visit` runs these steps in this order and stops at the first one that fails; a
|
|
11
11
|
step that reads generated or installed state is invalid before the step that writes it. Run a step
|
|
12
|
-
by hand only to repair it, then resume with `--from <step>`.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
by hand only to repair it, then resume with `--from <step>`. Read a failed step's journal, which
|
|
13
|
+
its row names under the target's `tmp/units/wave/`, before running the step again. Journals and
|
|
14
|
+
overwrite receipts are written only where the work tree ignores `tmp/`.
|
|
15
|
+
|
|
16
|
+
1. Re-pin every range the audit's release readings name to the caret of its returned release,
|
|
17
|
+
and install before the overwrite. Read the audit population as the declared `@orkestrel`
|
|
18
|
+
dependencies in `dependencies` and `devDependencies`, plus declared foreign tools that the
|
|
19
|
+
blueprint plans in those sections; exclude the fixed showcase tool pair from ordinary release lookups.
|
|
20
|
+
Look up fleet releases with `*`; look up foreign tools with
|
|
21
|
+
a caret over the declared major when one can be extracted, otherwise with the declared range.
|
|
22
|
+
Do not treat a declared minor or patch bound as the lookup bound. Peer-only dependencies produce no release reading;
|
|
23
|
+
rewrite a peer range only when its name shares an audited release reading. For example, with
|
|
24
|
+
peer-only `@orkestrel/peer-only: ^0.0.1`, leave that peer unchanged; with a planned tool whose
|
|
25
|
+
registry serves `8.3.4`, apply `vite: ~8.2.0 -> ^8.3.4` even though the tilde excludes `8.3.4`.
|
|
16
26
|
2. Commit the manifest and the lockfile as the preparation commit. `scaffold overwrite` refuses a
|
|
17
27
|
tree carrying uncommitted changes, and the install left both dirty.
|
|
18
28
|
3. Run `scaffold overwrite`. One run repairs the `AGENTS.md` and `CLAUDE.md` pointers and deletes
|
|
@@ -33,17 +43,24 @@ by hand only to repair it, then resume with `--from <step>`.
|
|
|
33
43
|
rather than waiving past it.
|
|
34
44
|
- A copy the target git-ignores stays a `foreign` finding, so that target never reaches exit `0`
|
|
35
45
|
again. Keep a local MCP server registration outside the repository rather than at `.mcp.json`.
|
|
36
|
-
4. Force-verify
|
|
37
|
-
published.
|
|
46
|
+
4. Force-verify the same audit population and lookup bounds against a registry sweep taken after
|
|
47
|
+
the previous layer published. Do not infer verification of peer-only declarations from that audit.
|
|
38
48
|
5. Run the full install. The overwrite re-declares the toolchain ranges and declares each planned
|
|
39
49
|
dependency the manifest lacks, so the lockfile the first install regenerated no longer matches the
|
|
40
50
|
manifest.
|
|
41
51
|
6. Sweep the self-pins, per § Sweep the self-pins: the re-pin moves the snapshot class.
|
|
42
52
|
7. Run the mutating `format` script to converge generated writes.
|
|
43
|
-
8.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
8. Commit the overwrite's writes as `Overwrite with scaffold <version>`: every path the overwrite
|
|
54
|
+
wrote or removed, and the manifest and lockfile the install converged. The step refuses a dirty
|
|
55
|
+
path the overwrite did not write and names it. After committing an unrelated path, complete the intended overwrite commit by hand:
|
|
56
|
+
inspect the receipt's written and removed paths, stage those paths and the converged manifest
|
|
57
|
+
and lockfile, and commit them as `Overwrite with scaffold <version>`. Then resume with `--from gates`.
|
|
58
|
+
Treat the receipt as stale after any intervening commit; never use that receipt to authorize
|
|
59
|
+
another `record` commit. Skip this step for an offline overwrite and the `@orkestrel/scaffold` package.
|
|
60
|
+
9. Run the quality gates.
|
|
61
|
+
10. Run `node .agents/skills/orkestrel-publish/scripts/compare.ts` to compare the rebuilt `dist/`
|
|
62
|
+
against the published tarball for material content. An exit of 2 is an unanswered comparison,
|
|
63
|
+
never a moved dist: fetch and re-run rather than ruling a bump owed.
|
|
47
64
|
|
|
48
65
|
Restore every pin the target holds with `scripts/swap.ts --restore` before the visit's first step, per
|
|
49
66
|
[release.md](release.md) § Fix a dependency before it publishes, because the visit reads and
|
|
@@ -72,6 +89,30 @@ against that checkout.
|
|
|
72
89
|
Run visits in parallel slices of disjoint repositories, each slice strictly serial inside itself,
|
|
73
90
|
reporting per target. Refuse a failed target, name it, repair it, and re-run it alone.
|
|
74
91
|
|
|
92
|
+
### Regenerate a lock the install cannot move
|
|
93
|
+
|
|
94
|
+
When the install in step 1 or step 5 fails with `ERESOLVE`, read its conflict and rerun command.
|
|
95
|
+
An exact-peer cluster, such as `vitest` with `@vitest/browser-playwright`, can prevent npm from
|
|
96
|
+
moving the lockfile in place. Without the flag, the step deletes nothing.
|
|
97
|
+
|
|
98
|
+
- Pass `--regenerate` only when the user's instruction for the visit names it: the regeneration is a
|
|
99
|
+
destructive command under `.agents/orchestration.md` § Permission floor. A unit whose brief does
|
|
100
|
+
not name it, or whose sandbox refused a deletion, stops at the refusal and reports it.
|
|
101
|
+
- With the flag, refuse before moving anything when `node_modules` is a link, the lockfile is
|
|
102
|
+
untracked or carries uncommitted changes, the manifest names a local dependency spec or declares
|
|
103
|
+
`workspaces`, `tmp/` is not git-ignored, or the target is not the root of its work tree.
|
|
104
|
+
- Validate the backup and journal paths' ancestry and physical containment before writing or moving,
|
|
105
|
+
and revalidate before cleanup. Refuse a linked ancestor while permitting ignored scratch beneath a real target.
|
|
106
|
+
- Otherwise copy the lockfile and move `node_modules` under `tmp/units/wave/<stamp>/`, delete the
|
|
107
|
+
lockfile, install from the manifest, and prove the result: the install exits `0`, the lockfile
|
|
108
|
+
exists, `npm ls --all` exits `0`, and the manifest bytes are unchanged. Read each package named
|
|
109
|
+
by the conflict with its installed version in the step's note. A proved result deletes the moved
|
|
110
|
+
tree; a failed result restores the copied lockfile and moved tree and names why the step failed.
|
|
111
|
+
Confirm a recoverable tree and lock backup before deleting the active tree. Attempt rollback at
|
|
112
|
+
most once. If rollback fails, retain both backup paths for recovery. If completion journaling or
|
|
113
|
+
backup cleanup fails, report that failure and retain the restored or proved installation.
|
|
114
|
+
- Resume a visit that stopped at the refusal with `--regenerate --from <step>`.
|
|
115
|
+
|
|
75
116
|
## Rule on the bump
|
|
76
117
|
|
|
77
118
|
Bump on either trigger: `scripts/compare.ts` exits 3 (the rebuilt dist differs materially from the
|
|
@@ -100,6 +141,8 @@ registry copy over any staged tip, so every consumer stays red until that tip is
|
|
|
100
141
|
|
|
101
142
|
## Prepare a layer
|
|
102
143
|
|
|
144
|
+
- When the manifest's `engines.node` names a floor below the `DEFAULT_ENGINES` a generated workspace declares, raise it to that floor and move the package's CI floor row with it.
|
|
145
|
+
- Before the release, rule the package's guide and source comments against `.claude/rules/writing.md` § Substitutions and reword each hit its rows name; identifiers stay.
|
|
103
146
|
- Compare release packs between hosts by paths, sizes, and content hashes, and report executable-mode differences separately; a pack made on Windows records `0644` for an entry git tracks as `100755`.
|
|
104
147
|
|
|
105
148
|
An unpublished package's first version is `0.0.1`. Do not bump it before that first publish. The
|
|
@@ -117,9 +160,9 @@ Prepare a published package's layer in this order, after the visit has ruled the
|
|
|
117
160
|
bumped manifest.
|
|
118
161
|
3. **Sweep the self-pins**, per the following section: the bump moves the version class.
|
|
119
162
|
4. **Run each package's own `prepublishOnly` script to green.**
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
163
|
+
Run the visit and this script on a Node whose bundled npm meets the `MINIMUM_NPM_VERSION` floor a
|
|
164
|
+
generated workspace declares in `devEngines`: the scripts spawn the npm CLI beside the running
|
|
165
|
+
Node binary when one is there, so a `PATH` change reaches them only where none is.
|
|
123
166
|
5. **Write the release commit and push before the window opens.** The preparation commit inside
|
|
124
167
|
the visit is a different commit at a different moment.
|
|
125
168
|
|
|
@@ -128,7 +128,7 @@ rest of the layer either fits inside it or takes another approval.
|
|
|
128
128
|
its own URL.
|
|
129
129
|
- Relay every new URL to the user the moment it appears, through a journal watcher, and never
|
|
130
130
|
pause the chain to wait for a click: a poll outlives the relay.
|
|
131
|
-
- Tell the user to click only the URL last in log order. A click on a superseded URL
|
|
131
|
+
- Tell the user to click only the URL last in log order. A click on a superseded URL invalidates the
|
|
132
132
|
live attempt, and the current poll then fails `403 Forbidden - GET /-/v1/done` mid-flight.
|
|
133
133
|
§ Read a `403` on the poll owns the recovery.
|
|
134
134
|
- **Never retry a publish that is still waiting for its authorization.** Each `npm publish`
|
|
@@ -151,7 +151,7 @@ the same status. Rule from the evidence, never from which cause reads likelier.
|
|
|
151
151
|
|
|
152
152
|
- Nobody clicked inside the session's life. The poll ran out its 45 seconds against a URL no one
|
|
153
153
|
opened, and the registry closed the session.
|
|
154
|
-
- The user clicked a superseded URL and
|
|
154
|
+
- The user clicked a superseded URL and invalidated the live attempt. The poll fails mid-flight while
|
|
155
155
|
the user is looking at a page that reports success.
|
|
156
156
|
- The registry refused the attempt's first poll, seconds after the mint and before anyone could
|
|
157
157
|
click, because the poll left from an egress address other than the one that minted the session.
|
|
@@ -160,7 +160,7 @@ the same status. Rule from the evidence, never from which cause reads likelier.
|
|
|
160
160
|
survives its first poll and relaying that one alone, per § Reach the approval.
|
|
161
161
|
- Tell those causes apart from the log and the user, never from the status alone. A single minted
|
|
162
162
|
URL that nobody opened in time is the abandon. A log carrying a URL the running attempt
|
|
163
|
-
superseded, with the user reporting a click, is the
|
|
163
|
+
superseded, with the user reporting a click, is the invalidated attempt. A drop within seconds of
|
|
164
164
|
the mint, before any relay, is the egress refusal.
|
|
165
165
|
- Recover the same way whichever it was: read the registry for the version, confirm no publish
|
|
166
166
|
process is live, then mint exactly one fresh attempt with the user at the keyboard.
|
|
@@ -178,9 +178,9 @@ the same status. Rule from the evidence, never from which cause reads likelier.
|
|
|
178
178
|
status of the pipeline, and a CDN read straight after a publish can still serve the previous
|
|
179
179
|
version.
|
|
180
180
|
- Treat a `404` after a first publish as pending rather than failed. A first publish creates the
|
|
181
|
-
packument and can serve `404` for minutes after success
|
|
182
|
-
|
|
183
|
-
same rule.
|
|
181
|
+
packument and can serve `404` for minutes after success. For a first publish, rerun
|
|
182
|
+
`window.ts --confirm NAME@VERSION` with a `--wait` long enough for a first publish before reporting
|
|
183
|
+
either way. A bump serving the old version is CDN lag, same rule.
|
|
184
184
|
- Rule on a pack-time manifest-rewriting warning by fetching the registry's copy of the manifest,
|
|
185
185
|
never by the warning's own text.
|
|
186
186
|
- Re-read the registry before telling the user a package failed. A chain still running, a retry
|
|
@@ -45,18 +45,20 @@ import {
|
|
|
45
45
|
readFileSync,
|
|
46
46
|
realpathSync,
|
|
47
47
|
renameSync,
|
|
48
|
-
rmSync,
|
|
49
48
|
writeFileSync,
|
|
50
49
|
} from 'node:fs'
|
|
51
50
|
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path'
|
|
52
51
|
import {
|
|
52
|
+
isRecord,
|
|
53
53
|
normalizeSlashes,
|
|
54
54
|
parseJsonRecord,
|
|
55
55
|
readMissingFlags,
|
|
56
56
|
readOption,
|
|
57
57
|
readOptions,
|
|
58
58
|
readString,
|
|
59
|
+
removeTree,
|
|
59
60
|
runNpm,
|
|
61
|
+
scanLocalSpecs,
|
|
60
62
|
} from '../../orkestrel-dispatch/scripts/helpers.ts'
|
|
61
63
|
|
|
62
64
|
type Manifest = Readonly<Record<string, unknown>>
|
|
@@ -256,25 +258,6 @@ const OVERRIDE_PRECEDERS: readonly string[] = [
|
|
|
256
258
|
'resolutions',
|
|
257
259
|
]
|
|
258
260
|
|
|
259
|
-
// The manifest blocks whose values are dependency specs; `overrides` nests records of them.
|
|
260
|
-
const SPEC_BLOCKS: readonly string[] = [
|
|
261
|
-
'dependencies',
|
|
262
|
-
'devDependencies',
|
|
263
|
-
'peerDependencies',
|
|
264
|
-
'optionalDependencies',
|
|
265
|
-
'overrides',
|
|
266
|
-
]
|
|
267
|
-
|
|
268
|
-
// npm-package-arg reads a spec as local when it carries a `file:` or `link:` prefix or begins like a
|
|
269
|
-
// path: a dot, `~/`, a separator, or a drive letter.
|
|
270
|
-
const LOCAL_SPEC_PATTERN = /^(?:file:|link:|\.|~[\\/]|[\\/]|[A-Za-z]:)/iu
|
|
271
|
-
|
|
272
|
-
// It also reads a spec as local when the spec ends in an archive extension and carries no protocol...
|
|
273
|
-
const ARCHIVE_SPEC_PATTERN = /^[^:]+\.(?:tgz|tar\.gz|tar)$/iu
|
|
274
|
-
|
|
275
|
-
// ...unless the spec is a `user/repo` shorthand, which names a hosted repository whatever it ends in.
|
|
276
|
-
const SHORTHAND_SPEC_PATTERN = /^[^:@%/\s.-][^:@%/\s]*\/[^:@\s/%]+$/u
|
|
277
|
-
|
|
278
261
|
// An optional `@scope/` and a name of the characters a registry URL carries untouched; a path
|
|
279
262
|
// separator beyond the scope's one `/`, an absolute form, and a drive form fall outside it.
|
|
280
263
|
const PACKAGE_NAME_PATTERN = /^(?:@[A-Za-z0-9~-][A-Za-z0-9._~-]*\/)?[A-Za-z0-9~-][A-Za-z0-9._~-]*$/u
|
|
@@ -287,18 +270,6 @@ const USAGE = [
|
|
|
287
270
|
' swap.ts --status --consumer DIR [--json]',
|
|
288
271
|
].join('\n')
|
|
289
272
|
|
|
290
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
291
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function isLocalSpec(spec: string): boolean {
|
|
295
|
-
const text = spec.trimStart()
|
|
296
|
-
return (
|
|
297
|
-
LOCAL_SPEC_PATTERN.test(text) ||
|
|
298
|
-
(ARCHIVE_SPEC_PATTERN.test(text) && !SHORTHAND_SPEC_PATTERN.test(text))
|
|
299
|
-
)
|
|
300
|
-
}
|
|
301
|
-
|
|
302
273
|
function isPackageName(name: string): boolean {
|
|
303
274
|
return (
|
|
304
275
|
name.length <= PACKAGE_NAME_LIMIT && !name.includes('..') && PACKAGE_NAME_PATTERN.test(name)
|
|
@@ -899,10 +870,6 @@ function replaceFile(path: string, text: string): void {
|
|
|
899
870
|
renameSync(temporary, path)
|
|
900
871
|
}
|
|
901
872
|
|
|
902
|
-
function removeTree(path: string): void {
|
|
903
|
-
rmSync(path, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 })
|
|
904
|
-
}
|
|
905
|
-
|
|
906
873
|
// Vite keys its pre-bundle on the installed version, so a same-version tarball would serve stale bytes.
|
|
907
874
|
function installConsumer(consumer: string): void {
|
|
908
875
|
invokeNpm(['install', '--ignore-scripts', '--no-audit', '--no-fund'], consumer)
|
|
@@ -1146,22 +1113,11 @@ function readPackedManifest(directory: string): string | undefined {
|
|
|
1146
1113
|
// or not a ledger recorded the spec.
|
|
1147
1114
|
function scanPackedSpecs(source: Source): readonly string[] {
|
|
1148
1115
|
const manifest = loadPackedManifest(source.directory)
|
|
1149
|
-
return
|
|
1150
|
-
|
|
1151
|
-
isLocalSpec(spec)
|
|
1152
|
-
? [`${source.name} would pack a local dependency spec: ${path} is ${spec}`]
|
|
1153
|
-
: [],
|
|
1154
|
-
),
|
|
1116
|
+
return scanLocalSpecs(manifest).map(
|
|
1117
|
+
([path, spec]) => `${source.name} would pack a local dependency spec: ${path} is ${spec}`,
|
|
1155
1118
|
)
|
|
1156
1119
|
}
|
|
1157
1120
|
|
|
1158
|
-
// An `overrides` value can nest records, so the path names every key down to the spec.
|
|
1159
|
-
function collectSpecs(path: string, value: unknown): ReadonlyArray<readonly [string, string]> {
|
|
1160
|
-
if (typeof value === 'string') return [[path, value]]
|
|
1161
|
-
if (!isRecord(value)) return []
|
|
1162
|
-
return Object.entries(value).flatMap(([key, child]) => collectSpecs(`${path}.${key}`, child))
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
1121
|
// A source that carries a ledger of its own has its manifest rewritten to the recorded ranges for the
|
|
1166
1122
|
// pack and restored byte for byte whether the pack succeeds or throws, so a consumer never receives a
|
|
1167
1123
|
// tarball spec that resolves only inside the source.
|