@avantf/dsh-plugin-base 0.3.1 → 0.4.0

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.
Files changed (98) hide show
  1. package/README.md +29 -15
  2. package/dist/bootstrap.d.ts +3 -2
  3. package/dist/bootstrap.d.ts.map +1 -1
  4. package/dist/bootstrap.js +3 -2
  5. package/dist/compat.d.ts +2 -2
  6. package/dist/compat.js +5 -5
  7. package/dist/errors.d.ts +6 -1
  8. package/dist/errors.d.ts.map +1 -1
  9. package/dist/index.d.ts +23 -9
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +45 -22
  12. package/dist/interface.d.ts +296 -23
  13. package/dist/interface.d.ts.map +1 -1
  14. package/dist/interface.js +206 -8
  15. package/dist/interface_gate.d.ts +20 -6
  16. package/dist/interface_gate.d.ts.map +1 -1
  17. package/dist/interface_gate.js +37 -7
  18. package/dist/internal.d.ts +26 -1
  19. package/dist/internal.d.ts.map +1 -1
  20. package/dist/internal.js +27 -1
  21. package/dist/kit/family.d.ts +2 -2
  22. package/dist/kit/family.js +3 -3
  23. package/dist/kit/index.d.ts +5 -1
  24. package/dist/kit/index.d.ts.map +1 -1
  25. package/dist/kit/index.js +5 -1
  26. package/dist/kit/logger.d.ts +1 -1
  27. package/dist/kit/logger.js +1 -1
  28. package/dist/kit/prompt_files.d.ts +37 -3
  29. package/dist/kit/prompt_files.d.ts.map +1 -1
  30. package/dist/kit/prompt_files.js +45 -0
  31. package/dist/kit/typert.d.ts +2 -2
  32. package/dist/kit/wellformed.d.ts +79 -0
  33. package/dist/kit/wellformed.d.ts.map +1 -0
  34. package/dist/kit/wellformed.js +155 -0
  35. package/dist/layout.d.ts +17 -2
  36. package/dist/layout.d.ts.map +1 -1
  37. package/dist/layout.js +15 -5
  38. package/dist/lint.d.ts.map +1 -1
  39. package/dist/lint.js +2 -2
  40. package/dist/lock.d.ts +18 -0
  41. package/dist/lock.d.ts.map +1 -1
  42. package/dist/lock.js +77 -10
  43. package/dist/net.d.ts +106 -3
  44. package/dist/net.d.ts.map +1 -1
  45. package/dist/net.js +128 -30
  46. package/dist/providers/archive.d.ts.map +1 -1
  47. package/dist/providers/archive.js +108 -20
  48. package/dist/providers/model.d.ts +26 -3
  49. package/dist/providers/model.d.ts.map +1 -1
  50. package/dist/providers/model.js +159 -32
  51. package/dist/providers/npm.d.ts +5 -0
  52. package/dist/providers/npm.d.ts.map +1 -1
  53. package/dist/providers/npm.js +62 -21
  54. package/dist/provisioner.d.ts.map +1 -1
  55. package/dist/provisioner.js +128 -31
  56. package/dist/state.d.ts.map +1 -1
  57. package/dist/state.js +8 -3
  58. package/dist/tar.d.ts +7 -0
  59. package/dist/tar.d.ts.map +1 -1
  60. package/dist/tar.js +12 -5
  61. package/dist/types.d.ts +11 -1
  62. package/dist/types.d.ts.map +1 -1
  63. package/dist/zip.d.ts.map +1 -1
  64. package/dist/zip.js +10 -1
  65. package/package.json +18 -19
  66. package/dist/artifact.js.map +0 -1
  67. package/dist/bootstrap.js.map +0 -1
  68. package/dist/cli.js.map +0 -1
  69. package/dist/compat.js.map +0 -1
  70. package/dist/conformance.js.map +0 -1
  71. package/dist/errors.js.map +0 -1
  72. package/dist/fs.js.map +0 -1
  73. package/dist/index.js.map +0 -1
  74. package/dist/integrity.js.map +0 -1
  75. package/dist/interface.js.map +0 -1
  76. package/dist/interface_gate.js.map +0 -1
  77. package/dist/internal.js.map +0 -1
  78. package/dist/kit/family.js.map +0 -1
  79. package/dist/kit/index.js.map +0 -1
  80. package/dist/kit/logger.js.map +0 -1
  81. package/dist/kit/prompt_files.js.map +0 -1
  82. package/dist/kit/typert.js.map +0 -1
  83. package/dist/layout.js.map +0 -1
  84. package/dist/lint.js.map +0 -1
  85. package/dist/lock.js.map +0 -1
  86. package/dist/manifest.js.map +0 -1
  87. package/dist/net.js.map +0 -1
  88. package/dist/package-name.js.map +0 -1
  89. package/dist/preset.js.map +0 -1
  90. package/dist/providers/archive.js.map +0 -1
  91. package/dist/providers/model.js.map +0 -1
  92. package/dist/providers/npm.js.map +0 -1
  93. package/dist/provisioner.js.map +0 -1
  94. package/dist/semver.js.map +0 -1
  95. package/dist/state.js.map +0 -1
  96. package/dist/tar.js.map +0 -1
  97. package/dist/types.js.map +0 -1
  98. package/dist/zip.js.map +0 -1
