@orkestrel/scaffold 0.0.2 → 0.0.3
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 +29 -15
- package/dist/bin/scaffold.js +1162 -1200
- package/dist/bin/scaffold.js.map +1 -1
- package/dist/host/AGENTS.md +124 -925
- package/dist/host/CLAUDE.md +260 -495
- package/dist/host/agents/skills/orkestrel-align-packages/SKILL.md +53 -0
- package/dist/host/agents/skills/orkestrel-align-packages/agents/openai.yaml +4 -0
- package/dist/host/agents/skills/orkestrel-align-packages/references/fleet.md +50 -0
- package/dist/host/agents/skills/orkestrel-align-packages/references/integration.md +56 -0
- package/dist/host/agents/skills/orkestrel-build-application/SKILL.md +64 -0
- package/dist/host/agents/skills/orkestrel-build-application/agents/openai.yaml +4 -0
- package/dist/host/agents/skills/orkestrel-build-application/references/application.md +129 -0
- package/dist/host/agents/skills/orkestrel-harden-package/SKILL.md +64 -0
- package/dist/host/agents/skills/orkestrel-harden-package/agents/openai.yaml +4 -0
- package/dist/host/agents/skills/orkestrel-harden-package/references/centralization.md +85 -0
- package/dist/host/agents/skills/orkestrel-harden-package/references/contract.md +57 -0
- package/dist/host/agents/skills/orkestrel-harden-package/references/hardening.md +93 -0
- package/dist/host/agents/skills/orkestrel-harden-package/references/research.md +61 -0
- package/dist/host/claude/agents/application.md +32 -0
- package/dist/host/claude/agents/builder.md +12 -7
- package/dist/host/claude/agents/checker.md +15 -8
- package/dist/host/claude/agents/codex.md +40 -0
- package/dist/host/claude/agents/grok.md +20 -37
- package/dist/host/claude/agents/orkestrel.md +89 -223
- package/dist/host/claude/agents/planner.md +14 -34
- package/dist/host/claude/agents/reviewer.md +39 -24
- package/dist/host/claude/agents/verifier.md +15 -10
- package/dist/host/claude/rules/application.md +57 -0
- package/dist/host/claude/rules/architecture.md +179 -0
- package/dist/host/claude/rules/browser.md +28 -0
- package/dist/host/claude/rules/documentation.md +64 -0
- package/dist/host/claude/rules/names.md +209 -0
- package/dist/host/claude/rules/patterns.md +130 -0
- package/dist/host/claude/rules/quality.md +45 -0
- package/dist/host/claude/rules/styles.md +64 -0
- package/dist/host/claude/rules/tests.md +123 -0
- package/dist/host/claude/rules/typescript.md +78 -0
- package/dist/host/claude/rules/workspace.md +180 -0
- package/dist/host/claude/settings.json +116 -0
- package/dist/host/claude/skills/orkestrel-align-packages/SKILL.md +10 -0
- package/dist/host/claude/skills/orkestrel-build-application/SKILL.md +12 -0
- package/dist/host/claude/skills/orkestrel-harden-package/SKILL.md +10 -0
- package/dist/host/codex/agents/analyst.toml +15 -0
- package/dist/host/codex/agents/application.toml +25 -0
- package/dist/host/codex/agents/builder.toml +24 -0
- package/dist/host/codex/agents/checker.toml +15 -0
- package/dist/host/codex/agents/grok.toml +17 -0
- package/dist/host/codex/agents/implementer.toml +17 -0
- package/dist/host/codex/agents/orkestrel.toml +16 -0
- package/dist/host/codex/agents/planner.toml +20 -0
- package/dist/host/codex/agents/reviewer.toml +18 -0
- package/dist/host/codex/agents/verifier.toml +14 -0
- package/dist/host/codex/config.toml +64 -0
- package/dist/host/dotfiles/oxlintrc.json +307 -1
- package/dist/host/guides/src/scaffold.md +2059 -2007
- package/dist/host/manifest.json +355 -137
- package/dist/host/scripts/codex.sh +49 -0
- package/dist/host/scripts/cursor.sh +33 -47
- package/dist/host/scripts/deps.sh +34 -16
- package/dist/host/scripts/ollama.sh +6 -149
- package/dist/host/tests/setupPolicy.ts +354 -0
- package/dist/src/core/index.cjs +6600 -1199
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +801 -266
- package/dist/src/core/index.d.ts +801 -266
- package/dist/src/core/index.js +6518 -1191
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +3132 -593
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +643 -95
- package/dist/src/server/index.d.ts +643 -95
- package/dist/src/server/index.js +3054 -594
- package/dist/src/server/index.js.map +1 -1
- package/package.json +15 -12
- package/dist/host/claude/agents/composer.md +0 -64
- package/dist/host/claude/agents/researcher.md +0 -38
- package/dist/host/claude/agents/scout.md +0 -35
- package/dist/host/github/workflows/ci.yml +0 -64
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import { Audit } from '../core/index.ts';
|
|
2
2
|
import { Blueprint } from '../core/index.ts';
|
|
3
|
+
import { BooleanShape } from '@orkestrel/contract';
|
|
3
4
|
import { CatalogEntry } from '../core/index.ts';
|
|
5
|
+
import { ContractInterface } from '@orkestrel/contract';
|
|
4
6
|
import { Dependency } from '../core/index.ts';
|
|
5
7
|
import { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
6
8
|
import { EmitterHooks } from '@orkestrel/emitter';
|
|
7
9
|
import { EmitterInterface } from '@orkestrel/emitter';
|
|
8
10
|
import { GuideSync } from '../core/index.ts';
|
|
11
|
+
import { HostArtifact } from '../core/index.ts';
|
|
12
|
+
import { NumberShape } from '@orkestrel/contract';
|
|
13
|
+
import { ObjectShape } from '@orkestrel/contract';
|
|
14
|
+
import { OptionalShape } from '@orkestrel/contract';
|
|
9
15
|
import { Plan } from '../core/index.ts';
|
|
16
|
+
import { ScaffoldErrorCode } from '../core/index.ts';
|
|
17
|
+
import { Snapshot } from '../core/index.ts';
|
|
18
|
+
import { StringShape } from '@orkestrel/contract';
|
|
10
19
|
import { SyncReport } from '../core/index.ts';
|
|
11
20
|
import { VersionSync } from '../core/index.ts';
|
|
12
21
|
|
|
22
|
+
/** One mutable aggregate entry allowance shared by fleet catalog roots. */
|
|
23
|
+
export declare type CatalogAllowance = Float64Array;
|
|
24
|
+
|
|
13
25
|
/**
|
|
14
26
|
* Build the fleet package catalog — one `CatalogEntry` per `@orkestrel/*`
|
|
15
27
|
* package discovered under each root, its description drawn from its own
|
|
@@ -42,7 +54,20 @@ import { VersionSync } from '../core/index.ts';
|
|
|
42
54
|
* catalogPackages(['/repos']) // [{ name: '@orkestrel/contract', version: '0.0.5', description: '…' }, …]
|
|
43
55
|
* ```
|
|
44
56
|
*/
|
|
45
|
-
export declare function catalogPackages(roots: readonly string[]): readonly CatalogEntry[];
|
|
57
|
+
export declare function catalogPackages(roots: readonly string[], limit?: number): readonly CatalogEntry[];
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Promote a complete staged set and roll every earlier destination back when
|
|
61
|
+
* any later promotion fails.
|
|
62
|
+
*
|
|
63
|
+
* @param transaction - Same-volume sibling staging state.
|
|
64
|
+
* @param paths - Portable target-relative files to promote.
|
|
65
|
+
* @throws `ScaffoldError('WRITE', ...)` with recovery details on failure.
|
|
66
|
+
*/
|
|
67
|
+
export declare function commitWriteTransaction(transaction: WriteTransaction, paths: readonly string[]): void;
|
|
68
|
+
|
|
69
|
+
/** Consume one aggregate fleet-catalog traversal slot. */
|
|
70
|
+
export declare function consumeCatalogAllowance(allowance: CatalogAllowance, root: string): void;
|
|
46
71
|
|
|
47
72
|
/**
|
|
48
73
|
* Create a `MaterializerInterface` (server) — the materialization entity,
|
|
@@ -78,6 +103,30 @@ export declare function createMaterializer(options?: MaterializerOptions): Mater
|
|
|
78
103
|
*/
|
|
79
104
|
export declare function createSync(options?: SyncOptions): SyncInterface;
|
|
80
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Create a physical directory path one segment at a time behind captured identities.
|
|
108
|
+
*
|
|
109
|
+
* @param path - The absolute directory path to establish.
|
|
110
|
+
* @param boundary - The boundary name used in diagnostics.
|
|
111
|
+
* @returns The final directory anchor and the subset created by this call.
|
|
112
|
+
*/
|
|
113
|
+
export declare function createWriteDirectory(path: string, boundary: string): WriteDirectoryResult;
|
|
114
|
+
|
|
115
|
+
/** Default cumulative response bytes retained by one Sync operation. */
|
|
116
|
+
export declare const DEFAULT_SYNC_BUDGET = 16777216;
|
|
117
|
+
|
|
118
|
+
/** Default simultaneous upstream requests used by `Sync`. */
|
|
119
|
+
export declare const DEFAULT_SYNC_CONCURRENCY = 6;
|
|
120
|
+
|
|
121
|
+
/** Default maximum dependencies or catalog entries retained by one Sync operation. */
|
|
122
|
+
export declare const DEFAULT_SYNC_ITEMS = 256;
|
|
123
|
+
|
|
124
|
+
/** Default per-response byte limit used by `Sync`. */
|
|
125
|
+
export declare const DEFAULT_SYNC_LIMIT = 5242880;
|
|
126
|
+
|
|
127
|
+
/** Default per-request timeout used by `Sync`, in milliseconds. */
|
|
128
|
+
export declare const DEFAULT_SYNC_TIMEOUT = 10000;
|
|
129
|
+
|
|
81
130
|
/**
|
|
82
131
|
* Reconstruct a `Blueprint` from an EXISTING repo at `target` — the faithful
|
|
83
132
|
* inverse `audit` / `repair` / `mirror` need to diff a live package against
|
|
@@ -85,12 +134,12 @@ export declare function createSync(options?: SyncOptions): SyncInterface;
|
|
|
85
134
|
*
|
|
86
135
|
* @param target - The existing package directory to derive a `Blueprint` from.
|
|
87
136
|
* @remarks
|
|
88
|
-
*
|
|
89
|
-
* name is
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
137
|
+
* A scoped package name is stripped to its bounded safe short name. An
|
|
138
|
+
* unscoped name is accepted only when the target is app-only, `private: true`,
|
|
139
|
+
* and the name satisfies `isWorkspaceName`; every other name is a coded
|
|
140
|
+
* `TARGET` failure. `src` is derived from `src/<environment>/` and `app` from
|
|
141
|
+
* `app/<environment>/`; a target with no environment on either axis is also a coded
|
|
142
|
+
* `TARGET` failure. `dependencies` /
|
|
94
143
|
* `peers` are the `@orkestrel/`-prefixed entries of `manifest.dependencies` /
|
|
95
144
|
* `manifest.peerDependencies` (a peer flagged `peerDependenciesMeta[name]
|
|
96
145
|
* .optional === true` carries `optional: true`). `extras` is EVERY entry of
|
|
@@ -102,24 +151,56 @@ export declare function createSync(options?: SyncOptions): SyncInterface;
|
|
|
102
151
|
* ALSO present in
|
|
103
152
|
* `manifest.peerDependencies` or `manifest.dependencies` (e.g. a peer
|
|
104
153
|
* dev-installed for local testing) is likewise excluded from `extras` — it
|
|
105
|
-
* already
|
|
154
|
+
* already appears as a `peer`/`dependency` above, and double-counting it as
|
|
106
155
|
* an `extra` would land it in `peers ∩ extras`, a blocking `validateBlueprint`
|
|
107
156
|
* gate. `overrides` is always `[]` — derivation cannot know a caller's
|
|
108
157
|
* template-override intent.
|
|
109
158
|
* @returns The reconstructed `Blueprint`.
|
|
110
159
|
* @throws `ScaffoldError('TARGET', …)` when `target`'s manifest is unreadable
|
|
111
|
-
* (via `readManifest`), is not valid JSON, its
|
|
112
|
-
*
|
|
160
|
+
* (via `readManifest`), is not valid JSON, its name is unsafe for its
|
|
161
|
+
* publication mode, or `target` carries no source or application environment.
|
|
113
162
|
*
|
|
114
163
|
* @example
|
|
115
164
|
* ```ts
|
|
116
165
|
* import { deriveBlueprint } from '@orkestrel/scaffold/server'
|
|
117
166
|
*
|
|
118
|
-
* deriveBlueprint('./packages/router') // { name: 'router',
|
|
167
|
+
* deriveBlueprint('./packages/router') // { name: 'router', src: ['core', 'server'], … }
|
|
119
168
|
* ```
|
|
120
169
|
*/
|
|
121
170
|
export declare function deriveBlueprint(target: string): Blueprint;
|
|
122
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Compute a bounded-memory SHA-256 digest for one file.
|
|
174
|
+
*
|
|
175
|
+
* @param path - The file to read.
|
|
176
|
+
* @returns Its lowercase SHA-256 digest.
|
|
177
|
+
*/
|
|
178
|
+
export declare function digestFile(path: string): string;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Compute SHA-256 from exact lowercase hexadecimal bytes without decoding the whole value at once.
|
|
182
|
+
*
|
|
183
|
+
* @param hex - Exact hexadecimal bytes.
|
|
184
|
+
* @returns Their lowercase SHA-256 digest.
|
|
185
|
+
*/
|
|
186
|
+
export declare function digestHex(hex: string): string;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Compute SHA-256 from UTF-8 text.
|
|
190
|
+
*
|
|
191
|
+
* @param value - The text to hash.
|
|
192
|
+
* @returns Its lowercase SHA-256 digest.
|
|
193
|
+
*/
|
|
194
|
+
export declare function digestText(value: string): string;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Remove an uncommitted or already-committed write transaction's private residue.
|
|
198
|
+
*
|
|
199
|
+
* @param transaction - The transaction to discard.
|
|
200
|
+
* @throws `ScaffoldError('WRITE', ...)` when its private root cannot be removed.
|
|
201
|
+
*/
|
|
202
|
+
export declare function discardWriteTransaction(transaction: WriteTransaction): void;
|
|
203
|
+
|
|
123
204
|
/**
|
|
124
205
|
* List a fleet root's `@orkestrel/*` package directories.
|
|
125
206
|
*
|
|
@@ -137,7 +218,47 @@ export declare function deriveBlueprint(target: string): Blueprint;
|
|
|
137
218
|
* discoverPackages('./packages') // ['/abs/packages/router', '/abs/packages/budget']
|
|
138
219
|
* ```
|
|
139
220
|
*/
|
|
140
|
-
export declare function discoverPackages(root: string): readonly string[];
|
|
221
|
+
export declare function discoverPackages(root: string, allowance?: CatalogAllowance): readonly string[];
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Render the local pointer written when an upstream dependency guide is not vendored yet.
|
|
225
|
+
*
|
|
226
|
+
* @param source - The canonical `guides/src/<name>.md` source path.
|
|
227
|
+
* @returns The deterministic pointer content.
|
|
228
|
+
*/
|
|
229
|
+
export declare function guideStub(source: string): string;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Extract the first paragraph from the first blockquote in a Markdown guide.
|
|
233
|
+
*
|
|
234
|
+
* @param text - The guide Markdown to traverse.
|
|
235
|
+
* @returns A normalized one-line description, or `undefined` when parsing
|
|
236
|
+
* fails, no blockquote paragraph exists, or the paragraph is empty.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```ts
|
|
240
|
+
* import { guideToDescription } from '@orkestrel/scaffold/server'
|
|
241
|
+
*
|
|
242
|
+
* guideToDescription('> A concise package description.\n>\n> More detail.')
|
|
243
|
+
* // 'A concise package description.'
|
|
244
|
+
* ```
|
|
245
|
+
*/
|
|
246
|
+
export declare function guideToDescription(text: string): string | undefined;
|
|
247
|
+
|
|
248
|
+
/** One validated guide update and its contained destination. */
|
|
249
|
+
export declare interface GuideWrite {
|
|
250
|
+
readonly guide: GuideSync;
|
|
251
|
+
readonly destination: string;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** Reserved metadata file written at the root of every staged host. */
|
|
255
|
+
export declare const HOST_MANIFEST_PATH = "manifest.json";
|
|
256
|
+
|
|
257
|
+
/** A complete vendored-host inventory with file entries and declared directory roots. */
|
|
258
|
+
export declare interface HostManifest {
|
|
259
|
+
readonly entries: readonly ManifestEntry[];
|
|
260
|
+
readonly roots: readonly string[];
|
|
261
|
+
}
|
|
141
262
|
|
|
142
263
|
/**
|
|
143
264
|
* Locate this MODULE's own installed package root — the nearest ancestor of
|
|
@@ -164,16 +285,18 @@ export declare function discoverPackages(root: string): readonly string[];
|
|
|
164
285
|
export declare function hostRoot(): string;
|
|
165
286
|
|
|
166
287
|
/**
|
|
167
|
-
* Rehydrate a `Plan`'s `host`-origin artifacts with their
|
|
168
|
-
*
|
|
288
|
+
* Rehydrate a `Plan`'s `host`-origin artifacts with their exact byte hex read
|
|
289
|
+
* from `host` — manifest-aware, via `locateHostSource`.
|
|
169
290
|
*
|
|
170
291
|
* @param plan - The plan to hydrate.
|
|
171
292
|
* @param host - The resolved host root to read from.
|
|
172
|
-
* @returns A new `Plan` whose file-shaped `host` artifacts carry `
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
293
|
+
* @returns A new `Plan` whose file-shaped `host` artifacts carry exact `hex`.
|
|
294
|
+
* Directory-shaped host artifacts expand into one byte-aware artifact
|
|
295
|
+
* per file, preserving their group and mapping the artifact/source prefixes.
|
|
296
|
+
* `template` / `computed` artifacts pass through untouched.
|
|
297
|
+
* @throws `ScaffoldError('TARGET', …)` when the host is not a readable
|
|
298
|
+
* directory, a present manifest is invalid/incomplete, or a required source
|
|
299
|
+
* is absent, escaping, not a file/directory as declared, or unreadable.
|
|
177
300
|
*
|
|
178
301
|
* @example
|
|
179
302
|
* ```ts
|
|
@@ -184,38 +307,77 @@ export declare function hostRoot(): string;
|
|
|
184
307
|
*/
|
|
185
308
|
export declare function hydratePlan(plan: Plan, host: string): Plan;
|
|
186
309
|
|
|
310
|
+
/** Narrow one exact aggregate fleet traversal allowance. */
|
|
311
|
+
export declare function isCatalogAllowance(value: unknown): value is CatalogAllowance;
|
|
312
|
+
|
|
313
|
+
/** Whether a normalized catalog description is bounded and contains no controls. */
|
|
314
|
+
export declare function isCatalogDescription(value: unknown): value is string;
|
|
315
|
+
|
|
316
|
+
/** Whether one dependency is an exact data-property record safe to snapshot. */
|
|
317
|
+
export declare function isDependencyData(value: unknown): value is Dependency;
|
|
318
|
+
|
|
319
|
+
/** Whether one host filesystem path is bounded, non-empty, and safe to render in a terminal. */
|
|
320
|
+
export declare function isFilesystemPath(value: unknown): value is string;
|
|
321
|
+
|
|
187
322
|
/**
|
|
188
|
-
*
|
|
189
|
-
* `storage`, a string `destination`, and a boolean `executable`.
|
|
323
|
+
* Narrow a value to one exact complete vendored-host manifest.
|
|
190
324
|
*
|
|
191
|
-
* @param value - The candidate
|
|
192
|
-
* @returns `true`
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
325
|
+
* @param value - The candidate manifest value.
|
|
326
|
+
* @returns `true` only for an exact `{ entries, roots }` record with safe paths.
|
|
327
|
+
*/
|
|
328
|
+
export declare function isHostManifest(value: unknown): value is HostManifest;
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Narrow a value to one exact vendored-host manifest entry.
|
|
197
332
|
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
* ```
|
|
333
|
+
* @param value - The candidate raw manifest entry.
|
|
334
|
+
* @returns `true` only for the exact safe entry shape.
|
|
201
335
|
*/
|
|
202
336
|
export declare function isManifestEntry(value: unknown): value is ManifestEntry;
|
|
203
337
|
|
|
338
|
+
/** Narrow an exact initial-listener record for `Materializer`. */
|
|
339
|
+
export declare function isMaterializerEventHooks(value: unknown): value is EmitterHooks<MaterializerEventMap>;
|
|
340
|
+
|
|
204
341
|
/**
|
|
205
|
-
*
|
|
342
|
+
* Determine whether a caught filesystem error reports an absent path.
|
|
206
343
|
*
|
|
207
|
-
* @param value - The
|
|
208
|
-
* @returns `true`
|
|
344
|
+
* @param value - The caught value.
|
|
345
|
+
* @returns `true` only for an `Error` whose `code` is exactly `ENOENT`.
|
|
346
|
+
*/
|
|
347
|
+
export declare function isMissingPathError(value: unknown): boolean;
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Determine whether a value is a non-empty portable relative POSIX path.
|
|
209
351
|
*
|
|
210
|
-
* @
|
|
211
|
-
*
|
|
212
|
-
|
|
352
|
+
* @param value - The candidate path.
|
|
353
|
+
* @returns `true` when every path segment is safe and portable.
|
|
354
|
+
*/
|
|
355
|
+
export declare function isPortablePath(value: unknown): value is string;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Whether a path is an existing physical directory rather than a file or link.
|
|
213
359
|
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
|
|
360
|
+
* @param path - The filesystem path to inspect without following links.
|
|
361
|
+
* @returns `true` only for a successful `lstat` reporting a directory.
|
|
362
|
+
*/
|
|
363
|
+
export declare function isRealDirectory(path: string): boolean;
|
|
364
|
+
|
|
365
|
+
/** Determine whether a target-relative path addresses preserved repository metadata. */
|
|
366
|
+
export declare function isReservedTargetPath(value: string): boolean;
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Determine whether a host-relative path resembles local configuration or credentials.
|
|
370
|
+
*
|
|
371
|
+
* @param value - The portable candidate path.
|
|
372
|
+
* @returns `true` when the path must be excluded from vendored host output.
|
|
217
373
|
*/
|
|
218
|
-
export declare function
|
|
374
|
+
export declare function isSensitiveHostPath(value: string): boolean;
|
|
375
|
+
|
|
376
|
+
/** Narrow an exact initial-listener record for `Sync`. */
|
|
377
|
+
export declare function isSyncEventHooks(value: unknown): value is EmitterHooks<SyncEventMap>;
|
|
378
|
+
|
|
379
|
+
/** Whether one externally supplied string is safe to render in terminal or JSON diagnostics. */
|
|
380
|
+
export declare function isTerminalText(value: unknown): value is string;
|
|
219
381
|
|
|
220
382
|
/**
|
|
221
383
|
* Whether a target path is absent, empty, or contains nothing but a `.git`
|
|
@@ -233,12 +395,23 @@ export declare function isRecord(value: unknown): value is Record<string, unknow
|
|
|
233
395
|
*/
|
|
234
396
|
export declare function isVacant(target: string): boolean;
|
|
235
397
|
|
|
398
|
+
/** Narrow one exact transaction destination precondition. */
|
|
399
|
+
export declare function isWritePrecondition(value: unknown): value is WritePrecondition;
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Recursively list a directory's descendant directories.
|
|
403
|
+
*
|
|
404
|
+
* @param root - The directory to list.
|
|
405
|
+
* @returns Root-relative POSIX directory paths in code-unit order.
|
|
406
|
+
*/
|
|
407
|
+
export declare function listDirectories(root: string): readonly string[];
|
|
408
|
+
|
|
236
409
|
/**
|
|
237
410
|
* Recursively list a directory's files as root-relative paths.
|
|
238
411
|
*
|
|
239
412
|
* @param root - The directory to list.
|
|
240
|
-
* @returns Root-relative file paths (posix-style `/` separators),
|
|
241
|
-
* when `root` is absent.
|
|
413
|
+
* @returns Root-relative file paths (posix-style `/` separators), code-unit
|
|
414
|
+
* sorted, or `[]` when `root` is absent.
|
|
242
415
|
*
|
|
243
416
|
* @example
|
|
244
417
|
* ```ts
|
|
@@ -253,7 +426,7 @@ export declare function listFiles(root: string): readonly string[];
|
|
|
253
426
|
* Resolve the absolute host-storage path for a host-origin artifact's
|
|
254
427
|
* `source`, manifest-aware.
|
|
255
428
|
*
|
|
256
|
-
* @param manifest - The host
|
|
429
|
+
* @param manifest - The parsed complete host manifest, or `undefined`
|
|
257
430
|
* when the host carries none (raw-repo-root fallback).
|
|
258
431
|
* @param source - The artifact's `source` (or `path`) to resolve.
|
|
259
432
|
* @param host - The resolved host root the path is joined against.
|
|
@@ -269,11 +442,18 @@ export declare function listFiles(root: string): readonly string[];
|
|
|
269
442
|
* import { locateHostSource } from '@orkestrel/scaffold/server'
|
|
270
443
|
*
|
|
271
444
|
* locateHostSource(undefined, 'package.json', './dist/host') // './dist/host/package.json'
|
|
272
|
-
* locateHostSource(
|
|
445
|
+
* locateHostSource(
|
|
446
|
+
* {
|
|
447
|
+
* entries: [{ storage: 'pkg.tmpl', destination: 'package.json', executable: false }],
|
|
448
|
+
* roots: [],
|
|
449
|
+
* },
|
|
450
|
+
* 'package.json',
|
|
451
|
+
* './dist/host',
|
|
452
|
+
* )
|
|
273
453
|
* // './dist/host/pkg.tmpl'
|
|
274
454
|
* ```
|
|
275
455
|
*/
|
|
276
|
-
export declare function locateHostSource(manifest:
|
|
456
|
+
export declare function locateHostSource(manifest: HostManifest | undefined, source: string, host: string): string | undefined;
|
|
277
457
|
|
|
278
458
|
/** One entry of the vendored host's `manifest.json` (server). */
|
|
279
459
|
export declare interface ManifestEntry {
|
|
@@ -283,7 +463,7 @@ export declare interface ManifestEntry {
|
|
|
283
463
|
}
|
|
284
464
|
|
|
285
465
|
/**
|
|
286
|
-
* The materialization entity (server) — the only impure
|
|
466
|
+
* The materialization entity (server) — the only impure environment in the
|
|
287
467
|
* package, writing a `Plan` to `node:fs` behind an explicit call.
|
|
288
468
|
*
|
|
289
469
|
* @remarks
|
|
@@ -293,10 +473,16 @@ export declare interface ManifestEntry {
|
|
|
293
473
|
* `content`, failing fast on any write error (`ScaffoldError('WRITE', …)`).
|
|
294
474
|
* `repair` is into-existing: it skips the vacancy check and writes ONLY the
|
|
295
475
|
* `missing` / `stale` artifacts an `Audit` names, leaving `aligned` ones
|
|
296
|
-
* untouched.
|
|
297
|
-
*
|
|
298
|
-
*
|
|
476
|
+
* untouched. Hydrated directory-shaped host entries are expanded into
|
|
477
|
+
* file-shaped artifacts, so canonical skills and agent configuration are
|
|
478
|
+
* audited and repaired file by file. `prune` deletes stale files under
|
|
479
|
+
* `target/.claude/agents/`, `target/.codex/agents/`, and `target/scripts/`
|
|
480
|
+
* that the vendored `host` does not name. After `destroy()`
|
|
299
481
|
* every method throws `DESTROYED`; teardown is idempotent, emitter last.
|
|
482
|
+
* Before the vacancy check or any write, `materialize` and `repair` require a
|
|
483
|
+
* structural `isPlan` match and a valid `validatePlan` result. Contextual
|
|
484
|
+
* overrides that are missing from the artifact set, host-owned, or target
|
|
485
|
+
* `package.json` therefore fail closed instead of being silently ignored.
|
|
300
486
|
*
|
|
301
487
|
* @remarks
|
|
302
488
|
* `host`-origin copies are MANIFEST-AWARE: when the resolved `host` root
|
|
@@ -356,7 +542,7 @@ export declare interface ManifestEntry {
|
|
|
356
542
|
* import { blueprint, blueprintToPlan } from '@orkestrel/scaffold'
|
|
357
543
|
* import { createMaterializer } from '@orkestrel/scaffold/server'
|
|
358
544
|
*
|
|
359
|
-
* const plan = blueprintToPlan(blueprint('budget', {
|
|
545
|
+
* const plan = blueprintToPlan(blueprint('budget', { src: ['core'] }))
|
|
360
546
|
* const materializer = createMaterializer()
|
|
361
547
|
* materializer.materialize(plan, './packages/budget-new')
|
|
362
548
|
* materializer.destroy()
|
|
@@ -368,7 +554,7 @@ export declare class Materializer implements MaterializerInterface {
|
|
|
368
554
|
get emitter(): EmitterInterface<MaterializerEventMap>;
|
|
369
555
|
materialize(plan: Plan, target: string): MaterializeResult;
|
|
370
556
|
repair(plan: Plan, audit: Audit, target: string): MaterializeResult;
|
|
371
|
-
prune(target: string): MaterializeResult;
|
|
557
|
+
prune(target: string, expected: Readonly<Record<string, string>>): MaterializeResult;
|
|
372
558
|
destroy(): void;
|
|
373
559
|
}
|
|
374
560
|
|
|
@@ -381,7 +567,7 @@ export declare interface MaterializeResult {
|
|
|
381
567
|
readonly removed: readonly string[];
|
|
382
568
|
}
|
|
383
569
|
|
|
384
|
-
/** `Materializer`'s push observation
|
|
570
|
+
/** `Materializer`'s push observation channel (AGENTS §13, server). */
|
|
385
571
|
export declare type MaterializerEventMap = {
|
|
386
572
|
readonly copy: readonly [path: string];
|
|
387
573
|
readonly write: readonly [path: string];
|
|
@@ -396,7 +582,7 @@ export declare interface MaterializerInterface {
|
|
|
396
582
|
readonly emitter: EmitterInterface<MaterializerEventMap>;
|
|
397
583
|
materialize(plan: Plan, target: string): MaterializeResult;
|
|
398
584
|
repair(plan: Plan, audit: Audit, target: string): MaterializeResult;
|
|
399
|
-
prune(target: string): MaterializeResult;
|
|
585
|
+
prune(target: string, expected: Snapshot): MaterializeResult;
|
|
400
586
|
destroy(): void;
|
|
401
587
|
}
|
|
402
588
|
|
|
@@ -418,23 +604,123 @@ export declare interface MaterializerOptions {
|
|
|
418
604
|
readonly error?: EmitterErrorHandler;
|
|
419
605
|
}
|
|
420
606
|
|
|
607
|
+
/** The compiled, closed data-only `MaterializerOptions` contract. */
|
|
608
|
+
export declare const materializerOptionsContract: ContractInterface<Readonly<{} & {
|
|
609
|
+
host?: string;
|
|
610
|
+
}>>;
|
|
611
|
+
|
|
612
|
+
/** Build the closed data-only `MaterializerOptions` shape. */
|
|
613
|
+
export declare function materializerOptionsShape(): ObjectShape<{
|
|
614
|
+
host: OptionalShape<StringShape>;
|
|
615
|
+
}, false>;
|
|
616
|
+
|
|
617
|
+
/** Maximum normalized package-catalog description length. */
|
|
618
|
+
export declare const MAX_CATALOG_DESCRIPTION_LENGTH = 500;
|
|
619
|
+
|
|
620
|
+
/** Maximum caller-controlled filesystem path depth accepted before filesystem work. */
|
|
621
|
+
export declare const MAX_FILESYSTEM_DEPTH = 64;
|
|
622
|
+
|
|
623
|
+
/** Maximum UTF-8 bytes parsed from one local package guide. */
|
|
624
|
+
export declare const MAX_GUIDE_BYTES = 5242880;
|
|
625
|
+
|
|
626
|
+
/** Maximum directory nesting accepted by one vendored-host traversal. */
|
|
627
|
+
export declare const MAX_HOST_DEPTH = 32;
|
|
628
|
+
|
|
629
|
+
/** Maximum filesystem entries accepted by one vendored-host traversal. */
|
|
630
|
+
export declare const MAX_HOST_ENTRIES = 4096;
|
|
631
|
+
|
|
632
|
+
/** Maximum UTF-8 bytes accepted in one portable filesystem path segment. */
|
|
633
|
+
export declare const MAX_PATH_SEGMENT_BYTES = 255;
|
|
634
|
+
|
|
635
|
+
/** Maximum caller-supplied endpoint characters inspected before URL allocation. */
|
|
636
|
+
export declare const MAX_SYNC_BASE_LENGTH = 2048;
|
|
637
|
+
|
|
638
|
+
/** Maximum portable Git branch characters accepted by the guide endpoint. */
|
|
639
|
+
export declare const MAX_SYNC_BRANCH_LENGTH = 255;
|
|
640
|
+
|
|
641
|
+
/** Maximum configurable cumulative response bytes retained by one Sync operation. */
|
|
642
|
+
export declare const MAX_SYNC_BUDGET = 104857600;
|
|
643
|
+
|
|
644
|
+
/** Maximum simultaneous upstream requests accepted by `Sync`. */
|
|
645
|
+
export declare const MAX_SYNC_CONCURRENCY = 64;
|
|
646
|
+
|
|
647
|
+
/** Maximum configurable dependencies or catalog entries for one Sync operation. */
|
|
648
|
+
export declare const MAX_SYNC_ITEMS = 1000;
|
|
649
|
+
|
|
650
|
+
/** Maximum response body accepted by `Sync`, in bytes. */
|
|
651
|
+
export declare const MAX_SYNC_LIMIT = 5242880;
|
|
652
|
+
|
|
653
|
+
/** Maximum retry count accepted by `Sync`. */
|
|
654
|
+
export declare const MAX_SYNC_RETRIES = 5;
|
|
655
|
+
|
|
656
|
+
/** Maximum per-request timeout accepted by `Sync`, in milliseconds. */
|
|
657
|
+
export declare const MAX_SYNC_TIMEOUT = 300000;
|
|
658
|
+
|
|
421
659
|
/**
|
|
422
|
-
*
|
|
423
|
-
*
|
|
660
|
+
* Remove the canonical Orkestrel scope from a dependency name.
|
|
661
|
+
*
|
|
662
|
+
* @param name - A dependency name.
|
|
663
|
+
* @returns Its unscoped member when canonical, otherwise the original name.
|
|
664
|
+
*/
|
|
665
|
+
export declare function packageShortName(name: string): string;
|
|
666
|
+
|
|
667
|
+
/** Parse a bounded dense array of host filesystem paths without invoking caller methods. */
|
|
668
|
+
export declare function parseFilesystemPaths(value: unknown, limit: number): readonly string[] | undefined;
|
|
669
|
+
|
|
670
|
+
/** Parse exact materializer options before allocating its emitter. */
|
|
671
|
+
export declare function parseMaterializerOptions(value: unknown): MaterializerOptions;
|
|
672
|
+
|
|
673
|
+
/** Parse a bounded dense array of portable paths without invoking caller methods. */
|
|
674
|
+
export declare function parsePortablePaths(value: unknown, limit: number): readonly string[] | undefined;
|
|
675
|
+
|
|
676
|
+
/** Parse and normalize one upstream HTTP(S) endpoint base. */
|
|
677
|
+
export declare function parseSyncBase(value: unknown): SyncBase;
|
|
678
|
+
|
|
679
|
+
/** Parse a safe Git branch path for the canonical raw-guide URL. */
|
|
680
|
+
export declare function parseSyncBranch(value: unknown): SyncBranch;
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Snapshot only declared guide references while enforcing per-file and cumulative byte limits.
|
|
684
|
+
*
|
|
685
|
+
* @param value - The caller-supplied guide content map.
|
|
686
|
+
* @param names - Exact dependency names eligible for selection.
|
|
687
|
+
* @param budget - Maximum cumulative UTF-8 bytes.
|
|
688
|
+
* @returns A frozen selected map, or `undefined` when no map was supplied.
|
|
689
|
+
*/
|
|
690
|
+
export declare function parseSyncCurrent(value: Readonly<Record<string, string>> | undefined, names: readonly string[], budget: number): Readonly<Record<string, string>> | undefined;
|
|
691
|
+
|
|
692
|
+
/** Parse and semantically validate dependency data before Sync performs network I/O. */
|
|
693
|
+
export declare function parseSyncDependencies(value: unknown, external: boolean): readonly Dependency[];
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Parse the exact bounded `SyncOptions` boundary before allocating resources.
|
|
697
|
+
*
|
|
698
|
+
* @param value - Caller-supplied options.
|
|
699
|
+
* @returns A fresh, validated options record.
|
|
700
|
+
*/
|
|
701
|
+
export declare function parseSyncOptions(value: unknown): SyncOptions;
|
|
702
|
+
|
|
703
|
+
/** Parse bounded exact transaction preconditions without invoking caller methods. */
|
|
704
|
+
export declare function parseWritePreconditions(value: unknown, limit: number): readonly WritePrecondition[] | undefined;
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* The prune-owned directories. Files outside these roots are never candidates
|
|
708
|
+
* for removal, including project-owned skills under `.agents/skills` and
|
|
709
|
+
* `.claude/skills`.
|
|
424
710
|
*
|
|
425
711
|
* @example
|
|
426
712
|
* ```ts
|
|
427
713
|
* import { PRUNE_DIRECTORIES } from '@orkestrel/scaffold/server'
|
|
428
714
|
*
|
|
429
|
-
* PRUNE_DIRECTORIES // ['.claude/agents', 'scripts']
|
|
715
|
+
* PRUNE_DIRECTORIES // ['.claude/agents', '.codex/agents', 'scripts']
|
|
430
716
|
* ```
|
|
431
717
|
*/
|
|
432
|
-
export declare const PRUNE_DIRECTORIES: readonly [
|
|
718
|
+
export declare const PRUNE_DIRECTORIES: readonly string[];
|
|
433
719
|
|
|
434
720
|
/**
|
|
435
721
|
* List the repo-relative POSIX paths under `target`'s prune directories
|
|
436
|
-
* (`.claude/agents`, `scripts`) that the vendored `host`
|
|
437
|
-
* declare — THE single source of truth for prune drift, consumed by both
|
|
722
|
+
* (`.claude/agents`, `.codex/agents`, `scripts`) that the vendored `host`
|
|
723
|
+
* allowlist does NOT declare — THE single source of truth for prune drift, consumed by both
|
|
438
724
|
* `Materializer.prune` (which deletes exactly these paths) and the bin's
|
|
439
725
|
* audit/preview UX (which now shows them honestly instead of a
|
|
440
726
|
* structurally-always-zero `audit.foreign`).
|
|
@@ -457,24 +743,56 @@ export declare const PRUNE_DIRECTORIES: readonly [".claude/agents", "scripts"];
|
|
|
457
743
|
*/
|
|
458
744
|
export declare function pruneTargets(target: string, host: string): readonly string[];
|
|
459
745
|
|
|
746
|
+
/**
|
|
747
|
+
* Read one contained file as exact lowercase hexadecimal bytes.
|
|
748
|
+
*
|
|
749
|
+
* @param root - The declared containing root.
|
|
750
|
+
* @param path - The root-relative file path.
|
|
751
|
+
* @param code - The coded failure for containment or reading.
|
|
752
|
+
* @param boundary - The boundary name used in diagnostics.
|
|
753
|
+
* @returns The exact file bytes encoded as lowercase hexadecimal.
|
|
754
|
+
*/
|
|
755
|
+
export declare function readFileHex(root: string, path: string, code: ScaffoldErrorCode, boundary: string, limit?: number): string;
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Read one contained physical file as bounded UTF-8 text.
|
|
759
|
+
*
|
|
760
|
+
* @param root - The declared containing root.
|
|
761
|
+
* @param path - The root-relative file path.
|
|
762
|
+
* @param code - The coded failure for containment or reading.
|
|
763
|
+
* @param boundary - The boundary name used in diagnostics.
|
|
764
|
+
* @returns The exact file bytes decoded as UTF-8 text.
|
|
765
|
+
*/
|
|
766
|
+
export declare function readFileText(root: string, path: string, code: ScaffoldErrorCode, boundary: string, limit?: number): string;
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Read bounded physical local guide mirrors for declared dependencies.
|
|
770
|
+
*
|
|
771
|
+
* @param target - The package root.
|
|
772
|
+
* @param dependencies - The declared dependencies whose mirrors are eligible.
|
|
773
|
+
* @returns Existing guide content keyed by dependency name.
|
|
774
|
+
*/
|
|
775
|
+
export declare function readGuideReferences(target: string, dependencies: readonly Dependency[]): Readonly<Record<string, string>>;
|
|
776
|
+
|
|
460
777
|
/**
|
|
461
778
|
* Read and validate a vendored host root's `manifest.json`, when present.
|
|
462
779
|
*
|
|
463
780
|
* @param host - The host root to probe.
|
|
464
|
-
* @returns The parsed
|
|
781
|
+
* @returns The parsed complete manifest, or `undefined` when `host` has no
|
|
465
782
|
* `manifest.json` — the raw-repo-root fallback (`Materializer` then maps
|
|
466
783
|
* an artifact's `source` to `host` 1:1, no vendored staging indirection).
|
|
467
784
|
* @throws `ScaffoldError('TARGET', …)` when `manifest.json` exists but is
|
|
468
|
-
* unreadable,
|
|
785
|
+
* unreadable, malformed, collision-prone, root-incomplete, or does not map
|
|
786
|
+
* bijectively and case-exactly onto real contained storage files.
|
|
469
787
|
*
|
|
470
788
|
* @example
|
|
471
789
|
* ```ts
|
|
472
790
|
* import { readHostManifest } from '@orkestrel/scaffold/server'
|
|
473
791
|
*
|
|
474
|
-
* readHostManifest('./dist/host') //
|
|
792
|
+
* readHostManifest('./dist/host') // HostManifest | undefined
|
|
475
793
|
* ```
|
|
476
794
|
*/
|
|
477
|
-
export declare function readHostManifest(host: string):
|
|
795
|
+
export declare function readHostManifest(host: string): HostManifest | undefined;
|
|
478
796
|
|
|
479
797
|
/**
|
|
480
798
|
* Read `target/package.json` text — the read that feeds `manifestToDependencies`.
|
|
@@ -495,15 +813,14 @@ export declare function readHostManifest(host: string): readonly ManifestEntry[]
|
|
|
495
813
|
export declare function readManifest(target: string): string;
|
|
496
814
|
|
|
497
815
|
/**
|
|
498
|
-
* Read a target's current
|
|
499
|
-
*
|
|
816
|
+
* Read a target's current bytes at a set of relative paths into a
|
|
817
|
+
* byte-exact hexadecimal {@link Snapshot} — the I/O that feeds `diffPlan`.
|
|
500
818
|
*
|
|
501
819
|
* @param target - The target directory to read from.
|
|
502
820
|
* @param paths - The plan-relative artifact paths to probe.
|
|
503
|
-
* @returns A
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
* placeholder for a missing file, so `diffPlan` reports it `missing`).
|
|
821
|
+
* @returns A snapshot keyed by path; each file maps to its exact lowercase
|
|
822
|
+
* hexadecimal bytes and a directly requested directory maps to `''`
|
|
823
|
+
* (presence only). An absent path is omitted entirely.
|
|
507
824
|
* @throws `ScaffoldError('TARGET', …)` when an EXISTING path fails to read
|
|
508
825
|
* (e.g. `EACCES` / `EPERM`) — carries the offending relative `path` (and
|
|
509
826
|
* the resolved `full` path) in `context`. An absent path is never an
|
|
@@ -514,10 +831,88 @@ export declare function readManifest(target: string): string;
|
|
|
514
831
|
* import { readTarget } from '@orkestrel/scaffold/server'
|
|
515
832
|
*
|
|
516
833
|
* readTarget('./packages/router', ['package.json', 'src/core/index.ts'])
|
|
517
|
-
* // { 'package.json': '
|
|
834
|
+
* // { 'package.json': '7b226e616d65223a…', 'src/core/index.ts': '6578706f7274…' }
|
|
518
835
|
* ```
|
|
519
836
|
*/
|
|
520
|
-
export declare function readTarget(target: string, paths: readonly string[]):
|
|
837
|
+
export declare function readTarget(target: string, paths: readonly string[]): Snapshot;
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* Map a manifest destination from an artifact's source prefix to its target prefix.
|
|
841
|
+
*
|
|
842
|
+
* @param artifact - The host artifact carrying the target path and optional source.
|
|
843
|
+
* @param destination - The matched manifest destination.
|
|
844
|
+
* @returns The exact target-relative path for the matched manifest file.
|
|
845
|
+
* @throws `ScaffoldError('INVALID', …)` when `destination` is outside the source prefix.
|
|
846
|
+
*/
|
|
847
|
+
export declare function remapArtifactPath(artifact: HostArtifact, destination: string): string;
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Atomically promote a staged sibling directory while preserving recoverable state.
|
|
851
|
+
*
|
|
852
|
+
* @param staging - The completed staging directory.
|
|
853
|
+
* @param target - The destination directory to replace.
|
|
854
|
+
* @param backup - The sibling path reserved for the prior target.
|
|
855
|
+
* @throws `ScaffoldError('WRITE', …)` with explicit `committed` and recovery paths.
|
|
856
|
+
*/
|
|
857
|
+
export declare function replaceDirectory(staging: string, target: string, backup: string): void;
|
|
858
|
+
|
|
859
|
+
/** Windows device names that remain reserved even when followed by an extension. */
|
|
860
|
+
export declare const RESERVED_PATH_SEGMENT_PATTERN: RegExp;
|
|
861
|
+
|
|
862
|
+
/** Existing repository metadata that a materialization target must never own. */
|
|
863
|
+
export declare const RESERVED_TARGET_PATH_PATTERN: RegExp;
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Resolve a path beneath a declared root and reject lexical or symlink escape.
|
|
867
|
+
*
|
|
868
|
+
* @param root - The containing filesystem root.
|
|
869
|
+
* @param path - The candidate path, relative or absolute.
|
|
870
|
+
* @param code - The coded error to raise on escape.
|
|
871
|
+
* @param boundary - The boundary name used in diagnostics.
|
|
872
|
+
* @returns The lexically resolved candidate after realpath-aware validation.
|
|
873
|
+
*/
|
|
874
|
+
export declare function resolveContainedPath(root: string, path: string, code: ScaffoldErrorCode, boundary: string): string;
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Resolve and completely preflight the canonical guide destinations a sync may write.
|
|
878
|
+
*
|
|
879
|
+
* @param guides - Structurally validated behind guide results.
|
|
880
|
+
* @param target - The repository root that owns `guides/src`.
|
|
881
|
+
* @returns Each guide paired with its contained destination.
|
|
882
|
+
* @throws `ScaffoldError('WRITE', ...)` before mutation for ownership, collision,
|
|
883
|
+
* containment, or existing filesystem-shape violations.
|
|
884
|
+
*/
|
|
885
|
+
export declare function resolveGuideWrites(guides: readonly GuideSync[], target: string): readonly GuideWrite[];
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Resolve a contained path whose existing ancestor chain contains no links.
|
|
889
|
+
*
|
|
890
|
+
* @param root - The trusted lexical and physical root.
|
|
891
|
+
* @param path - The portable root-relative path.
|
|
892
|
+
* @param code - The coded error to raise on failure.
|
|
893
|
+
* @param boundary - The boundary name used in diagnostics.
|
|
894
|
+
* @returns The contained destination.
|
|
895
|
+
* @throws `ScaffoldError` when containment fails or an ancestor is not a real directory.
|
|
896
|
+
*/
|
|
897
|
+
export declare function resolvePhysicalPath(root: string, path: string, code: ScaffoldErrorCode, boundary: string): string;
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* Resolve the deepest existing ancestor of a path through the real filesystem.
|
|
901
|
+
*
|
|
902
|
+
* @param path - The absolute or relative path to resolve.
|
|
903
|
+
* @returns A path whose existing prefix has been resolved through symlinks.
|
|
904
|
+
*/
|
|
905
|
+
export declare function resolveRealPath(path: string): string;
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* Restore quarantined files to their original target-relative paths.
|
|
909
|
+
*
|
|
910
|
+
* @param transaction - The nominal transaction that owns the quarantine and target.
|
|
911
|
+
* @param paths - The relative paths to restore, in their original move order.
|
|
912
|
+
* @throws `ScaffoldError('WRITE', …)` after attempting every reverse-order
|
|
913
|
+
* restoration when one or more files could not be restored.
|
|
914
|
+
*/
|
|
915
|
+
export declare function restoreFiles(transaction: WriteTransaction, paths: readonly string[]): void;
|
|
521
916
|
|
|
522
917
|
/**
|
|
523
918
|
* Filter a manifest record's entries down to `@orkestrel/`-prefixed keys with
|
|
@@ -539,6 +934,9 @@ export declare function readTarget(target: string, paths: readonly string[]): Re
|
|
|
539
934
|
*/
|
|
540
935
|
export declare function selectOrkestrelEntries(value: unknown): readonly (readonly [string, string])[];
|
|
541
936
|
|
|
937
|
+
/** Local configuration and credential-like paths that must never enter a vendored host. */
|
|
938
|
+
export declare const SENSITIVE_HOST_PATH_PATTERN: RegExp;
|
|
939
|
+
|
|
542
940
|
/**
|
|
543
941
|
* Stage the vendored host set (byte-preserved copies + `manifest.json`) from
|
|
544
942
|
* a repo root into an output directory — the BUILD-time primitive the
|
|
@@ -547,26 +945,20 @@ export declare function selectOrkestrelEntries(value: unknown): readonly (readon
|
|
|
547
945
|
* writes (via `hostRoot` / `readHostManifest`).
|
|
548
946
|
*
|
|
549
947
|
* @param root - The repo root every `paths` entry resolves against.
|
|
550
|
-
* @param out - The output directory to
|
|
948
|
+
* @param out - The output directory to replace after staging completes.
|
|
551
949
|
* @param paths - The repo-relative file/directory entries to stage; defaults
|
|
552
950
|
* to the package's own vendored set (`HOST_PATHS`) — a caller passes an
|
|
553
951
|
* explicit list only to stage an arbitrary/test set.
|
|
554
952
|
* @remarks
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
* deterministic on every build platform (Windows `stat` carries no execute
|
|
562
|
-
* bit); all vendored executables are shell scripts by construction.
|
|
563
|
-
* `manifest.json` is written LAST, as `entries` code-unit sorted by
|
|
564
|
-
* `destination`, tab-indented JSON with a trailing newline.
|
|
953
|
+
* Every source, path collision, and root/output relationship is preflighted
|
|
954
|
+
* before output mutation. Files are copied into a temporary sibling; the
|
|
955
|
+
* completed staging tree atomically replaces `out`, with rollback when the
|
|
956
|
+
* swap fails. The manifest records both sorted file `entries` and the
|
|
957
|
+
* complete sorted directory `roots` inventory so destructive consumers can
|
|
958
|
+
* distinguish a declared-empty root from a truncated manifest.
|
|
565
959
|
* @returns The written manifest's entries (`{ storage, destination, executable }`).
|
|
566
|
-
* @throws `ScaffoldError('TARGET', …)`
|
|
567
|
-
*
|
|
568
|
-
* destinations when two entries map to the same `storagePath` (the guard
|
|
569
|
-
* run BEFORE `manifest.json` is written).
|
|
960
|
+
* @throws `ScaffoldError('TARGET', …)` for an invalid/escaping source or path
|
|
961
|
+
* collision, and `ScaffoldError('WRITE', …)` for staging/swap failures.
|
|
570
962
|
*
|
|
571
963
|
* @example
|
|
572
964
|
* ```ts
|
|
@@ -582,7 +974,7 @@ export declare function stageHost(root: string, out: string, paths?: readonly st
|
|
|
582
974
|
* Map a repo-relative path to its vendored-host STAGING path, per the
|
|
583
975
|
* dotfile-mapping rule `stageHost` writes into `manifest.json`.
|
|
584
976
|
*
|
|
585
|
-
* @param path - The repo-relative source path (e.g. `.claude/agents/
|
|
977
|
+
* @param path - The repo-relative source path (e.g. `.claude/agents/reviewer.md`).
|
|
586
978
|
* @returns The mapped storage path: a leading-dot TOP-LEVEL FILE maps to
|
|
587
979
|
* `dotfiles/<name-without-dot>`; a leading-dot DIRECTORY segment loses its
|
|
588
980
|
* dot wherever it appears; an undotted path is unchanged.
|
|
@@ -592,7 +984,7 @@ export declare function stageHost(root: string, out: string, paths?: readonly st
|
|
|
592
984
|
* import { storagePath } from '@orkestrel/scaffold/server'
|
|
593
985
|
*
|
|
594
986
|
* storagePath('.gitignore') // 'dotfiles/gitignore'
|
|
595
|
-
* storagePath('.claude/agents/
|
|
987
|
+
* storagePath('.claude/agents/reviewer.md') // 'claude/agents/reviewer.md'
|
|
596
988
|
* storagePath('.github/workflows/ci.yml') // 'github/workflows/ci.yml'
|
|
597
989
|
* storagePath('AGENTS.md') // 'AGENTS.md'
|
|
598
990
|
* ```
|
|
@@ -665,13 +1057,25 @@ export declare class Sync implements SyncInterface {
|
|
|
665
1057
|
* alongside the existing `error` events for each degraded sub-fetch.
|
|
666
1058
|
*/
|
|
667
1059
|
catalog(): Promise<readonly CatalogEntry[]>;
|
|
668
|
-
pull(target: string): Promise<SyncReport>;
|
|
1060
|
+
pull(target: string, dependencies?: readonly Dependency[]): Promise<SyncReport>;
|
|
669
1061
|
write(report: SyncReport, target: string): Promise<readonly string[]>;
|
|
670
1062
|
destroy(): void;
|
|
671
1063
|
}
|
|
672
1064
|
|
|
1065
|
+
/** Safe ASCII branch alphabet accepted before Git ref-component validation. */
|
|
1066
|
+
export declare const SYNC_BRANCH_PATTERN: RegExp;
|
|
1067
|
+
|
|
1068
|
+
/** Mutable one-cell byte allowance shared by concurrent Sync readers. */
|
|
1069
|
+
export declare type SyncAllowance = Float64Array;
|
|
1070
|
+
|
|
1071
|
+
/** One normalized upstream HTTP(S) endpoint base accepted by `Sync`. */
|
|
1072
|
+
export declare type SyncBase = string;
|
|
1073
|
+
|
|
1074
|
+
/** One bounded Git-compatible branch path accepted by the guide endpoint. */
|
|
1075
|
+
export declare type SyncBranch = string;
|
|
1076
|
+
|
|
673
1077
|
/**
|
|
674
|
-
* `Sync`'s push observation
|
|
1078
|
+
* `Sync`'s push observation channel (AGENTS §13, server).
|
|
675
1079
|
*
|
|
676
1080
|
* @remarks
|
|
677
1081
|
* `package` fires once per `catalog()` entry processed; its `note` is the
|
|
@@ -691,6 +1095,13 @@ export declare type SyncEventMap = {
|
|
|
691
1095
|
readonly destroy: readonly [];
|
|
692
1096
|
};
|
|
693
1097
|
|
|
1098
|
+
/** Build the closed upstream-guide endpoint options shape. */
|
|
1099
|
+
export declare function syncGuideOptionsShape(): ObjectShape<{
|
|
1100
|
+
base: OptionalShape<StringShape>;
|
|
1101
|
+
branch: OptionalShape<StringShape>;
|
|
1102
|
+
timeout: OptionalShape<NumberShape>;
|
|
1103
|
+
}, false>;
|
|
1104
|
+
|
|
694
1105
|
/**
|
|
695
1106
|
* The upstream-synchronization contract (server) — the impure FETCH sibling
|
|
696
1107
|
* of `MaterializerInterface`.
|
|
@@ -700,7 +1111,7 @@ export declare interface SyncInterface {
|
|
|
700
1111
|
guides(deps: readonly Dependency[], current?: Readonly<Record<string, string>>): Promise<readonly GuideSync[]>;
|
|
701
1112
|
versions(deps: readonly Dependency[]): Promise<readonly VersionSync[]>;
|
|
702
1113
|
catalog(): Promise<readonly CatalogEntry[]>;
|
|
703
|
-
pull(target: string): Promise<SyncReport>;
|
|
1114
|
+
pull(target: string, dependencies?: readonly Dependency[]): Promise<SyncReport>;
|
|
704
1115
|
write(report: SyncReport, target: string): Promise<readonly string[]>;
|
|
705
1116
|
destroy(): void;
|
|
706
1117
|
}
|
|
@@ -730,22 +1141,104 @@ export declare interface SyncInterface {
|
|
|
730
1141
|
*/
|
|
731
1142
|
export declare interface SyncOptions {
|
|
732
1143
|
readonly guides?: {
|
|
733
|
-
readonly base?:
|
|
734
|
-
readonly branch?:
|
|
1144
|
+
readonly base?: SyncBase;
|
|
1145
|
+
readonly branch?: SyncBranch;
|
|
735
1146
|
readonly timeout?: number;
|
|
736
1147
|
};
|
|
737
1148
|
readonly registry?: {
|
|
738
|
-
readonly base?:
|
|
1149
|
+
readonly base?: SyncBase;
|
|
739
1150
|
readonly timeout?: number;
|
|
740
1151
|
};
|
|
741
1152
|
readonly concurrency?: number;
|
|
742
1153
|
readonly retries?: number;
|
|
743
1154
|
readonly strict?: boolean;
|
|
744
1155
|
readonly limit?: number;
|
|
1156
|
+
readonly items?: number;
|
|
1157
|
+
readonly budget?: number;
|
|
745
1158
|
readonly on?: EmitterHooks<SyncEventMap>;
|
|
746
1159
|
readonly error?: EmitterErrorHandler;
|
|
747
1160
|
}
|
|
748
1161
|
|
|
1162
|
+
/** The compiled, closed data-only `SyncOptions` contract. */
|
|
1163
|
+
export declare const syncOptionsContract: ContractInterface<Readonly<{} & {
|
|
1164
|
+
guides?: Readonly<{} & {
|
|
1165
|
+
base?: string;
|
|
1166
|
+
branch?: string;
|
|
1167
|
+
timeout?: number;
|
|
1168
|
+
}>;
|
|
1169
|
+
registry?: Readonly<{} & {
|
|
1170
|
+
base?: string;
|
|
1171
|
+
timeout?: number;
|
|
1172
|
+
}>;
|
|
1173
|
+
concurrency?: number;
|
|
1174
|
+
retries?: number;
|
|
1175
|
+
strict?: boolean;
|
|
1176
|
+
limit?: number;
|
|
1177
|
+
items?: number;
|
|
1178
|
+
budget?: number;
|
|
1179
|
+
}>>;
|
|
1180
|
+
|
|
1181
|
+
/** Build the closed data-only `SyncOptions` shape. */
|
|
1182
|
+
export declare function syncOptionsShape(): ObjectShape<{
|
|
1183
|
+
guides: OptionalShape<ObjectShape<{
|
|
1184
|
+
base: OptionalShape<StringShape>;
|
|
1185
|
+
branch: OptionalShape<StringShape>;
|
|
1186
|
+
timeout: OptionalShape<NumberShape>;
|
|
1187
|
+
}, false>>;
|
|
1188
|
+
registry: OptionalShape<ObjectShape<{
|
|
1189
|
+
base: OptionalShape<StringShape>;
|
|
1190
|
+
timeout: OptionalShape<NumberShape>;
|
|
1191
|
+
}, false>>;
|
|
1192
|
+
concurrency: OptionalShape<NumberShape>;
|
|
1193
|
+
retries: OptionalShape<NumberShape>;
|
|
1194
|
+
strict: OptionalShape<BooleanShape>;
|
|
1195
|
+
limit: OptionalShape<NumberShape>;
|
|
1196
|
+
items: OptionalShape<NumberShape>;
|
|
1197
|
+
budget: OptionalShape<NumberShape>;
|
|
1198
|
+
}, false>;
|
|
1199
|
+
|
|
1200
|
+
/** Build the closed registry endpoint options shape. */
|
|
1201
|
+
export declare function syncRegistryOptionsShape(): ObjectShape<{
|
|
1202
|
+
base: OptionalShape<StringShape>;
|
|
1203
|
+
timeout: OptionalShape<NumberShape>;
|
|
1204
|
+
}, false>;
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* Assemble one synchronization report from already ordered guide and version outcomes.
|
|
1208
|
+
*
|
|
1209
|
+
* @param target - The target package root.
|
|
1210
|
+
* @param guides - Guide outcomes.
|
|
1211
|
+
* @param versions - Version outcomes.
|
|
1212
|
+
* @returns The derived whole report.
|
|
1213
|
+
*/
|
|
1214
|
+
export declare function syncReportOf(target: string, guides: readonly GuideSync[], versions: readonly VersionSync[]): SyncReport;
|
|
1215
|
+
|
|
1216
|
+
/**
|
|
1217
|
+
* Revalidate one captured physical-directory identity without following links.
|
|
1218
|
+
*
|
|
1219
|
+
* @param anchor - The captured path, device, and inode.
|
|
1220
|
+
* @param boundary - The boundary name used in diagnostics.
|
|
1221
|
+
* @throws `ScaffoldError('WRITE', ...)` when the directory is missing or changed.
|
|
1222
|
+
*/
|
|
1223
|
+
export declare function validateWriteAnchor(anchor: WriteAnchor, boundary: string): void;
|
|
1224
|
+
|
|
1225
|
+
/**
|
|
1226
|
+
* Revalidate every private directory owned by a write transaction.
|
|
1227
|
+
*
|
|
1228
|
+
* @param transaction - The nominal transaction state.
|
|
1229
|
+
* @throws `ScaffoldError('WRITE', ...)` when any private directory changed.
|
|
1230
|
+
*/
|
|
1231
|
+
export declare function validateWriteDirectories(transaction: WriteTransaction): void;
|
|
1232
|
+
|
|
1233
|
+
/**
|
|
1234
|
+
* Revalidate the transaction target against its original or transaction-owned identity.
|
|
1235
|
+
*
|
|
1236
|
+
* @param transaction - The nominal transaction state.
|
|
1237
|
+
* @param owned - A target directory created by the current commit.
|
|
1238
|
+
* @throws `ScaffoldError('WRITE', ...)` when the target identity changed.
|
|
1239
|
+
*/
|
|
1240
|
+
export declare function validateWriteTarget(transaction: WriteTransaction, owned: WriteAnchor | undefined): void;
|
|
1241
|
+
|
|
749
1242
|
/**
|
|
750
1243
|
* The vendored set of destination-relative paths under `directory` (one of
|
|
751
1244
|
* `PRUNE_DIRECTORIES`) that `pruneTargets` must NOT report — read from the
|
|
@@ -771,9 +1264,64 @@ export declare interface SyncOptions {
|
|
|
771
1264
|
* ```ts
|
|
772
1265
|
* import { vendoredPruneSet } from '@orkestrel/scaffold/server'
|
|
773
1266
|
*
|
|
774
|
-
* vendoredPruneSet('./dist/host', '.claude/agents') // Set { '.claude/agents/
|
|
1267
|
+
* vendoredPruneSet('./dist/host', '.claude/agents') // Set { '.claude/agents/reviewer.md', … }
|
|
775
1268
|
* ```
|
|
776
1269
|
*/
|
|
777
1270
|
export declare function vendoredPruneSet(host: string, directory: string): ReadonlySet<string>;
|
|
778
1271
|
|
|
1272
|
+
/** Exact SHA-256 digest accepted by write preconditions. */
|
|
1273
|
+
export declare const WRITE_DIGEST_PATTERN: RegExp;
|
|
1274
|
+
|
|
1275
|
+
/** A physical directory identity captured across a write transaction. */
|
|
1276
|
+
export declare interface WriteAnchor {
|
|
1277
|
+
readonly path: string;
|
|
1278
|
+
readonly device: number;
|
|
1279
|
+
readonly inode: number;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/** Anchored result of creating a physical directory path one segment at a time. */
|
|
1283
|
+
export declare interface WriteDirectoryResult {
|
|
1284
|
+
readonly anchor: WriteAnchor;
|
|
1285
|
+
readonly created: readonly WriteAnchor[];
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
/** One destination snapshot required to remain stable through a write commit. */
|
|
1289
|
+
export declare interface WriteExpectation {
|
|
1290
|
+
readonly path: string;
|
|
1291
|
+
readonly shape: 'absent' | 'file' | 'directory';
|
|
1292
|
+
readonly device?: number;
|
|
1293
|
+
readonly inode?: number;
|
|
1294
|
+
readonly modified?: number;
|
|
1295
|
+
readonly size?: number;
|
|
1296
|
+
readonly digest?: string;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
/** Caller-observed destination state that a write transaction must still match. */
|
|
1300
|
+
export declare interface WritePrecondition {
|
|
1301
|
+
readonly path: string;
|
|
1302
|
+
readonly shape: 'absent' | 'file';
|
|
1303
|
+
readonly digest?: string;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
/**
|
|
1307
|
+
* Nominal, same-volume write-transaction state. Construction derives every
|
|
1308
|
+
* filesystem path from a target and portable relative paths; callers cannot
|
|
1309
|
+
* supply a deletion root or mutate captured arrays.
|
|
1310
|
+
*/
|
|
1311
|
+
export declare class WriteTransaction {
|
|
1312
|
+
#private;
|
|
1313
|
+
constructor(token: unknown, target: string, root: string, stage: string, backup: string, expectations: readonly WriteExpectation[], parents: readonly WriteAnchor[], directories: readonly WriteAnchor[], anchor: WriteAnchor, existing: WriteAnchor | undefined);
|
|
1314
|
+
/** Create private staging state and snapshot every destination before mutation. */
|
|
1315
|
+
static create(target: string, paths: readonly string[], preconditions?: readonly WritePrecondition[]): WriteTransaction;
|
|
1316
|
+
get target(): string;
|
|
1317
|
+
get root(): string;
|
|
1318
|
+
get stage(): string;
|
|
1319
|
+
get backup(): string;
|
|
1320
|
+
get expectations(): readonly WriteExpectation[];
|
|
1321
|
+
get parents(): readonly WriteAnchor[];
|
|
1322
|
+
get directories(): readonly WriteAnchor[];
|
|
1323
|
+
get anchor(): WriteAnchor;
|
|
1324
|
+
get existing(): WriteAnchor | undefined;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
779
1327
|
export { }
|