@ttsc/unplugin 0.31.0 → 0.31.1
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/lib/core/bun/bun.d.cts +3 -2
- package/lib/core/bun/bun.d.mts +3 -2
- package/lib/core/bun/bun.d.ts +3 -2
- package/lib/core/bun/bun.js +8 -4
- package/lib/core/bun/bun.js.map +1 -1
- package/lib/core/bun/bun.mjs +8 -4
- package/lib/core/bun/bun.mjs.map +1 -1
- package/lib/core/observer/createInputObserver.js +6 -5
- package/lib/core/observer/createInputObserver.js.map +1 -1
- package/lib/core/observer/createInputObserver.mjs +6 -5
- package/lib/core/observer/createInputObserver.mjs.map +1 -1
- package/lib/core/observer/openIsolatedRecursiveWatch.d.cts +11 -12
- package/lib/core/observer/openIsolatedRecursiveWatch.d.mts +11 -12
- package/lib/core/observer/openIsolatedRecursiveWatch.d.ts +11 -12
- package/lib/core/observer/openIsolatedRecursiveWatch.js +11 -12
- package/lib/core/observer/openIsolatedRecursiveWatch.js.map +1 -1
- package/lib/core/observer/openIsolatedRecursiveWatch.mjs +11 -12
- package/lib/core/observer/openIsolatedRecursiveWatch.mjs.map +1 -1
- package/lib/core/transform/cache/TtscCachedProjectTransform.d.cts +12 -3
- package/lib/core/transform/cache/TtscCachedProjectTransform.d.mts +12 -3
- package/lib/core/transform/cache/TtscCachedProjectTransform.d.ts +12 -3
- package/lib/core/transform/cache/selectCachedGenerationAction.d.cts +2 -0
- package/lib/core/transform/cache/selectCachedGenerationAction.d.mts +2 -0
- package/lib/core/transform/cache/selectCachedGenerationAction.d.ts +2 -0
- package/lib/core/transform/cache/selectCachedGenerationAction.js +1 -1
- package/lib/core/transform/cache/selectCachedGenerationAction.js.map +1 -1
- package/lib/core/transform/cache/selectCachedGenerationAction.mjs +1 -1
- package/lib/core/transform/cache/selectCachedGenerationAction.mjs.map +1 -1
- package/lib/core/transform/deliverCachedTransform.d.cts +36 -0
- package/lib/core/transform/deliverCachedTransform.d.mts +36 -0
- package/lib/core/transform/deliverCachedTransform.d.ts +36 -0
- package/lib/core/transform/deliverCachedTransform.js +73 -0
- package/lib/core/transform/deliverCachedTransform.js.map +1 -0
- package/lib/core/transform/deliverCachedTransform.mjs +71 -0
- package/lib/core/transform/deliverCachedTransform.mjs.map +1 -0
- package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.d.cts +2 -2
- package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.d.mts +2 -2
- package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.d.ts +2 -2
- package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.js +6 -2
- package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.js.map +1 -1
- package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.mjs +6 -2
- package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.mjs.map +1 -1
- package/lib/core/transform/envelope/selectExternalInputPaths.d.cts +3 -5
- package/lib/core/transform/envelope/selectExternalInputPaths.d.mts +3 -5
- package/lib/core/transform/envelope/selectExternalInputPaths.d.ts +3 -5
- package/lib/core/transform/envelope/selectExternalInputPaths.js +8 -7
- package/lib/core/transform/envelope/selectExternalInputPaths.js.map +1 -1
- package/lib/core/transform/envelope/selectExternalInputPaths.mjs +8 -7
- package/lib/core/transform/envelope/selectExternalInputPaths.mjs.map +1 -1
- package/lib/core/transform/filesystem/TtscTransformFilesystemOperations.d.cts +15 -12
- package/lib/core/transform/filesystem/TtscTransformFilesystemOperations.d.mts +15 -12
- package/lib/core/transform/filesystem/TtscTransformFilesystemOperations.d.ts +15 -12
- package/lib/core/transform/generation/selectTransformAttemptDisposition.d.cts +3 -1
- package/lib/core/transform/generation/selectTransformAttemptDisposition.d.mts +3 -1
- package/lib/core/transform/generation/selectTransformAttemptDisposition.d.ts +3 -1
- package/lib/core/transform/generation/selectTransformAttemptDisposition.js +3 -1
- package/lib/core/transform/generation/selectTransformAttemptDisposition.js.map +1 -1
- package/lib/core/transform/generation/selectTransformAttemptDisposition.mjs +3 -1
- package/lib/core/transform/generation/selectTransformAttemptDisposition.mjs.map +1 -1
- package/lib/core/transform/generation/transformProject.d.cts +9 -7
- package/lib/core/transform/generation/transformProject.d.mts +9 -7
- package/lib/core/transform/generation/transformProject.d.ts +9 -7
- package/lib/core/transform/generation/transformProject.js +14 -9
- package/lib/core/transform/generation/transformProject.js.map +1 -1
- package/lib/core/transform/generation/transformProject.mjs +14 -9
- package/lib/core/transform/generation/transformProject.mjs.map +1 -1
- package/lib/core/transform/inputs/preparePluginBuildEnvironments.d.cts +11 -4
- package/lib/core/transform/inputs/preparePluginBuildEnvironments.d.mts +11 -4
- package/lib/core/transform/inputs/preparePluginBuildEnvironments.d.ts +11 -4
- package/lib/core/transform/inputs/preparePluginBuildEnvironments.js +44 -7
- package/lib/core/transform/inputs/preparePluginBuildEnvironments.js.map +1 -1
- package/lib/core/transform/inputs/preparePluginBuildEnvironments.mjs +44 -7
- package/lib/core/transform/inputs/preparePluginBuildEnvironments.mjs.map +1 -1
- package/lib/core/transform/tracker/broker/WatchBroker.d.cts +14 -4
- package/lib/core/transform/tracker/broker/WatchBroker.d.mts +14 -4
- package/lib/core/transform/tracker/broker/WatchBroker.d.ts +14 -4
- package/lib/core/transform/tracker/broker/WatchBrokerTransport.d.cts +63 -0
- package/lib/core/transform/tracker/broker/WatchBrokerTransport.d.mts +63 -0
- package/lib/core/transform/tracker/broker/WatchBrokerTransport.d.ts +63 -0
- package/lib/core/transform/tracker/broker/WatchBrokerTransport.js +89 -0
- package/lib/core/transform/tracker/broker/WatchBrokerTransport.js.map +1 -0
- package/lib/core/transform/tracker/broker/WatchBrokerTransport.mjs +89 -0
- package/lib/core/transform/tracker/broker/WatchBrokerTransport.mjs.map +1 -0
- package/lib/core/transform/tracker/broker/drainWatchBroker.d.cts +8 -8
- package/lib/core/transform/tracker/broker/drainWatchBroker.d.mts +8 -8
- package/lib/core/transform/tracker/broker/drainWatchBroker.d.ts +8 -8
- package/lib/core/transform/tracker/broker/drainWatchBroker.js +12 -13
- package/lib/core/transform/tracker/broker/drainWatchBroker.js.map +1 -1
- package/lib/core/transform/tracker/broker/drainWatchBroker.mjs +12 -13
- package/lib/core/transform/tracker/broker/drainWatchBroker.mjs.map +1 -1
- package/lib/core/transform/tracker/broker/getWatchBroker.d.cts +18 -15
- package/lib/core/transform/tracker/broker/getWatchBroker.d.mts +18 -15
- package/lib/core/transform/tracker/broker/getWatchBroker.d.ts +18 -15
- package/lib/core/transform/tracker/broker/getWatchBroker.js +87 -17
- package/lib/core/transform/tracker/broker/getWatchBroker.js.map +1 -1
- package/lib/core/transform/tracker/broker/getWatchBroker.mjs +87 -17
- package/lib/core/transform/tracker/broker/getWatchBroker.mjs.map +1 -1
- package/lib/core/transform/tracker/broker/openBrokeredWatch.d.cts +5 -5
- package/lib/core/transform/tracker/broker/openBrokeredWatch.d.mts +5 -5
- package/lib/core/transform/tracker/broker/openBrokeredWatch.d.ts +5 -5
- package/lib/core/transform/tracker/broker/openBrokeredWatch.js +11 -14
- package/lib/core/transform/tracker/broker/openBrokeredWatch.js.map +1 -1
- package/lib/core/transform/tracker/broker/openBrokeredWatch.mjs +11 -14
- package/lib/core/transform/tracker/broker/openBrokeredWatch.mjs.map +1 -1
- package/lib/core/transform/tracker/broker/usesWatchBroker.d.cts +7 -7
- package/lib/core/transform/tracker/broker/usesWatchBroker.d.mts +7 -7
- package/lib/core/transform/tracker/broker/usesWatchBroker.d.ts +7 -7
- package/lib/core/transform/tracker/broker/usesWatchBroker.js +7 -7
- package/lib/core/transform/tracker/broker/usesWatchBroker.mjs +7 -7
- package/lib/core/transform/tracker/broker/watchBrokerSource.d.cts +9 -10
- package/lib/core/transform/tracker/broker/watchBrokerSource.d.mts +9 -10
- package/lib/core/transform/tracker/broker/watchBrokerSource.d.ts +9 -10
- package/lib/core/transform/tracker/broker/watchBrokerSource.js +10 -11
- package/lib/core/transform/tracker/broker/watchBrokerSource.js.map +1 -1
- package/lib/core/transform/tracker/broker/watchBrokerSource.mjs +10 -11
- package/lib/core/transform/tracker/broker/watchBrokerSource.mjs.map +1 -1
- package/lib/core/transform/transformTtsc.d.cts +7 -4
- package/lib/core/transform/transformTtsc.d.mts +7 -4
- package/lib/core/transform/transformTtsc.d.ts +7 -4
- package/lib/core/transform/transformTtsc.js +37 -92
- package/lib/core/transform/transformTtsc.js.map +1 -1
- package/lib/core/transform/transformTtsc.mjs +37 -92
- package/lib/core/transform/transformTtsc.mjs.map +1 -1
- package/lib/core/transform/validation/TtscGenerationProof.d.cts +105 -0
- package/lib/core/transform/validation/TtscGenerationProof.d.mts +105 -0
- package/lib/core/transform/validation/TtscGenerationProof.d.ts +105 -0
- package/lib/core/transform/validation/TtscGenerationProof.js +149 -0
- package/lib/core/transform/validation/TtscGenerationProof.js.map +1 -0
- package/lib/core/transform/validation/TtscGenerationProof.mjs +149 -0
- package/lib/core/transform/validation/TtscGenerationProof.mjs.map +1 -0
- package/lib/core/transform/validation/matchesCachedSource.d.cts +18 -15
- package/lib/core/transform/validation/matchesCachedSource.d.mts +18 -15
- package/lib/core/transform/validation/matchesCachedSource.d.ts +18 -15
- package/lib/core/transform/validation/matchesCachedSource.js +28 -22
- package/lib/core/transform/validation/matchesCachedSource.js.map +1 -1
- package/lib/core/transform/validation/matchesCachedSource.mjs +28 -22
- package/lib/core/transform/validation/matchesCachedSource.mjs.map +1 -1
- package/lib/core/transform/validation/matchesCompleteInputSnapshot.d.cts +3 -2
- package/lib/core/transform/validation/matchesCompleteInputSnapshot.d.mts +3 -2
- package/lib/core/transform/validation/matchesCompleteInputSnapshot.d.ts +3 -2
- package/lib/core/transform/validation/matchesCompleteInputSnapshot.js +4 -4
- package/lib/core/transform/validation/matchesCompleteInputSnapshot.js.map +1 -1
- package/lib/core/transform/validation/matchesCompleteInputSnapshot.mjs +4 -4
- package/lib/core/transform/validation/matchesCompleteInputSnapshot.mjs.map +1 -1
- package/lib/core/transform/validation/matchesNarrowPersistentInputs.d.cts +2 -1
- package/lib/core/transform/validation/matchesNarrowPersistentInputs.d.mts +2 -1
- package/lib/core/transform/validation/matchesNarrowPersistentInputs.d.ts +2 -1
- package/lib/core/transform/validation/matchesNarrowPersistentInputs.js +2 -2
- package/lib/core/transform/validation/matchesNarrowPersistentInputs.js.map +1 -1
- package/lib/core/transform/validation/matchesNarrowPersistentInputs.mjs +2 -2
- package/lib/core/transform/validation/matchesNarrowPersistentInputs.mjs.map +1 -1
- package/lib/core/transform/validation/matchesUniversalHostInputTrees.d.cts +3 -2
- package/lib/core/transform/validation/matchesUniversalHostInputTrees.d.mts +3 -2
- package/lib/core/transform/validation/matchesUniversalHostInputTrees.d.ts +3 -2
- package/lib/core/transform/validation/matchesUniversalHostInputTrees.js +5 -3
- package/lib/core/transform/validation/matchesUniversalHostInputTrees.js.map +1 -1
- package/lib/core/transform/validation/matchesUniversalHostInputTrees.mjs +5 -3
- package/lib/core/transform/validation/matchesUniversalHostInputTrees.mjs.map +1 -1
- package/lib/core/transform/validation/matchesUniversalHostInputs.d.cts +3 -2
- package/lib/core/transform/validation/matchesUniversalHostInputs.d.mts +3 -2
- package/lib/core/transform/validation/matchesUniversalHostInputs.d.ts +3 -2
- package/lib/core/transform/validation/matchesUniversalHostInputs.js +5 -5
- package/lib/core/transform/validation/matchesUniversalHostInputs.js.map +1 -1
- package/lib/core/transform/validation/matchesUniversalHostInputs.mjs +5 -5
- package/lib/core/transform/validation/matchesUniversalHostInputs.mjs.map +1 -1
- package/lib/core/transform/validation/nativeInputPredicatesHold.d.cts +5 -4
- package/lib/core/transform/validation/nativeInputPredicatesHold.d.mts +5 -4
- package/lib/core/transform/validation/nativeInputPredicatesHold.d.ts +5 -4
- package/lib/core/transform/validation/nativeInputPredicatesHold.js +31 -12
- package/lib/core/transform/validation/nativeInputPredicatesHold.js.map +1 -1
- package/lib/core/transform/validation/nativeInputPredicatesHold.mjs +31 -12
- package/lib/core/transform/validation/nativeInputPredicatesHold.mjs.map +1 -1
- package/lib/core/transform/validation/notificationsProveProgramUnchanged.d.cts +2 -1
- package/lib/core/transform/validation/notificationsProveProgramUnchanged.d.mts +2 -1
- package/lib/core/transform/validation/notificationsProveProgramUnchanged.d.ts +2 -1
- package/lib/core/transform/validation/notificationsProveProgramUnchanged.js +2 -2
- package/lib/core/transform/validation/notificationsProveProgramUnchanged.js.map +1 -1
- package/lib/core/transform/validation/notificationsProveProgramUnchanged.mjs +2 -2
- package/lib/core/transform/validation/notificationsProveProgramUnchanged.mjs.map +1 -1
- package/lib/core/transform/watch/notifyWatchInputs.js +3 -0
- package/lib/core/transform/watch/notifyWatchInputs.js.map +1 -1
- package/lib/core/transform/watch/notifyWatchInputs.mjs +3 -0
- package/lib/core/transform/watch/notifyWatchInputs.mjs.map +1 -1
- package/lib/core/turbopack/turbopack.js +2 -1
- package/lib/core/turbopack/turbopack.js.map +1 -1
- package/lib/core/turbopack/turbopack.mjs +2 -1
- package/lib/core/turbopack/turbopack.mjs.map +1 -1
- package/package.json +3 -3
- package/src/core/bun/bun.ts +8 -4
- package/src/core/observer/createInputObserver.ts +6 -5
- package/src/core/observer/openIsolatedRecursiveWatch.ts +11 -12
- package/src/core/transform/cache/TtscCachedProjectTransform.ts +13 -3
- package/src/core/transform/cache/selectCachedGenerationAction.ts +9 -1
- package/src/core/transform/deliverCachedTransform.ts +97 -0
- package/src/core/transform/envelope/selectDeclaredProjectInputKeys.ts +5 -2
- package/src/core/transform/envelope/selectExternalInputPaths.ts +7 -7
- package/src/core/transform/filesystem/TtscTransformFilesystemOperations.ts +15 -12
- package/src/core/transform/generation/selectTransformAttemptDisposition.ts +3 -1
- package/src/core/transform/generation/transformProject.ts +13 -9
- package/src/core/transform/inputs/preparePluginBuildEnvironments.ts +41 -7
- package/src/core/transform/tracker/broker/WatchBroker.ts +15 -4
- package/src/core/transform/tracker/broker/WatchBrokerTransport.ts +82 -0
- package/src/core/transform/tracker/broker/drainWatchBroker.ts +12 -13
- package/src/core/transform/tracker/broker/getWatchBroker.ts +89 -18
- package/src/core/transform/tracker/broker/openBrokeredWatch.ts +11 -14
- package/src/core/transform/tracker/broker/usesWatchBroker.ts +7 -7
- package/src/core/transform/tracker/broker/watchBrokerSource.ts +10 -11
- package/src/core/transform/transformTtsc.ts +36 -92
- package/src/core/transform/validation/TtscGenerationProof.ts +201 -0
- package/src/core/transform/validation/matchesCachedSource.ts +27 -21
- package/src/core/transform/validation/matchesCompleteInputSnapshot.ts +5 -3
- package/src/core/transform/validation/matchesNarrowPersistentInputs.ts +3 -1
- package/src/core/transform/validation/matchesUniversalHostInputTrees.ts +6 -2
- package/src/core/transform/validation/matchesUniversalHostInputs.ts +6 -4
- package/src/core/transform/validation/nativeInputPredicatesHold.ts +36 -14
- package/src/core/transform/validation/notificationsProveProgramUnchanged.ts +3 -1
- package/src/core/transform/watch/notifyWatchInputs.ts +3 -0
- package/src/core/turbopack/turbopack.ts +2 -1
|
@@ -217,11 +217,12 @@ export function createInputObserver(
|
|
|
217
217
|
let poller: { close(): void } | undefined;
|
|
218
218
|
let flushTimer: NodeJS.Timeout | undefined;
|
|
219
219
|
|
|
220
|
-
// Windows
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
//
|
|
224
|
-
//
|
|
220
|
+
// Windows uses ttsc's native completion-port helper, excluding access-only
|
|
221
|
+
// notifications without opening Node fs-event handles (samchon/ttsc#1719).
|
|
222
|
+
// Do not restore fs.watch here: reads can invalidate an unchanged generation,
|
|
223
|
+
// and deleting a watched temporary tree can abort Node (samchon/ttsc#1411).
|
|
224
|
+
// macOS keeps each scope in its own brokered FSEventStream, whose dropped
|
|
225
|
+
// events are reported instead of lost (samchon/ttsc#1418, samchon/ttsc#1425).
|
|
225
226
|
const open =
|
|
226
227
|
operations.watch ??
|
|
227
228
|
(process.platform === "win32" || process.platform === "darwin"
|
|
@@ -7,18 +7,17 @@ import { openBrokeredWatch } from "../transform/tracker/broker/openBrokeredWatch
|
|
|
7
7
|
* Open one recursive observer inside the transform core's isolated watch broker
|
|
8
8
|
* instead of the host process.
|
|
9
9
|
*
|
|
10
|
-
* On Windows,
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* bounded poll.
|
|
10
|
+
* On Windows, ttsc's direct native helper excludes access-only notifications
|
|
11
|
+
* and reports actual mutation, loss and failure through the same broker sink.
|
|
12
|
+
* On macOS, libuv serves every directory watch of a loop through one
|
|
13
|
+
* FSEventStream and re-creates it whenever any watch opens or closes, losing
|
|
14
|
+
* the events in between (samchon/ttsc#1418), where the broker opens one stream
|
|
15
|
+
* per watch. The observer's scopes get the isolation the transform core's
|
|
16
|
+
* trackers have, through the same registration (`openBrokeredWatch`) with a
|
|
17
|
+
* sink of their own that forwards events (samchon/ttsc#1485). Attributed events
|
|
18
|
+
* reach `listener` with a joined caller-directory path; unattributed events use
|
|
19
|
+
* null. A failed registration reaches `onError`, which hands the scope's
|
|
20
|
+
* entries to the bounded poll.
|
|
22
21
|
*
|
|
23
22
|
* Registration completes asynchronously, and FSEvents can later drop events
|
|
24
23
|
* (samchon/ttsc#1425). Until the broker confirms the watch, and whenever it
|
|
@@ -232,12 +232,22 @@ export interface TtscCachedProjectTransform {
|
|
|
232
232
|
|
|
233
233
|
/**
|
|
234
234
|
* A locally admitted answer with incomplete host observations cannot be
|
|
235
|
-
* retained for
|
|
236
|
-
*
|
|
237
|
-
*
|
|
235
|
+
* retained for shared or persistent reuse. A separately admitted coherent
|
|
236
|
+
* local success may share first deliveries only in its explicit nonwatching
|
|
237
|
+
* pass (passDeliveryOnly). Successful answers need only explicit unavailable
|
|
238
|
+
* observations; diagnostic admission keeps its existing current-verdict
|
|
239
|
+
* policy. This flag never grants admission itself.
|
|
238
240
|
*/
|
|
239
241
|
freshDeliveryOnly?: boolean;
|
|
240
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Coherent local success whose only missing authority is host observation.
|
|
245
|
+
* WARNING (#1713): this grants neither persistent nor pooled reuse. The
|
|
246
|
+
* common proof owner requires an explicit nonwatching pass, a recorded
|
|
247
|
+
* source, first delivery and actual host-cache withdrawal on every delivery.
|
|
248
|
+
*/
|
|
249
|
+
passDeliveryOnly?: boolean;
|
|
250
|
+
|
|
241
251
|
/** Absolute path to the directory that owns the tsconfig. */
|
|
242
252
|
projectRoot: string;
|
|
243
253
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { envelopeDerivation } from "../envelope/envelopeDerivation";
|
|
2
2
|
import { isVolatileFile } from "../envelope/isVolatileFile";
|
|
3
|
+
import type { TtscGenerationProof } from "../validation/TtscGenerationProof";
|
|
3
4
|
import { matchesCachedSource } from "../validation/matchesCachedSource";
|
|
4
5
|
import type { TtscCachedProjectTransform } from "./TtscCachedProjectTransform";
|
|
5
6
|
import type { TtscTransformCache } from "./TtscTransformCache";
|
|
@@ -42,6 +43,7 @@ export function selectCachedGenerationAction(props: {
|
|
|
42
43
|
generation: Promise<TtscCachedProjectTransform>;
|
|
43
44
|
key: string;
|
|
44
45
|
source: string;
|
|
46
|
+
proof?: TtscGenerationProof.Transaction;
|
|
45
47
|
}): "serve" | "retry" | "capture" {
|
|
46
48
|
if (
|
|
47
49
|
!isVolatileFile(envelopeDerivation(props.cached), {
|
|
@@ -49,7 +51,13 @@ export function selectCachedGenerationAction(props: {
|
|
|
49
51
|
projectRoot: props.cached.projectRoot,
|
|
50
52
|
result: props.cached.result,
|
|
51
53
|
}) &&
|
|
52
|
-
matchesCachedSource(
|
|
54
|
+
matchesCachedSource(
|
|
55
|
+
props.cached,
|
|
56
|
+
props.file,
|
|
57
|
+
props.source,
|
|
58
|
+
props.epoch,
|
|
59
|
+
props.proof,
|
|
60
|
+
)
|
|
53
61
|
) {
|
|
54
62
|
return "serve";
|
|
55
63
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { TtscCachedProjectTransform } from "./cache/TtscCachedProjectTransform";
|
|
2
|
+
import type { TtscTransformCache } from "./cache/TtscTransformCache";
|
|
3
|
+
import { evictGeneration } from "./cache/evictGeneration";
|
|
4
|
+
import { selectOrEvict } from "./cache/selectOrEvict";
|
|
5
|
+
import { reportMissingProgramOutput } from "./diagnostics/reportMissingProgramOutput";
|
|
6
|
+
import { reportSuccessDiagnostics } from "./diagnostics/reportSuccessDiagnostics";
|
|
7
|
+
import { TtscMissingProgramOutputError } from "./errors/TtscMissingProgramOutputError";
|
|
8
|
+
import { createTransformResult } from "./utils/createTransformResult";
|
|
9
|
+
import { TtscGenerationProof } from "./validation/TtscGenerationProof";
|
|
10
|
+
import { markCachedSourceServed } from "./validation/markCachedSourceServed";
|
|
11
|
+
import type { TtscTransformHooks } from "./watch/TtscTransformHooks";
|
|
12
|
+
import type { TtscWatchSelection } from "./watch/TtscWatchSelection";
|
|
13
|
+
import { notifyFailedGenerationInputs } from "./watch/notifyFailedGenerationInputs";
|
|
14
|
+
import { notifyVolatileDelivery } from "./watch/notifyVolatileDelivery";
|
|
15
|
+
import { notifyWatchInputs } from "./watch/notifyWatchInputs";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Deliver both captured and reused generations through one failure boundary.
|
|
19
|
+
*
|
|
20
|
+
* WARNING (#1713): host capabilities and callbacks apply to every delivery,
|
|
21
|
+
* including cache hits. Incomplete local results must never survive a failed
|
|
22
|
+
* handoff or acquire a persistent record. Stable ordinary generations retain
|
|
23
|
+
* their existing callback-failure recovery policy.
|
|
24
|
+
*
|
|
25
|
+
* A missing program output is an admitted absence: notify the same selection
|
|
26
|
+
* inputs and return control to the host. Compile failure retains its existing
|
|
27
|
+
* terminal policy through selectOrEvict and reports repair inputs.
|
|
28
|
+
*
|
|
29
|
+
* @evidence contracts/common.md#principled-implementation Captured and reused results share lifecycle admission, output selection, diagnostics and host handoff; incomplete ownership is evicted on any failed delivery effect, while missing output remains a host fallthrough.
|
|
30
|
+
* @evidence contracts/common.md#clear-and-simple-design One synchronous boundary removes duplicate initial/cache-hit delivery paths and their divergent callback and cleanup rules.
|
|
31
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Missing outputs never manufacture transformed bytes or reusable observation authority; incomplete handoff failure cannot leave an owner for a sibling.
|
|
32
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose states per-delivery capability, callback failure, missing-output and compile-failure responsibilities.
|
|
33
|
+
* @evidence contracts/portability.md#os-neutral-implementation Native identities and host spellings remain delegated to the generation's existing output/watch owners.
|
|
34
|
+
* @evidence contracts/performance.md#efficient-algorithms Selection uses generation indexes; diagnostics, output/map work and current host callbacks remain necessary per delivery. Watch input and record derivation retain their owning population costs.
|
|
35
|
+
* @evidence contracts/performance.md#reuse-equivalent-work Initial and reused answers share the exact same operation, while generation-owned indexes and the pass-qualified compiled result retain their separate validity premises.
|
|
36
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources Fresh-only admission releases capture resources; failed incomplete delivery evicts only its exact Promise. Ordinary selection/terminal and host lifecycle owners retain their established resource policy.
|
|
37
|
+
*/
|
|
38
|
+
export function deliverCachedTransform(props: {
|
|
39
|
+
cache: TtscTransformCache | undefined;
|
|
40
|
+
cached: TtscCachedProjectTransform;
|
|
41
|
+
generation: Promise<TtscCachedProjectTransform>;
|
|
42
|
+
key: string;
|
|
43
|
+
epoch: number | undefined;
|
|
44
|
+
file: string;
|
|
45
|
+
source: string;
|
|
46
|
+
hooks: TtscTransformHooks | undefined;
|
|
47
|
+
selection: TtscWatchSelection;
|
|
48
|
+
}) {
|
|
49
|
+
const {
|
|
50
|
+
cache,
|
|
51
|
+
cached,
|
|
52
|
+
generation,
|
|
53
|
+
key,
|
|
54
|
+
epoch,
|
|
55
|
+
file,
|
|
56
|
+
source,
|
|
57
|
+
hooks,
|
|
58
|
+
selection,
|
|
59
|
+
} = props;
|
|
60
|
+
try {
|
|
61
|
+
TtscGenerationProof.admitFreshOnly(
|
|
62
|
+
cached,
|
|
63
|
+
cache,
|
|
64
|
+
key,
|
|
65
|
+
generation,
|
|
66
|
+
epoch,
|
|
67
|
+
hooks,
|
|
68
|
+
);
|
|
69
|
+
reportSuccessDiagnostics(cached, epoch);
|
|
70
|
+
let output;
|
|
71
|
+
try {
|
|
72
|
+
output = selectOrEvict(cache, key, generation, epoch, {
|
|
73
|
+
file,
|
|
74
|
+
projectRoot: cached.projectRoot,
|
|
75
|
+
result: cached.result,
|
|
76
|
+
tsconfig: cached.tsconfig,
|
|
77
|
+
});
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (!(error instanceof TtscMissingProgramOutputError)) {
|
|
80
|
+
notifyFailedGenerationInputs(hooks, cached, file, selection);
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
reportMissingProgramOutput(cached, error, epoch);
|
|
84
|
+
notifyWatchInputs(hooks, cached, file, selection);
|
|
85
|
+
markCachedSourceServed(cached, file);
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
notifyWatchInputs(hooks, cached, file, selection);
|
|
89
|
+
markCachedSourceServed(cached, file);
|
|
90
|
+
notifyVolatileDelivery(hooks, cached, file);
|
|
91
|
+
return createTransformResult(file, source, output);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (cached.freshDeliveryOnly === true)
|
|
94
|
+
evictGeneration(cache, key, generation);
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -26,8 +26,8 @@ import { isTransformScratchInput } from "../tsconfig/isTransformScratchInput";
|
|
|
26
26
|
* Visits each reported occurrence in graph endpoints/globals/configs,
|
|
27
27
|
* candidates, host inputs and dependency arrays. Native resolve, scratch
|
|
28
28
|
* checks, project-key identity/ancestor/case observations and text hashing
|
|
29
|
-
* precede each own-key membership test
|
|
30
|
-
*
|
|
29
|
+
* precede each own-key membership test after lexical deduplication; repeated
|
|
30
|
+
* declarations pay resolution but no repeated native classification. Entry
|
|
31
31
|
* arrays from Object.entries/Object.values follow producer populations,
|
|
32
32
|
* while the returned set cannot exceed keys present in the project snapshot.
|
|
33
33
|
* @evidenceExclude contracts/performance.md#reuse-equivalent-work
|
|
@@ -49,9 +49,12 @@ export function selectDeclaredProjectInputKeys(props: {
|
|
|
49
49
|
}
|
|
50
50
|
const graph = props.result.graph;
|
|
51
51
|
const keys = new Set<string>();
|
|
52
|
+
const seen = new Set<string>();
|
|
52
53
|
const add = (entry: unknown): void => {
|
|
53
54
|
if (typeof entry !== "string" || entry.length === 0) return;
|
|
54
55
|
const absolute = path.resolve(props.projectRoot, entry);
|
|
56
|
+
if (seen.has(absolute)) return;
|
|
57
|
+
seen.add(absolute);
|
|
55
58
|
if (isTransformScratchInput(absolute, props.scratchDirectory)) return;
|
|
56
59
|
const key = toProjectKey(props.projectRoot, absolute, props.identities);
|
|
57
60
|
if (Object.prototype.hasOwnProperty.call(props.projectInputHashes, key)) {
|
|
@@ -36,17 +36,15 @@ import { envelopeGraphIndexes } from "./envelopeGraphIndexes";
|
|
|
36
36
|
* @evidence contracts/performance.md#efficient-algorithms
|
|
37
37
|
* Cold graph index construction precedes separate scans of output, graph,
|
|
38
38
|
* candidate, dependency and host lists, followed by every collected member's
|
|
39
|
-
* filter pass.
|
|
40
|
-
* observations
|
|
41
|
-
* seen. Native path/ancestor/case, existence and walk policy/component checks
|
|
39
|
+
* filter pass. Lexical deduplication precedes native identity/candidate/walk
|
|
40
|
+
* observations, including rejected members; distinct aliases stay separate. Native path/ancestor/case, existence and walk policy/component checks
|
|
42
41
|
* add costs to list/key text. Collected members, candidate/seen sets and
|
|
43
42
|
* output allocate population-sized storage; final string sorting adds output
|
|
44
43
|
* comparison work.
|
|
45
44
|
* @evidence contracts/performance.md#reuse-equivalent-work
|
|
46
45
|
* Generation state shares completed graph parsing, while this call's native
|
|
47
46
|
* identity context reuses its qualified path observations. The sets dedupe
|
|
48
|
-
*
|
|
49
|
-
* every repeated classification. Supplied filesystem, producer-derived state
|
|
47
|
+
* every lexical classification and mark candidate membership. Supplied filesystem, producer-derived state
|
|
50
48
|
* and membership policy must represent the same stable generation view.
|
|
51
49
|
* @evidenceExclude contracts/performance.md#bound-retention-and-release-resources
|
|
52
50
|
* Its collections are local to the call and released on return; only the
|
|
@@ -144,6 +142,10 @@ export function selectExternalInputPaths(props: {
|
|
|
144
142
|
}
|
|
145
143
|
const absolute = path.resolve(props.projectRoot, member);
|
|
146
144
|
const spelling = path.resolve(absolute);
|
|
145
|
+
// Classify each lexical address once, including rejected walk members.
|
|
146
|
+
// Physical aliases remain distinct so retargeting is still observable.
|
|
147
|
+
if (seen.has(spelling)) continue;
|
|
148
|
+
seen.add(spelling);
|
|
147
149
|
const identity = pathIdentityKey(absolute, identities);
|
|
148
150
|
const observation = graphIndexes.inputObservations.get(spelling);
|
|
149
151
|
const missingCandidate =
|
|
@@ -153,7 +155,6 @@ export function selectExternalInputPaths(props: {
|
|
|
153
155
|
if (
|
|
154
156
|
identity === excluded ||
|
|
155
157
|
isTransformScratchInput(absolute, props.scratchDirectory) ||
|
|
156
|
-
seen.has(spelling) ||
|
|
157
158
|
(!missingCandidate &&
|
|
158
159
|
isProjectWalkPath(
|
|
159
160
|
props.projectRoot,
|
|
@@ -167,7 +168,6 @@ export function selectExternalInputPaths(props: {
|
|
|
167
168
|
}
|
|
168
169
|
// Preserve distinct lexical aliases even when they currently select the
|
|
169
170
|
// same physical file. A later retarget must validate the alias itself.
|
|
170
|
-
seen.add(spelling);
|
|
171
171
|
output.push(absolute);
|
|
172
172
|
}
|
|
173
173
|
output.sort();
|
|
@@ -198,23 +198,26 @@ export interface TtscTransformFilesystemOperations {
|
|
|
198
198
|
* Open one directory's change notification, or throw when the observed
|
|
199
199
|
* filesystem cannot provide one.
|
|
200
200
|
*
|
|
201
|
-
* Left undefined, generations watch the host filesystem
|
|
202
|
-
*
|
|
203
|
-
* observing another filesystem supplies its own;
|
|
204
|
-
* cannot be opened keeps validating from recorded
|
|
205
|
-
* cache.
|
|
201
|
+
* Left undefined, generations watch the host filesystem through the native
|
|
202
|
+
* Linux helper, the native Windows completion-port helper, or the macOS
|
|
203
|
+
* FSEvents broker. An embedder observing another filesystem supplies its own;
|
|
204
|
+
* a generation whose watch cannot be opened keeps validating from recorded
|
|
205
|
+
* state instead of losing its cache.
|
|
206
206
|
*
|
|
207
|
-
* Supplying one
|
|
208
|
-
*
|
|
209
|
-
* the native abort
|
|
210
|
-
* tree is deleted
|
|
211
|
-
*
|
|
207
|
+
* Supplying one bypasses these native owners. Wrapping Node's `fs.watch`
|
|
208
|
+
* reintroduces Windows access-only notifications that invalidate unchanged
|
|
209
|
+
* inputs, and the native abort its fs-event backend can raise when a watched
|
|
210
|
+
* temporary tree is deleted. It also gives up explicit notification-loss
|
|
211
|
+
* reporting from the Linux helper and macOS's per-watch FSEventStream.
|
|
212
|
+
* Preserve mutation and loss reporting when implementing this capability;
|
|
213
|
+
* timestamps or identical current bytes cannot discard an actual A-B-A
|
|
214
|
+
* event.
|
|
212
215
|
*
|
|
213
216
|
* @evidence contracts/common.md#principled-implementation The watch capability reports actual directory changes and failure; its absence or failure cannot certify silence as unchanged inputs.
|
|
214
217
|
* @evidence contracts/common.md#clear-and-simple-design One optional native operation exposes observation and a close handle, leaving broker selection and retained-generation proof in their owners.
|
|
215
218
|
* @evidence contracts/common.md#prohibited-implementation-shortcuts Injected watches are explicit capabilities rather than patched fs methods, and errors require recorded-state validation instead of synthetic live coverage.
|
|
216
|
-
* @evidence contracts/common.md#meaningful-documentation The native paragraphs explain
|
|
217
|
-
* @evidence contracts/portability.md#os-neutral-implementation OS-neutral watching requires the observed filesystem's capability and accounts for
|
|
219
|
+
* @evidence contracts/common.md#meaningful-documentation The native paragraphs explain default owners, failed watches, explicit override authority, access-only noise, native aborts and mutation/loss reporting that a direct fs.watch wrapper cannot supply.
|
|
220
|
+
* @evidence contracts/portability.md#os-neutral-implementation OS-neutral watching requires the observed filesystem's capability and accounts for native Windows mutation filtering and Linux/macOS loss reporting rather than assuming recursive notifications are interchangeable.
|
|
218
221
|
* @evidenceExclude contracts/performance.md#efficient-algorithms
|
|
219
222
|
* Only the signature of watch is declared here; the cost belongs to its
|
|
220
223
|
* implementation.
|
|
@@ -8,7 +8,9 @@ import { onlyLearnedCompileFacts } from "./onlyLearnedCompileFacts";
|
|
|
8
8
|
* facts describe the capture; this policy performs no capture or native proof.
|
|
9
9
|
*
|
|
10
10
|
* Coherent results return first. A local, lossless host-observation refusal can
|
|
11
|
-
* transfer
|
|
11
|
+
* transfer an incomplete local success. TtscGenerationProof owns any sharing of
|
|
12
|
+
* its first module deliveries inside an explicit nonwatching pass; this policy
|
|
13
|
+
* grants no independent native or persistent proof. Rejected attempts spend
|
|
12
14
|
* movement only when they neither refute a publication nor solely learn facts.
|
|
13
15
|
* Two movements or four captures stop retrying, retaining a current diagnostic
|
|
14
16
|
* rather than a terminal instability verdict when its config is not refuted.
|
|
@@ -64,18 +64,20 @@ import { selectTransformAttemptDisposition } from "./selectTransformAttemptDispo
|
|
|
64
64
|
* (samchon/ttsc#1545).
|
|
65
65
|
*
|
|
66
66
|
* A local success whose only lost premise is explicitly unavailable host
|
|
67
|
-
* observation may qualify for
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
67
|
+
* observation may qualify for local delivery. TtscGenerationProof additionally
|
|
68
|
+
* requires an explicitly nonwatching host and actual cache withdrawal for every
|
|
69
|
+
* delivery. It alone can share recorded first-module baselines inside the same
|
|
70
|
+
* explicit pass. This incomplete result cannot authorize ordinary resident
|
|
71
|
+
* reuse, a persistent project record or shared publication; repeated modules
|
|
72
|
+
* and later passes recapture. Actual changes, conflicts and unexplained missing
|
|
73
|
+
* proof retain the stabilization gate.
|
|
72
74
|
*
|
|
73
75
|
* Enabled private tracing records each computed disposition before its state is
|
|
74
76
|
* applied. It does not supply proof when capture throws or tracing fails.
|
|
75
77
|
*
|
|
76
|
-
* @evidence contracts/common.md#principled-implementation Each capture establishes config coherence and reusable success proof or a current diagnostic verdict; a local stable success with only explicit unavailable host observations instead transfers
|
|
78
|
+
* @evidence contracts/common.md#principled-implementation Each capture establishes config coherence and reusable success proof or a current diagnostic verdict; a local stable success with only explicit unavailable host observations instead transfers an incomplete local result whose bounded first deliveries require the common nonwatching pass owner, while mixed mutation, missing or conflicting proof retains retry admission.
|
|
77
79
|
* @evidence contracts/common.md#clear-and-simple-design The pure attempt policy selects acceptance and retry budgets; this loop owns mutable learned facts and resource handoff, capture owns proof construction, and the shared error builder owns terminal rendering and final disposal.
|
|
78
|
-
* @evidence contracts/common.md#prohibited-implementation-shortcuts Retrying follows learned dependencies/case policy or refuted publication payload rather than an endless workaround chain; only lossless producer-authorized observation unavailability can permit a local fresh answer, and it never becomes
|
|
80
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Retrying follows learned dependencies/case policy or refuted publication payload rather than an endless workaround chain; only lossless producer-authorized observation unavailability can permit a local fresh answer, and it never becomes complete or persistent/shared success proof or excuses actual mutation.
|
|
79
81
|
* @evidence contracts/common.md#meaningful-documentation Native paragraphs explain movement versus absolute budgets, failed-compile diagnostics and learned facts; separated props state delivery, tracking and inherited witness meaning.
|
|
80
82
|
* @evidence contracts/portability.md#os-neutral-implementation Each capture delegates native filesystem and compiler behavior to injected host boundaries; reported compiler case policy is carried between attempts rather than guessed from OS names.
|
|
81
83
|
* @evidence contracts/performance.md#efficient-algorithms At most four captures bound retry count, not each capture's project/config/input bytes, native walks, compiler/plugin work, observer setup or session waiting time. Each rejected attempt copies the cumulative witnessed Set and scans its external dependencies into that copy; the next capture receives a separate array of its names; supplied spellings contribute hashing/text cost. Terminal rendering visits retained attempts/witnesses, and disposal delegates observer/probe cleanup rather than making those effects constant work. Enabled tracing serializes disposition scalars and path text through the existing bounded append sink; disabled tracing skips that payload construction.
|
|
@@ -200,10 +202,12 @@ export async function transformProject(props: {
|
|
|
200
202
|
},
|
|
201
203
|
});
|
|
202
204
|
if (disposition.freshDeliveryOnly) {
|
|
203
|
-
//
|
|
204
|
-
//
|
|
205
|
+
// Missing observations never authorize persistent or shared reuse. A
|
|
206
|
+
// coherent fresh-only local success may separately earn bounded first
|
|
207
|
+
// deliveries through the common nonwatching pass owner (#1713).
|
|
205
208
|
cached.freshDeliveryOnly = true;
|
|
206
209
|
}
|
|
210
|
+
if (disposition.kind === "fresh-only") cached.passDeliveryOnly = true;
|
|
207
211
|
if (disposition.kind === "accepted" || disposition.kind === "fresh-only") {
|
|
208
212
|
return cached;
|
|
209
213
|
}
|
|
@@ -12,23 +12,30 @@ import { pluginSourceHolds } from "./pluginSourceHolds";
|
|
|
12
12
|
const asyncResults = new WeakSet<object>();
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Qualify actual plugin toolchain authority before synchronous input proofs.
|
|
16
16
|
* Cold Go/environment/SDK work stays off the host thread. A mismatch requests
|
|
17
17
|
* one fresh native environment reading; observation failure remains unavailable
|
|
18
18
|
* and the following admission or replay validator retains its failure policy. A
|
|
19
19
|
* resident generation can reuse its exact proven source state while healthy
|
|
20
20
|
* notifications and the still-qualified environment witness both hold. Native
|
|
21
|
-
* environment
|
|
21
|
+
* environment authority remains mandatory; source events cannot prove it.
|
|
22
|
+
*
|
|
23
|
+
* WARNING (#1712): yield before observing queued source changes, then qualify
|
|
24
|
+
* all current readings in one synchronous batch. Missing readings require an
|
|
25
|
+
* await and a fresh batch afterward. Source comparisons may request native
|
|
26
|
+
* refreshes; the caller must establish another current proof after those
|
|
27
|
+
* awaits. Never preserve a positive batch across an await or replay the SDK
|
|
28
|
+
* witness independently for every plugin and nested validator.
|
|
22
29
|
*
|
|
23
30
|
* @param cached Optional resident generation whose existing source-state and
|
|
24
31
|
* environment witness may qualify source reuse. Other preparation owners
|
|
25
32
|
* retain direct source comparison.
|
|
26
|
-
* @evidence contracts/common.md#principled-implementation Every reported plugin directory
|
|
33
|
+
* @evidence contracts/common.md#principled-implementation Every reported plugin directory qualifies current environment authority; only missing readings require asynchronous preparation. The same result's matching manifest state can share source proof only with a healthy exact-source tracker and the environment under which that tree was proven. Otherwise this operation compares source state once and a mismatch refreshes environment authority for the following owning validator to compare again; failed preparation cannot qualify an input.
|
|
27
34
|
* @evidence contracts/common.md#clear-and-simple-design One async boundary precedes existing synchronous generation, delivery and terminal proofs.
|
|
28
35
|
* @evidence contracts/common.md#prohibited-implementation-shortcuts Missing observations stay unproved; reported binary state never substitutes for native environment preparation or source comparison.
|
|
29
36
|
* @evidence contracts/common.md#meaningful-documentation Native prose identifies off-thread work, mismatch refresh and preserved downstream failure ownership.
|
|
30
37
|
* @evidence contracts/portability.md#os-neutral-implementation The same native toolchain/environment reader and caller filesystem source digest qualify each directory without platform guesses.
|
|
31
|
-
* @evidence contracts/performance.md#efficient-algorithms The envelope selector
|
|
38
|
+
* @evidence contracts/performance.md#efficient-algorithms The envelope selector indexes directories once per result. Linear directory passes batch-qualify current readings, prepare missing authority, compare source state and refresh mismatches. Each synchronous batch hashes variables once and shares distinct native dependencies; any preparation await requires another current batch. A qualified source witness avoids enumeration; other source comparisons enumerate and sort files, check metadata and hash bytes when the digest cannot be reused. A mismatch requests one environment refresh rather than a second source comparison here.
|
|
32
39
|
* @evidence contracts/performance.md#reuse-equivalent-work The environment owner shares equivalent in-flight requests and still-qualified readings. Resident source proof is reused only for the exact result and manifest digest, unchanged qualified environment and currently healthy covered source notifications; absent, dirty, replaced or unavailable witnesses retain direct proof. No epoch or quiet watcher alone authorizes reuse, and subsequent admission still owns its current validation.
|
|
33
40
|
* @evidence contracts/performance.md#bound-retention-and-release-resources This module records asynchronous execution ownership in a WeakSet before preparation, including failures, so disposed results are not retained. Requests and worker lifetimes remain with the environment owner; this sequential operation awaits each request and acquires no native observer or independent cancellation handle.
|
|
34
41
|
*/
|
|
@@ -38,10 +45,30 @@ export async function preparePluginBuildEnvironments(
|
|
|
38
45
|
cached?: TtscCachedProjectTransform,
|
|
39
46
|
): Promise<void> {
|
|
40
47
|
asyncResults.add(result);
|
|
41
|
-
|
|
48
|
+
const sources = selectPluginSourceInputs(result);
|
|
49
|
+
// Preserve the async preparation boundary even for warm environments.
|
|
50
|
+
// Events queued by the caller before awaiting preparation must participate
|
|
51
|
+
// in the source witness below. Observe the batch after this yield, never
|
|
52
|
+
// carry a positive environment observation across it (#1712).
|
|
53
|
+
await Promise.resolve();
|
|
54
|
+
const current = PluginBuildEnvironmentReadings.cachedAll(sources.keys());
|
|
55
|
+
let awaited = false;
|
|
56
|
+
for (const directory of sources.keys()) {
|
|
57
|
+
if (current.get(directory) !== undefined) continue;
|
|
58
|
+
awaited = true;
|
|
42
59
|
try {
|
|
43
60
|
await PluginBuildEnvironmentReadings.prepare(directory);
|
|
44
|
-
|
|
61
|
+
} catch {
|
|
62
|
+
// Keep unavailable authority for admission rather than cold fallback.
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const environments = awaited
|
|
66
|
+
? PluginBuildEnvironmentReadings.cachedAll(sources.keys())
|
|
67
|
+
: current;
|
|
68
|
+
const refresh: string[] = [];
|
|
69
|
+
for (const [directory, state] of sources) {
|
|
70
|
+
try {
|
|
71
|
+
const environment = environments.get(directory);
|
|
45
72
|
if (
|
|
46
73
|
cached?.result === result &&
|
|
47
74
|
cached.hostInputValidation?.trees.get(directory) === state &&
|
|
@@ -56,12 +83,19 @@ export async function preparePluginBuildEnvironments(
|
|
|
56
83
|
environment,
|
|
57
84
|
})
|
|
58
85
|
)
|
|
59
|
-
|
|
86
|
+
refresh.push(directory);
|
|
60
87
|
} catch {
|
|
61
88
|
// Admission and terminal recovery interpret unavailable proof in their
|
|
62
89
|
// own domain; this boundary never upgrades it to a successful reading.
|
|
63
90
|
}
|
|
64
91
|
}
|
|
92
|
+
for (const directory of refresh) {
|
|
93
|
+
try {
|
|
94
|
+
await PluginBuildEnvironmentReadings.prepare(directory, true);
|
|
95
|
+
} catch {
|
|
96
|
+
// Synchronous admission requalifies after this asynchronous window.
|
|
97
|
+
}
|
|
98
|
+
}
|
|
65
99
|
}
|
|
66
100
|
|
|
67
101
|
/**
|
|
@@ -6,10 +6,11 @@ import type { WatchBrokerRegistration } from "./WatchBrokerRegistration";
|
|
|
6
6
|
* The live state of the isolated watch process.
|
|
7
7
|
*
|
|
8
8
|
* The broker multiplexes every Windows and macOS watch of the process over one
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* ordered transport, a tracker's and an input observer's scope's alike. Windows
|
|
10
|
+
* uses the native helper's stdio; macOS uses Node IPC. Registrations and drains
|
|
11
|
+
* are counted so the channel is referenced only while a reply is outstanding,
|
|
12
|
+
* and each registration keeps the sink its messages go to and the spelling map
|
|
13
|
+
* that translates the child's canonical paths back to its own.
|
|
13
14
|
*
|
|
14
15
|
* @evidence contracts/common.md#principled-implementation
|
|
15
16
|
* Registration and request ids distinguish multiplexed owners; drain scopes
|
|
@@ -38,6 +39,16 @@ export interface WatchBroker {
|
|
|
38
39
|
/** The isolated watch process; unreferenced whenever no reply is outstanding. */
|
|
39
40
|
child: ChildProcess;
|
|
40
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Native stdio transport on Windows; absent for the macOS IPC broker and
|
|
44
|
+
* explicit test transports.
|
|
45
|
+
*/
|
|
46
|
+
transport?: {
|
|
47
|
+
send(message: unknown): boolean;
|
|
48
|
+
reference(active: boolean): void;
|
|
49
|
+
close(): void;
|
|
50
|
+
};
|
|
51
|
+
|
|
41
52
|
/**
|
|
42
53
|
* Round-trips awaiting the child's reply, by request id, each released with
|
|
43
54
|
* whether the child answered it.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { WatchBroker } from "./WatchBroker";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Common lifecycle seam for the native Windows stdio broker and macOS IPC.
|
|
5
|
+
*
|
|
6
|
+
* The transport owns framing and demand references only. Ordered native
|
|
7
|
+
* notifications and per-registration readiness remain backend responsibilities;
|
|
8
|
+
* a successful send cannot certify coverage or cache reuse.
|
|
9
|
+
*
|
|
10
|
+
* @evidence contracts/common.md#principled-implementation One transport seam preserves explicit failure and reference ownership for both supported broker backends.
|
|
11
|
+
* @evidence contracts/common.md#clear-and-simple-design Callers express send, demand and retirement through this namespace instead of duplicating platform checks or modifying a ChildProcess.
|
|
12
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Supported child streams and IPC APIs are used without replacing runtime methods.
|
|
13
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose separates transport completion from native watch authority.
|
|
14
|
+
* @evidence contracts/portability.md#os-neutral-implementation Native selection stays at broker startup; all tracker and observer consumers share these operations.
|
|
15
|
+
* @evidenceExclude contracts/performance.md#efficient-algorithms Member operations own their delegated cost.
|
|
16
|
+
* @evidenceExclude contracts/performance.md#reuse-equivalent-work The broker owner selects transport and sharing lifetime.
|
|
17
|
+
* @evidenceExclude contracts/performance.md#bound-retention-and-release-resources This namespace itself retains no transport registry.
|
|
18
|
+
*/
|
|
19
|
+
export namespace WatchBrokerTransport {
|
|
20
|
+
/**
|
|
21
|
+
* Queue a message on the selected transport. False refuses delivery; true
|
|
22
|
+
* only means queued, with actual acknowledgment or failure still
|
|
23
|
+
* outstanding.
|
|
24
|
+
*
|
|
25
|
+
* @evidence contracts/common.md#principled-implementation Native and IPC transports preserve separate queue acceptance and observed backend replies.
|
|
26
|
+
* @evidence contracts/common.md#clear-and-simple-design One selection delegates framing to the startup-owned transport.
|
|
27
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts No queue result is upgraded into readiness or a native drain.
|
|
28
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose states the limited meaning of the returned boolean.
|
|
29
|
+
* @evidence contracts/portability.md#os-neutral-implementation Explicit stdio capability takes precedence over optional IPC.
|
|
30
|
+
* @evidence contracts/performance.md#efficient-algorithms Transport selection is fixed work; JSON framing, message bytes and pipe backpressure belong to the selected sender.
|
|
31
|
+
* @evidenceExclude contracts/performance.md#reuse-equivalent-work Sending an effect does not own computation reuse.
|
|
32
|
+
* @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The selected sender and request owner retain queued bytes and outstanding acknowledgment state.
|
|
33
|
+
*/
|
|
34
|
+
export function send(broker: WatchBroker, message: unknown): boolean {
|
|
35
|
+
return broker.transport === undefined
|
|
36
|
+
? broker.child.send?.(message as object) === true
|
|
37
|
+
: broker.transport.send(message);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Keep the selected reply channel live exactly while caller demand exists.
|
|
42
|
+
* Counts belong to registration/drain owners; native references are flags.
|
|
43
|
+
*
|
|
44
|
+
* @evidence contracts/common.md#principled-implementation Outstanding requests retain both process and reply channel, preventing host exit before acknowledgment.
|
|
45
|
+
* @evidence contracts/common.md#clear-and-simple-design One operation applies the caller's aggregated demand to either transport.
|
|
46
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Optional Bun IPC methods are used as capabilities without installing replacements.
|
|
47
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose identifies count ownership and flag semantics.
|
|
48
|
+
* @evidence contracts/portability.md#os-neutral-implementation Optional IPC methods and a selected native pipe capability express runtime differences.
|
|
49
|
+
* @evidenceExclude contracts/performance.md#efficient-algorithms Reference toggling selects no data-processing algorithm.
|
|
50
|
+
* @evidenceExclude contracts/performance.md#reuse-equivalent-work This effect owns no shared computation.
|
|
51
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources The caller supplies aggregate demand; removing the last demand unreferences process and reply channel without asserting native termination.
|
|
52
|
+
*/
|
|
53
|
+
export function reference(broker: WatchBroker, active: boolean): void {
|
|
54
|
+
if (broker.transport !== undefined) broker.transport.reference(active);
|
|
55
|
+
else if (active) {
|
|
56
|
+
broker.child.ref();
|
|
57
|
+
broker.child.channel?.ref?.();
|
|
58
|
+
} else {
|
|
59
|
+
broker.child.unref();
|
|
60
|
+
broker.child.channel?.unref?.();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* End this broker's request stream. The last-registration owner separately
|
|
66
|
+
* attempts process termination; closing a channel is not proof of child
|
|
67
|
+
* exit.
|
|
68
|
+
*
|
|
69
|
+
* @evidence contracts/common.md#principled-implementation Channel retirement is distinct from process exit and native resource closure.
|
|
70
|
+
* @evidence contracts/common.md#clear-and-simple-design Startup-owned transport closes its request stream without platform checks in consumers.
|
|
71
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Supported end/disconnect operations preserve native ownership without synthetic exit acknowledgment.
|
|
72
|
+
* @evidence contracts/common.md#meaningful-documentation Native prose identifies the independent termination attempt and limited closure meaning.
|
|
73
|
+
* @evidence contracts/portability.md#os-neutral-implementation Selected stream closure and optional IPC disconnection keep platform details behind the transport seam.
|
|
74
|
+
* @evidenceExclude contracts/performance.md#efficient-algorithms Closing one channel selects no processing algorithm.
|
|
75
|
+
* @evidenceExclude contracts/performance.md#reuse-equivalent-work Retirement owns no computation reuse.
|
|
76
|
+
* @evidence contracts/performance.md#bound-retention-and-release-resources The selected transport ends its input; process kill and actual native cleanup remain the broker and backend's responsibilities.
|
|
77
|
+
*/
|
|
78
|
+
export function close(broker: WatchBroker): void {
|
|
79
|
+
if (broker.transport !== undefined) broker.transport.close();
|
|
80
|
+
else broker.child.disconnect?.();
|
|
81
|
+
}
|
|
82
|
+
}
|