package/dist/interface.js CHANGED
@@ -1,15 +1,19 @@
1
1
  /**
2
2
  * The integer interface generation this module implements.
3
3
  *
4
- * `1` is the first frozen generation: the surface recorded by `api/interface-v1.json`. The file name's
5
- * `N` and this constant are the SAME fact — `test/public-surface.spec.ts` asserts that the snapshot for
6
- * this constant exists and that its `interfaceVersion` field equals it, so "the JSON says v2, the
7
- * constant says 1" cannot happen. Bump it (and add `api/interface-vN.json`) only for an interface
8
- * change (INTERFACE.md §1); a behaviour change or a fix does NOT touch it. The plugins bake this number
9
- * into their artifacts and compare it, at startup, with the number the base they loaded reports — a
10
- * difference is a warning and a capability-level degradation, never a refused mount.
4
+ * `3` is the CURRENT generation: the v2 surface MINUS the 18 zero-consumer members that moved to
5
+ * `./internal` (INTERFACE.md §9) and PLUS the one newly-named compat type (`ServiceContract`). The
6
+ * file name's `N` and this constant are the SAME fact — `test/public-surface.spec.ts` asserts that the
7
+ * snapshot for this constant exists and that its `interfaceVersion` field equals it, so "the JSON says
8
+ * v4, the constant says 3" cannot happen. Bump it (and add `api/interface-vN.json`) only for an
9
+ * interface change (INTERFACE.md §1); a behaviour change or a fix does NOT touch it. The plugins bake
10
+ * this number into their artifacts and compare it, at startup, with the number the base they loaded
11
+ * reports — a difference is a warning and a capability-level degradation, never a refused mount.
12
+ *
13
+ * `2` and `1` are the earlier frozen generations (`api/interface-v2.json`, `api/interface-v1.json`).
14
+ * They stay in the tree as those generations' records and as the types the plugins still import.
11
15
  */
12
- export const INTERFACE_VERSION = 1;
16
+ export const INTERFACE_VERSION = 3;
13
17
  /**
14
18
  * Every VALUE name of the v1 `.` surface, in {@link BaseRuntimeV1} declaration order.
15
19
  *
@@ -133,4 +137,198 @@ export const TYPE_NAMES_V1 = [
133
137
  'InterfaceVerdict',
134
138
  'InterfaceRequirement',
135
139
  ];
140
+ /**
141
+ * Every VALUE name of the FROZEN v2 `.` surface, in {@link BaseRuntimeV2} declaration order: the v1
142
+ * list verbatim, then the two well-formed-text members.
143
+ *
144
+ * The spread is the point — an additive generation states itself as "v1 plus these", so a member that
145
+ * disappears from v1 cannot quietly disappear from v2 too. The `satisfies` clause still checks the
146
+ * whole v2 `keyof`, so a member added to the interface and not to this list is a compile error.
147
+ */
148
+ export const VALUE_NAMES_V2 = [
149
+ ...VALUE_NAMES_V1,
150
+ 'wellFormedText',
151
+ 'wellFormedDeep',
152
+ ];
153
+ /**
154
+ * Every TYPE name of the FROZEN v2 `.` surface, in {@link BaseTypeSurfaceV2} declaration order.
155
+ *
156
+ * v2 adds no named type, so this is the v1 list; the `satisfies` clause still ties it to
157
+ * {@link BaseTypeSurfaceV2}, and the gate asserts v1 ⊆ v2 for both halves.
158
+ */
159
+ export const TYPE_NAMES_V2 = [...TYPE_NAMES_V1];
160
+ /**
161
+ * The VALUE names v3 shed from `.` — the frozen PRUNE list (INTERFACE.md §9).
162
+ *
163
+ * Every one of them has zero consumers across the two plugin trees' non-test source and scripts (the
164
+ * proof is `PUBLIC-SURFACE`'s cross-tree check), and every one of them now lives on `./internal`
165
+ * instead. This list is not documentation: `test/public-surface.spec.ts` asserts
166
+ * `VALUE_NAMES_V2 === [...VALUE_NAMES_V3, ...PRUNED_VALUE_NAMES]` (both directions), so a v4 cannot
167
+ * quietly drop a name that is neither in the surface nor on this list.
168
+ */
169
+ export const PRUNED_VALUE_NAMES = [
170
+ 'CAPABILITIES',
171
+ 'COMPAT_PROBE_TOOL',
172
+ 'DEFAULT_DEADLINE_MS',
173
+ 'NPM_PACKAGE_KIND',
174
+ 'checkInterval',
175
+ 'checkServices',
176
+ 'createPluginLogger',
177
+ 'declaredSchemaKeys',
178
+ 'endpointId',
179
+ 'fieldSymbol',
180
+ 'floorOf',
181
+ 'normalizeOnMissing',
182
+ 'npmPackageProvider',
183
+ 'probeToolsRegistry',
184
+ 'probeTypertRegistry',
185
+ 'resolveRuntimeVersion',
186
+ 'resultSymbol',
187
+ 'strictCodec',
188
+ ];
189
+ /**
190
+ * Every VALUE name of the CURRENT (v3) `.` surface, in {@link BaseRuntimeV3} declaration order.
191
+ *
192
+ * NOT a spread of v2: v3 prunes, so it is stated as itself. The `satisfies` clause ties it to
193
+ * {@link BaseRuntimeV3}, and the gate asserts the whole `keyof`, so a member added to the interface
194
+ * and not to this list is a compile error.
195
+ */
196
+ export const VALUE_NAMES_V3 = [
197
+ 'INTERFACE_VERSION',
198
+ 'COMPAT_PREFIX',
199
+ 'BUILD_VERSIONS_FILE',
200
+ 'ITEM_SCHEMA_VERSION',
201
+ 'checkInterface',
202
+ 'readInterfaceRequirement',
203
+ 'provision',
204
+ 'compatReport',
205
+ 'registerMegaphone',
206
+ 'schemaNamesFrom',
207
+ 'verifyRegisteredFaces',
208
+ 'readDeclaredVersions',
209
+ 'readBuildVersions',
210
+ 'readRuntimeVersions',
211
+ 'toolProbeDeclaration',
212
+ 'verdictOf',
213
+ 'gatherEvidence',
214
+ 'PromptFiles',
215
+ 'familyHome',
216
+ 'familyToolsDir',
217
+ 'familyModelsDir',
218
+ 'resolveDataHome',
219
+ 'expandHome',
220
+ 'wellFormedText',
221
+ 'wellFormedDeep',
222
+ 'createProvisioner',
223
+ 'ProvisionError',
224
+ 'reasonOf',
225
+ 'binaryArchiveProvider',
226
+ 'BINARY_ARCHIVE_KIND',
227
+ 'modelCacheProvider',
228
+ 'MODEL_CACHE_KIND',
229
+ ];
230
+ /**
231
+ * The TYPE names v3 NAMES for the first time — they were reachable through `export *` in v2 but were
232
+ * never declared in {@link BaseTypeSurfaceV2}, so they had no entry and no promise. v3's explicit
233
+ * `.` states them; `ServiceContract` is the load-bearing one (mem's compat spec imports it by name).
234
+ */
235
+ export const ADDED_TYPE_NAMES = [
236
+ 'ArchivePack',
237
+ 'AtStartup',
238
+ 'AtUse',
239
+ 'BinaryArchiveSpec',
240
+ 'BuiltinKind',
241
+ 'Disposable',
242
+ 'ModelCacheLayout',
243
+ 'ModelCacheSpec',
244
+ 'PlanAction',
245
+ 'ProvisionItem',
246
+ 'ReportAction',
247
+ 'ResourceSource',
248
+ 'ServiceContract',
249
+ ];
250
+ /**
251
+ * The TYPE names v3 sheds: the types that existed only for the values that moved to `./internal`.
252
+ * They live on `./internal` too, so the move is complete on both halves of the surface.
253
+ */
254
+ export const PRUNED_TYPE_NAMES = [
255
+ 'PluginLogger',
256
+ 'PluginLoggerHost',
257
+ 'PluginLoggerOptions',
258
+ 'StrictCodec',
259
+ ];
260
+ /**
261
+ * Every TYPE name of the CURRENT (v3) `.` surface, in {@link BaseTypeSurfaceV3} declaration order.
262
+ *
263
+ * v3 is a pruning generation, so this is stated explicitly rather than spread. The gate asserts it
264
+ * partitions v2 together with {@link PRUNED_TYPE_NAMES} and {@link ADDED_TYPE_NAMES}.
265
+ */
266
+ export const TYPE_NAMES_V3 = [
267
+ 'ArchivePack',
268
+ 'BinaryArchiveSpec',
269
+ 'ModelCacheLayout',
270
+ 'ModelCacheSpec',
271
+ 'ProvisionCode',
272
+ 'AtStartup',
273
+ 'AtUse',
274
+ 'BuiltinKind',
275
+ 'Disposable',
276
+ 'EnsureOptions',
277
+ 'InstallContext',
278
+ 'InstallManifest',
279
+ 'ItemPolicy',
280
+ 'Kind',
281
+ 'Manifest',
282
+ 'MirrorPolicy',
283
+ 'OnMissing',
284
+ 'Plan',
285
+ 'PlanAction',
286
+ 'PlanEntry',
287
+ 'PlanOptions',
288
+ 'ProbeResult',
289
+ 'ProgressEvent',
290
+ 'Provider',
291
+ 'ProviderContext',
292
+ 'ProviderPlan',
293
+ 'ProvisionEvent',
294
+ 'ProvisionFs',
295
+ 'ProvisionItem',
296
+ 'ProvisionLock',
297
+ 'ProvisionLogger',
298
+ 'ProvisionPolicy',
299
+ 'ProvisionReport',
300
+ 'ProvisionReportEntry',
301
+ 'ProvisionStatus',
302
+ 'Provisioner',
303
+ 'ProvisionerExperimental',
304
+ 'ProvisionerOptions',
305
+ 'PrunePolicy',
306
+ 'PruneReport',
307
+ 'PublishMeta',
308
+ 'ReportAction',
309
+ 'Resolved',
310
+ 'ResourceHandle',
311
+ 'ResourceIdentity',
312
+ 'ResourceSource',
313
+ 'ResourceState',
314
+ 'Startup',
315
+ 'CompatContext',
316
+ 'CompatEvidence',
317
+ 'CompatLine',
318
+ 'CompatLogger',
319
+ 'CompatReportWords',
320
+ 'CompatSpec',
321
+ 'CompatVerdict',
322
+ 'ProbeOutcome',
323
+ 'ServiceContract',
324
+ 'ServiceProbe',
325
+ 'DataHomeInput',
326
+ 'LoadedPromptText',
327
+ 'PromptFileSpec',
328
+ 'PromptFilesIo',
329
+ 'PromptFilesLogger',
330
+ 'PromptFilesOptions',
331
+ 'InterfaceRequirement',
332
+ 'InterfaceVerdict',
333
+ ];
136
334
  //# sourceMappingURL=interface.js.map
@@ -13,10 +13,13 @@ export interface InterfaceRequirement {
13
13
  /**
14
14
  * What {@link checkInterface} decided.
15
15
  *
16
- * `ok` — both sides were readable and name the same generation; use the base normally.
17
- * `incompatible` — both sides were readable and differ (either direction); a caller must NOT use the
18
- * base's shared capabilities. The family invariant still holds: this is a degradation, never a
19
- * refused mount.
16
+ * `ok` — both sides were readable and the loaded base can serve this build: either the generations are
17
+ * equal, or the loaded base is NEWER and the newer generation provably keeps every member a consumer
18
+ * uses (the additive superset for v1 → v2; the pruning proof for v2 → v3).
19
+ * Use the base normally; if {@link InterfaceVerdict.warning} is set, log it as one WARNING first.
20
+ * `incompatible` — both sides were readable and the loaded base is OLDER than the build, so the members
21
+ * this build requires may be missing; a caller must NOT use the base's shared capabilities. The family
22
+ * invariant still holds: this is a degradation, never a refused mount.
20
23
  * `cannot-tell` — at least one side could not be read. "Cannot tell" is never "incompatible": the
21
24
  * caller warns and uses the base normally.
22
25
  */
@@ -31,12 +34,23 @@ export interface InterfaceVerdict {
31
34
  * it is. The caller owns the wording around it (prefix, "mounting anyway", …).
32
35
  */
33
36
  readonly reason?: string;
37
+ /**
38
+ * One sentence to log as a WARNING although the verdict is `ok` — present only for the accepted
39
+ * `loaded > required` case (the newer-but-compatible rule), absent otherwise. It is separate from
40
+ * {@link InterfaceVerdict.reason} because "ok but notable" and "not ok" are different outcomes: a
41
+ * caller that logs `reason` only for a non-`ok` status stays correct, and the additive case still
42
+ * gets its WARNING line.
43
+ */
44
+ readonly warning?: string;
34
45
  }
35
46
  /**
36
47
  * Compare the interface generation a caller requires with the one a loaded module reports.
37
48
  *
38
- * Pure, bidirectional and total: it reads exactly one property, guards that read, and answers a
39
- * verdict for every input. Both arguments are trusted only as far as they can be read.
49
+ * Pure, total and asymmetric: it reads exactly one property, guards that read, and answers a verdict
50
+ * for every input. Both arguments are trusted only as far as they can be read. `loaded < required` is
51
+ * `incompatible` (the caller may need members that are gone/never existed); `loaded > required` is `ok`
52
+ * plus a `warning`, on the generation-safety proof described in this module's header; equal is plain
53
+ * `ok`.
40
54
  *
41
55
  * @param required - the generation the caller was built for (its baked `interfaceVersion`).
42
56
  * @param module - the loaded base module; only `INTERFACE_VERSION` is read.
@@ -1 +1 @@
1
- {"version":3,"file":"interface_gate.d.ts","sourceRoot":"","sources":["../src/interface_gate.ts"],"names":[],"mappings":"AA4BA;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,qFAAqF;IACrF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAClC;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,cAAc,GAAG,aAAa,CAAA;IACtD,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/C,gBAAgB,CAiClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAa5F"}
1
+ {"version":3,"file":"interface_gate.d.ts","sourceRoot":"","sources":["../src/interface_gate.ts"],"names":[],"mappings":"AA6CA;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,qFAAqF;IACrF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAClC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,cAAc,GAAG,aAAa,CAAA;IACtD,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/C,gBAAgB,CA2ClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAa5F"}
@@ -18,9 +18,26 @@
18
18
  * - **It never throws.** A gate that throws while deciding would reject a mount it is not allowed to
19
19
  * reject. A module whose property access throws (the "hostile module" the plugins' loaders are
20
20
  * built to survive) reads as "reports no INTERFACE_VERSION", i.e. `cannot-tell`.
21
- * - **It is bidirectional.** A plugin written for a NEWER generation than the base it loaded is as
22
- * incompatible as one written for an older one; "in range but another generation" is the one case
23
- * `supportedRange` cannot see, so this gate must see it in both directions.
21
+ * - **Only MISSING members are unsafe.** The two directions are NOT symmetric. A build that needs a
22
+ * generation the loaded base has not reached (`loaded < required`) may ask for members that do not
23
+ * exist — that is `incompatible`. A build that meets a NEWER base (`loaded > required`) is the
24
+ * family's safe case: a generation must not take away a member an older build CONSUMES. That case
25
+ * is `ok` + a `warning`, never a degradation — a new generation must not downgrade anyone, which is
26
+ * the whole point of the rule. "In range but another generation" is the one case `supportedRange`
27
+ * cannot see, so this gate must see it.
28
+ *
29
+ * The "does not take away a consumed member" premise is not prose: it is asserted mechanically where
30
+ * the generations are declared, and the shape of the proof depends on the kind of transition:
31
+ *
32
+ * - an ADDITIVE generation states `Vn extends Vn-1` and the snapshot gate checks the name superset
33
+ * (`v1 → v2`, INTERFACE.md §5);
34
+ * - a PRUNING generation (`v2 → v3`, INTERFACE.md §9) instead proves `Vn-1 = Vn ⊎ PRUNED` plus that
35
+ * every `PRUNED` name has zero consumers across the two plugin trees
36
+ * (`test/public-surface.spec.ts`), and `test/interface_gate.spec.ts` pins it against the real module.
37
+ *
38
+ * The `loaded > required` branch below is admissible ONLY while one of those proofs holds. A generation
39
+ * that drops a name WITH a consumer would fail the pruning proof, and that is the signal it must not be
40
+ * waved through as `ok`.
24
41
  *
25
42
  * @module @avantf/dsh-plugin-base/interface_gate
26
43
  */
@@ -28,8 +45,11 @@ import { readFileSync } from 'node:fs';
28
45
  /**
29
46
  * Compare the interface generation a caller requires with the one a loaded module reports.
30
47
  *
31
- * Pure, bidirectional and total: it reads exactly one property, guards that read, and answers a
32
- * verdict for every input. Both arguments are trusted only as far as they can be read.
48
+ * Pure, total and asymmetric: it reads exactly one property, guards that read, and answers a verdict
49
+ * for every input. Both arguments are trusted only as far as they can be read. `loaded < required` is
50
+ * `incompatible` (the caller may need members that are gone/never existed); `loaded > required` is `ok`
51
+ * plus a `warning`, on the generation-safety proof described in this module's header; equal is plain
52
+ * `ok`.
33
53
  *
34
54
  * @param required - the generation the caller was built for (its baked `interfaceVersion`).
35
55
  * @param module - the loaded base module; only `INTERFACE_VERSION` is read.
@@ -62,12 +82,22 @@ export function checkInterface(required, module) {
62
82
  }
63
83
  if (loadedVersion === required)
64
84
  return { status: 'ok', required, loaded: loadedVersion };
85
+ if (loadedVersion > required) {
86
+ // The SAFE direction, admitted only on the mechanical superset proof (see the module header):
87
+ // every member this older build requires still exists, so the base is used normally — the newer
88
+ // generation's OWN members simply go unused by this build.
89
+ return {
90
+ status: 'ok',
91
+ required,
92
+ loaded: loadedVersion,
93
+ warning: `the loaded base reports interface generation ${String(loadedVersion)}, newer than the ${String(required)} this build was written for (host base is newer); WARNING — generations are pure additions, so every member this build requires is present and the base is judged usable`,
94
+ };
95
+ }
65
96
  return {
66
97
  status: 'incompatible',
67
98
  required,
68
99
  loaded: loadedVersion,
69
- reason: `this build was written for interface generation ${String(required)} but the loaded base reports ${String(loadedVersion)}`
70
- + ` (${loadedVersion > required ? 'newer' : 'older'} generation); the base's shared capabilities are not used`,
100
+ reason: `this build was written for interface generation ${String(required)} but the loaded base reports ${String(loadedVersion)} (older generation); the members this build requires may be missing, so the base's shared capabilities are not used`,
71
101
  };
72
102
  }
73
103
  /**
@@ -1,5 +1,21 @@
1
1
  /**
2
2
  * Framework building blocks shared by the core and the entry points.
3
+ *
4
+ * `./internal` is the second published subpath beside `.` and it carries everything the compatibility
5
+ * promise deliberately does NOT cover (root `AGENTS.md`; `docs/INTERFACE.md` §2/§5):
6
+ *
7
+ * - the framework's own seams (fs, locks, archives, layout, lint, semver …), and
8
+ * - the **composition pieces** of the pieces `.` does export: the individual probes and evidence
9
+ * helpers `compat.gatherEvidence` is built from, the provisioner's policy helpers and constants,
10
+ * the npm-package provider, and the Typert symbol kit whose symbols/wire helpers the two plugins
11
+ * keep as LOCAL mirrors by design (they are assembled at module load, before any base can be
12
+ * imported).
13
+ *
14
+ * Generation v3 moved exactly those zero-consumer names here (INTERFACE.md §9). `./internal` is NOT
15
+ * part of the interface surface: nothing on it is covered by the generation gate, so plugin authors
16
+ * must take their members off `.`. The names here are reachable for the base's own tests and for a
17
+ * consumer that genuinely needs a framework seam.
18
+ *
3
19
  * @module internal
4
20
  */
5
21
  export { defaultFs, exists, linkOrCopy } from './fs.js';
@@ -16,8 +32,17 @@ export { LAYOUT_SCHEMA_VERSION, STATUS_SCHEMA_VERSION, mergeRows, persistStatus,
16
32
  export type { DeclaredEntry, DeclaredFile, LayoutFile, StatusFile, StatusRow } from './state.js';
17
33
  export { BUILTIN_KINDS, IMPLEMENTED_POLICY_KEYS, ITEM_FIELDS, MANIFEST_FIELDS, UNIMPLEMENTED_POLICY_KEYS, UNIMPLEMENTED_PROVISION_POLICY_KEYS, hasStarBranch, isNamespacedKind, lintManifest, lintManifestText, unknownFields, } from './lint.js';
18
34
  export type { LintFinding, LintResult } from './lint.js';
19
- export { candidateUrls, downloadBytes, fetchImplOf, platformKey, readCapped, signalFor, verifySha256, DEFAULT_MAX_BYTES } from './net.js';
35
+ export { candidateUrls, downloadBytes, fetchImplOf, platformKey, readCapped, readCappedOrSpill, signalFor, verifySha256, DEFAULT_MAX_BYTES, METADATA_MAX_BYTES, SPILL_THRESHOLD_BYTES } from './net.js';
36
+ export type { BodySpill, CappedReadOptions } from './net.js';
20
37
  export { CONTROL_DIR, assertSafeRelativePath, assertSafeRelativeRoot, controlRoot, declaredPath, layoutPath, lockPath, quarantineRoot, stagingDir, statusLockPath, statusPath, tempRoot, versionSegment, } from './layout.js';
21
38
  export { BOOTSTRAP_SUBPATH, FRAMEWORK_INLINING_BEACONS, FRAMEWORK_PACKAGE, MIN_INLINING_BEACONS, findFrameworkImports, findInliningBeacons, isBootstrapSpecifier, } from './artifact.js';
22
39
  export type { FrameworkImportKind, FrameworkImportRef } from './artifact.js';
40
+ export { COMPAT_PROBE_TOOL, checkInterval, checkServices, declaredSchemaKeys, floorOf, probeToolsRegistry, probeTypertRegistry, resolveRuntimeVersion, } from './compat.js';
41
+ export { CAPABILITIES, DEFAULT_DEADLINE_MS, normalizeOnMissing } from './provisioner.js';
42
+ export { NPM_PACKAGE_KIND, npmPackageProvider } from './providers/npm.js';
43
+ export type { NpmPackageSpec } from './providers/npm.js';
44
+ export { createPluginLogger } from './kit/logger.js';
45
+ export type { PluginLogger, PluginLoggerHost, PluginLoggerOptions } from './kit/logger.js';
46
+ export { endpointId, fieldSymbol, resultSymbol, strictCodec } from './kit/typert.js';
47
+ export type { StrictCodec } from './kit/typert.js';
23
48
  //# sourceMappingURL=internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC9H,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,EACnB,UAAU,EACV,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,SAAS,EACT,aAAa,EACb,YAAY,EACZ,UAAU,EACV,UAAU,EACV,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAChG,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,WAAW,EACX,eAAe,EACf,yBAAyB,EACzB,mCAAmC,EACnC,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,aAAa,GACd,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACzI,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,sBAAsB,EACtB,WAAW,EACX,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,cAAc,EACd,UAAU,EACV,cAAc,EACd,UAAU,EACV,QAAQ,EACR,cAAc,GACf,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,iBAAiB,EACjB,0BAA0B,EAC1B,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"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"}
package/dist/internal.js CHANGED
@@ -1,5 +1,21 @@
1
1
  /**
2
2
  * Framework building blocks shared by the core and the entry points.
3
+ *
4
+ * `./internal` is the second published subpath beside `.` and it carries everything the compatibility
5
+ * promise deliberately does NOT cover (root `AGENTS.md`; `docs/INTERFACE.md` §2/§5):
6
+ *
7
+ * - the framework's own seams (fs, locks, archives, layout, lint, semver …), and
8
+ * - the **composition pieces** of the pieces `.` does export: the individual probes and evidence
9
+ * helpers `compat.gatherEvidence` is built from, the provisioner's policy helpers and constants,
10
+ * the npm-package provider, and the Typert symbol kit whose symbols/wire helpers the two plugins
11
+ * keep as LOCAL mirrors by design (they are assembled at module load, before any base can be
12
+ * imported).
13
+ *
14
+ * Generation v3 moved exactly those zero-consumer names here (INTERFACE.md §9). `./internal` is NOT
15
+ * part of the interface surface: nothing on it is covered by the generation gate, so plugin authors
16
+ * must take their members off `.`. The names here are reachable for the base's own tests and for a
17
+ * consumer that genuinely needs a framework seam.
18
+ *
3
19
  * @module internal
4
20
  */
5
21
  export { defaultFs, exists, linkOrCopy } from './fs.js';
@@ -12,7 +28,17 @@ export { assertPackageName } from './package-name.js';
12
28
  export { sriOfSha256, verifyIntegrity } from './integrity.js';
13
29
  export { LAYOUT_SCHEMA_VERSION, STATUS_SCHEMA_VERSION, mergeRows, persistStatus, readDeclared, readLayout, readStatus, recordDeclared, writeLayout, } from './state.js';
14
30
  export { BUILTIN_KINDS, IMPLEMENTED_POLICY_KEYS, ITEM_FIELDS, MANIFEST_FIELDS, UNIMPLEMENTED_POLICY_KEYS, UNIMPLEMENTED_PROVISION_POLICY_KEYS, hasStarBranch, isNamespacedKind, lintManifest, lintManifestText, unknownFields, } from './lint.js';
15
- export { candidateUrls, downloadBytes, fetchImplOf, platformKey, readCapped, signalFor, verifySha256, DEFAULT_MAX_BYTES } from './net.js';
31
+ export { candidateUrls, downloadBytes, fetchImplOf, platformKey, readCapped, readCappedOrSpill, signalFor, verifySha256, DEFAULT_MAX_BYTES, METADATA_MAX_BYTES, SPILL_THRESHOLD_BYTES } from './net.js';
16
32
  export { CONTROL_DIR, assertSafeRelativePath, assertSafeRelativeRoot, controlRoot, declaredPath, layoutPath, lockPath, quarantineRoot, stagingDir, statusLockPath, statusPath, tempRoot, versionSegment, } from './layout.js';
17
33
  export { BOOTSTRAP_SUBPATH, FRAMEWORK_INLINING_BEACONS, FRAMEWORK_PACKAGE, MIN_INLINING_BEACONS, findFrameworkImports, findInliningBeacons, isBootstrapSpecifier, } from './artifact.js';
34
+ // ── generation v3: the names `.` shed ────────────────────────────────────────────────────────────
35
+ // Each of these has zero consumers across the two plugin trees' non-test source and scripts
36
+ // (`test/public-surface.spec.ts` re-proves that mechanically). They are composition pieces of the
37
+ // members `.` still exports, or kit mirrors the plugins keep locally on purpose — never a plugin's
38
+ // entry point. Their canonical home is here; INTERFACE.md §9 records why each one moved.
39
+ export { COMPAT_PROBE_TOOL, checkInterval, checkServices, declaredSchemaKeys, floorOf, probeToolsRegistry, probeTypertRegistry, resolveRuntimeVersion, } from './compat.js';
40
+ export { CAPABILITIES, DEFAULT_DEADLINE_MS, normalizeOnMissing } from './provisioner.js';
41
+ export { NPM_PACKAGE_KIND, npmPackageProvider } from './providers/npm.js';
42
+ export { createPluginLogger } from './kit/logger.js';
43
+ export { endpointId, fieldSymbol, resultSymbol, strictCodec } from './kit/typert.js';
18
44
  //# sourceMappingURL=internal.js.map
@@ -36,8 +36,8 @@ export interface DataHomeInput {
36
36
  }
37
37
  /**
38
38
  * The data root: an explicit caller value (⑤) → `$AVANTF_HOME` (④) → the configured
39
- * `common.dataHome` (②) → `~/.avantf`. That is the family's layer order (`mem/AGENTS.md`
40
- * 「配置分层」: built-in → common.yaml → store → ENV → explicit), so the environment wins over the
39
+ * `common.dataHome` (②) → `~/.avantf`. That is the family's layer order (root `AGENTS.md`
40
+ * 「边界与路径」: built-in → profile → store → ENV → explicit), so the environment wins over the
41
41
  * config file and an explicit argument wins over both.
42
42
  *
43
43
  * The configured value is a NAMED slot ({@link DataHomeInput}) for the reason recorded there: it
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The family's path conventions — ONE definition of two directories that four modules used to spell
3
3
  * out independently (`@avantf/mem-contract`, `@avantf/mem-provision`, `@avantf/mem`'s config paths
4
- * and the work plugin's prompt layer). They are part of the kit because a change to either convention
4
+ * and the mission plugin's prompt layer). They are part of the kit because a change to either convention
5
5
  * must be fixable with one base release.
6
6
  *
7
7
  * TWO ROOTS, and they are deliberately different. Confusing them is the bug this module documents:
@@ -42,8 +42,8 @@ export function familyModelsDir(env = process.env) {
42
42
  }
43
43
  /**
44
44
  * The data root: an explicit caller value (⑤) → `$AVANTF_HOME` (④) → the configured
45
- * `common.dataHome` (②) → `~/.avantf`. That is the family's layer order (`mem/AGENTS.md`
46
- * 「配置分层」: built-in → common.yaml → store → ENV → explicit), so the environment wins over the
45
+ * `common.dataHome` (②) → `~/.avantf`. That is the family's layer order (root `AGENTS.md`
46
+ * 「边界与路径」: built-in → profile → store → ENV → explicit), so the environment wins over the
47
47
  * config file and an explicit argument wins over both.
48
48
  *
49
49
  * The configured value is a NAMED slot ({@link DataHomeInput}) for the reason recorded there: it
@@ -11,7 +11,10 @@
11
11
  * - the plugin logger (`createPluginLogger`),
12
12
  * - the family path conventions (`familyHome` / `familyToolsDir` / `familyModelsDir` /
13
13
  * `resolveDataHome` / `expandHome`),
14
- * - the Typert wire conventions (`strictCodec` / endpoint and field symbols).
14
+ * - the Typert wire conventions (`strictCodec` / endpoint and field symbols),
15
+ * - well-formed text (`wellFormedText` / `wellFormedDeep`): the lone-surrogate repair every
16
+ * model-visible boundary needs, with a local fallback for engines without
17
+ * `String.prototype.toWellFormed`.
15
18
  *
16
19
  * When the base is unavailable, every consumer degrades instead of failing: the prompt layer falls
17
20
  * back to the plugin's OWN built-in default bodies, the compatibility gate logs its `compat:`
@@ -23,4 +26,5 @@ export * from './prompt_files.js';
23
26
  export * from './logger.js';
24
27
  export * from './typert.js';
25
28
  export * from './family.js';
29
+ export * from './wellformed.js';
26
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/kit/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/kit/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA"}
package/dist/kit/index.js CHANGED
@@ -11,7 +11,10 @@
11
11
  * - the plugin logger (`createPluginLogger`),
12
12
  * - the family path conventions (`familyHome` / `familyToolsDir` / `familyModelsDir` /
13
13
  * `resolveDataHome` / `expandHome`),
14
- * - the Typert wire conventions (`strictCodec` / endpoint and field symbols).
14
+ * - the Typert wire conventions (`strictCodec` / endpoint and field symbols),
15
+ * - well-formed text (`wellFormedText` / `wellFormedDeep`): the lone-surrogate repair every
16
+ * model-visible boundary needs, with a local fallback for engines without
17
+ * `String.prototype.toWellFormed`.
15
18
  *
16
19
  * When the base is unavailable, every consumer degrades instead of failing: the prompt layer falls
17
20
  * back to the plugin's OWN built-in default bodies, the compatibility gate logs its `compat:`
@@ -23,4 +26,5 @@ export * from './prompt_files.js';
23
26
  export * from './logger.js';
24
27
  export * from './typert.js';
25
28
  export * from './family.js';
29
+ export * from './wellformed.js';
26
30
  //# sourceMappingURL=index.js.map
@@ -6,7 +6,7 @@
6
6
  * - the memory side's `createConsoleLogger(prefix)` (`@avantf/mem-contract`): a stable
7
7
  * `[avantf-mem] LEVEL message` line on STDERR, because the CLI and the MCP server own stdout for
8
8
  * JSON / JSON-RPC;
9
- * - the work side's `createLogger(host, sink)`: the same stderr line, PLUS a mirror into the host's
9
+ * - the mission side's `createLogger(host, sink)`: the same stderr line, PLUS a mirror into the host's
10
10
  * `ctx.logger` (`ctx.logger` alone never reaches the terminal).
11
11
  *
12
12
  * Both planes are kept, and each is independently injectable so a spec can assert the lines. Nothing
@@ -6,7 +6,7 @@
6
6
  * - the memory side's `createConsoleLogger(prefix)` (`@avantf/mem-contract`): a stable
7
7
  * `[avantf-mem] LEVEL message` line on STDERR, because the CLI and the MCP server own stdout for
8
8
  * JSON / JSON-RPC;
9
- * - the work side's `createLogger(host, sink)`: the same stderr line, PLUS a mirror into the host's
9
+ * - the mission side's `createLogger(host, sink)`: the same stderr line, PLUS a mirror into the host's
10
10
  * `ctx.logger` (`ctx.logger` alone never reaches the terminal).
11
11
  *
12
12
  * Both planes are kept, and each is independently injectable so a spec can assert the lines. Nothing
@@ -1,10 +1,13 @@
1
1
  /**
2
2
  * User-editable prompt text: one `.md` per prompt section, in the family's shared prompt directory
3
- * (`<data home>/prompts`, where each plugin owns a prefix — `mem-*` in the memory plugin, `work-*`
4
- * in the work engine).
3
+ * (`<data home>/prompts`, where each plugin owns a prefix — `mem-*` in the memory plugin, `mission-*`
4
+ * in the mission engine). Since generation v3 that prefix can be declared as
5
+ * {@link PromptFilesOptions.namespace} and is then validated by this module, so a mistyped prefix can
6
+ * no longer silently read or fill another plugin's user file; omitting the field keeps the pre-v3
7
+ * behaviour (no prefix check) for callers built against v1/v2.
5
8
  *
6
9
  * This lived, byte-for-byte identical except for its header comment, in BOTH plugins
7
- * (`@avantf/dsh-mem`'s and `@avantf/dsh-work`'s `packages/plugin/src/prompt_files.ts`) — the copy
10
+ * (`@avantf/dsh-mem`'s and `@avantf/dsh-mission`'s `packages/plugin/src/prompt_files.ts`) — the copy
8
11
  * was deliberate while the two were separate repositories with no shared family package, and the two
9
12
  * headers said "if a third consumer appears, hoist it into one shared package rather than copy it
10
13
  * again". The merge into one workspace is that moment: it now lives in the base
@@ -71,15 +74,46 @@ export interface PromptFilesLogger {
71
74
  export interface PromptFilesOptions {
72
75
  /** Directory holding one `.md` per section. Created when missing. */
73
76
  readonly dir: string;
77
+ /**
78
+ * The plugin's file-name prefix inside the SHARED prompt directory — `mem` for `mem-*.md`,
79
+ * `mission` for `mission-*.md`.
80
+ *
81
+ * `<data home>/prompts` is one directory shared by every plugin in the family, and until v3 the
82
+ * `mem-*` / `mission-*` prefix was a convention with NO machine check: a third plugin could declare
83
+ * `mem-foo.md` and silently take over (or fill) a file the memory plugin's user owns. Naming the
84
+ * namespace here turns that convention into a field the base validates.
85
+ *
86
+ * **Optional, and omitting it is fully backward compatible** — a caller that does not pass it gets
87
+ * byte-for-byte the pre-v3 behaviour (no prefix check at all). That is deliberate: the two installed
88
+ * plugins were built against v1/v2 and must keep working against a v3 base without a change.
89
+ *
90
+ * A namespace must be a kebab-case token (`/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/`). An ILLEGAL namespace
91
+ * is a caller bug, but this module's absolute property is that the prompt layer never throws: a bad
92
+ * namespace therefore makes every {@link PromptFiles.load} on this instance degrade to the caller's
93
+ * fallback with a WARNING, WITHOUT touching the disk (never a throw, never a read or write). When the
94
+ * namespace IS valid, every {@link PromptFileSpec.file} must be `<namespace>-…` and must be a bare
95
+ * file name; a spec that is not is skipped the same way (warning + fallback, no disk access), so a
96
+ * mistyped prefix can never read or overwrite another plugin's user file.
97
+ */
98
+ readonly namespace?: string;
74
99
  readonly logger?: PromptFilesLogger;
75
100
  /** Overridable for tests; defaults to the real filesystem. */
76
101
  readonly io?: PromptFilesIo;
77
102
  }
78
103
  export declare class PromptFiles {
79
104
  readonly dir: string;
105
+ /** The validated namespace prefix, or `undefined` (pre-v3 behaviour: no prefix check). */
106
+ readonly namespace: string | undefined;
107
+ /** Set when `namespace` was supplied but illegal; every `load` then degrades without touching disk. */
108
+ private readonly namespaceError;
80
109
  private readonly logger;
81
110
  private readonly io;
82
111
  constructor(options: PromptFilesOptions);
112
+ /**
113
+ * Whether `file` belongs to this instance's namespace. `true` when no namespace was given (the
114
+ * legacy contract: the caller owns the whole directory naming convention as before).
115
+ */
116
+ private ownsFile;
83
117
  /**
84
118
  * Ensure every spec's file exists with content, then return the text to inject. Ordered like the
85
119
  * manifest, so the caller can zip the result back onto its sections.
@@ -1 +1 @@
1
- {"version":3,"file":"prompt_files.d.ts","sourceRoot":"","sources":["../../src/kit/prompt_files.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,cAAc;IAC7B,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,+FAA+F;IAC/F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB;AAED,6FAA6F;AAC7F,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IAC7B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1B,gGAAgG;IAChG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,0GAA0G;AAC1G,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;IACnC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,CAAC,EAAE,aAAa,CAAA;CAC5B;AA6DD,qBAAa,WAAW;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;gBAEtB,OAAO,EAAE,kBAAkB;IAMvC;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,gBAAgB,EAAE;IAkBnE,OAAO,CAAC,OAAO;CAwBhB"}
1
+ {"version":3,"file":"prompt_files.d.ts","sourceRoot":"","sources":["../../src/kit/prompt_files.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,WAAW,cAAc;IAC7B,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,+FAA+F;IAC/F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB;AAED,6FAA6F;AAC7F,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IAC7B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1B,gGAAgG;IAChG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACvC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED,0GAA0G;AAC1G,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;IACnC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,CAAC,EAAE,aAAa,CAAA;CAC5B;AAgED,qBAAa,WAAW;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,0FAA0F;IAC1F,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,uGAAuG;IACvG,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoB;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;gBAEtB,OAAO,EAAE,kBAAkB;IAiBvC;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAOhB;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,gBAAgB,EAAE;IAmCnE,OAAO,CAAC,OAAO;CAwBhB"}