ttsc 0.31.0 → 0.31.2

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 (155) hide show
  1. package/cmd/platform/main.go +2 -2
  2. package/internal/sourceprocess/contain_windows.go +10 -13
  3. package/internal/sourceprocess/started_windows.go +41 -0
  4. package/internal/sourceprocess/windows_started_publication_distinguishes_pending_from_refusal_test.go +76 -0
  5. package/internal/watchhelper/run.go +30 -20
  6. package/internal/watchhelper/run_other.go +4 -4
  7. package/internal/watchhelper/run_windows.go +471 -0
  8. package/internal/watchhelper/watchhelper.go +8 -2
  9. package/internal/watchhelper/windows_notifications_preserve_mutations_without_access_noise_test.go +506 -0
  10. package/lib/compiler/internal/build/BuildExecution.d.ts +4 -2
  11. package/lib/compiler/internal/build/BuildExecution.js +40 -12
  12. package/lib/compiler/internal/build/BuildExecution.js.map +1 -1
  13. package/lib/compiler/internal/startResidentTransform.js +5 -4
  14. package/lib/compiler/internal/startResidentTransform.js.map +1 -1
  15. package/lib/compiler/internal/transformProjectInMemory.js +9 -7
  16. package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
  17. package/lib/internal/javascriptRuntimeCapabilities.d.ts +13 -4
  18. package/lib/internal/javascriptRuntimeCapabilities.js +56 -6
  19. package/lib/internal/javascriptRuntimeCapabilities.js.map +1 -1
  20. package/lib/internal/nativeBinary.d.ts +3 -3
  21. package/lib/internal/nativeBinary.js +3 -3
  22. package/lib/internal/pluginSource.d.ts +1 -0
  23. package/lib/internal/pluginSource.js +1 -0
  24. package/lib/internal/pluginSource.js.map +1 -1
  25. package/lib/internal/resolveNodeBinary.d.ts +6 -1
  26. package/lib/internal/resolveNodeBinary.js +6 -2
  27. package/lib/internal/resolveNodeBinary.js.map +1 -1
  28. package/lib/internal/runtimeExecutableIdentity.d.ts +22 -13
  29. package/lib/internal/runtimeExecutableIdentity.js +192 -102
  30. package/lib/internal/runtimeExecutableIdentity.js.map +1 -1
  31. package/lib/launcher/internal/runtime/installRuntimeHooks.js +58 -4
  32. package/lib/launcher/internal/runtime/installRuntimeHooks.js.map +1 -1
  33. package/lib/launcher/internal/ttscserver/captureLSPPluginSelectionInputs.d.ts +5 -1
  34. package/lib/launcher/internal/ttscserver/captureLSPPluginSelectionInputs.js +7 -2
  35. package/lib/launcher/internal/ttscserver/captureLSPPluginSelectionInputs.js.map +1 -1
  36. package/lib/launcher/internal/ttscserver/runTtscserver.js +8 -1
  37. package/lib/launcher/internal/ttscserver/runTtscserver.js.map +1 -1
  38. package/lib/plugin/internal/CapabilityResolutionFormat.d.ts +21 -62
  39. package/lib/plugin/internal/CapabilityResolutionFormat.js +15 -106
  40. package/lib/plugin/internal/CapabilityResolutionFormat.js.map +1 -1
  41. package/lib/plugin/internal/load/PluginDescriptorEvaluationCache.d.ts +6 -0
  42. package/lib/plugin/internal/load/PluginDescriptorEvaluationCache.js +4 -4
  43. package/lib/plugin/internal/load/PluginDescriptorEvaluationCache.js.map +1 -1
  44. package/lib/plugin/internal/load/loadProjectPlugins.d.ts +24 -14
  45. package/lib/plugin/internal/load/loadProjectPlugins.js +141 -56
  46. package/lib/plugin/internal/load/loadProjectPlugins.js.map +1 -1
  47. package/lib/plugin/internal/readCapabilityResolution.d.ts +6 -0
  48. package/lib/plugin/internal/readCapabilityResolution.js +8 -5
  49. package/lib/plugin/internal/readCapabilityResolution.js.map +1 -1
  50. package/lib/plugin/internal/source/GoEnvironmentReading.d.ts +48 -0
  51. package/lib/plugin/internal/source/GoEnvironmentReading.js +156 -0
  52. package/lib/plugin/internal/source/GoEnvironmentReading.js.map +1 -0
  53. package/lib/plugin/internal/source/NativeSourcePackages.d.ts +51 -13
  54. package/lib/plugin/internal/source/NativeSourcePackages.js +182 -27
  55. package/lib/plugin/internal/source/NativeSourcePackages.js.map +1 -1
  56. package/lib/plugin/internal/source/PluginBuildEnvironmentReadings.d.ts +42 -3
  57. package/lib/plugin/internal/source/PluginBuildEnvironmentReadings.js +68 -7
  58. package/lib/plugin/internal/source/PluginBuildEnvironmentReadings.js.map +1 -1
  59. package/lib/plugin/internal/source/PluginBuildEnvironmentWitness.d.ts +5 -3
  60. package/lib/plugin/internal/source/PluginBuildEnvironmentWitness.js +14 -8
  61. package/lib/plugin/internal/source/PluginBuildEnvironmentWitness.js.map +1 -1
  62. package/lib/plugin/internal/source/PluginContentIdentities.d.ts +265 -0
  63. package/lib/plugin/internal/source/PluginContentIdentities.js +452 -0
  64. package/lib/plugin/internal/source/PluginContentIdentities.js.map +1 -0
  65. package/lib/plugin/internal/source/PluginLoadAnswers.d.ts +63 -0
  66. package/lib/plugin/internal/source/PluginLoadAnswers.js +128 -0
  67. package/lib/plugin/internal/source/PluginLoadAnswers.js.map +1 -0
  68. package/lib/plugin/internal/source/SourceBuildCacheLayout.d.ts +10 -0
  69. package/lib/plugin/internal/source/SourceBuildCacheLayout.js +12 -0
  70. package/lib/plugin/internal/source/SourceBuildCacheLayout.js.map +1 -1
  71. package/lib/plugin/internal/source/SourcePluginWorkspace.d.ts +53 -19
  72. package/lib/plugin/internal/source/SourcePluginWorkspace.js +111 -22
  73. package/lib/plugin/internal/source/SourcePluginWorkspace.js.map +1 -1
  74. package/lib/plugin/internal/source/buildSourcePlugin.d.ts +34 -18
  75. package/lib/plugin/internal/source/buildSourcePlugin.js +52 -24
  76. package/lib/plugin/internal/source/buildSourcePlugin.js.map +1 -1
  77. package/lib/plugin/internal/source/computeCacheKey.d.ts +25 -7
  78. package/lib/plugin/internal/source/computeCacheKey.js +85 -34
  79. package/lib/plugin/internal/source/computeCacheKey.js.map +1 -1
  80. package/lib/plugin/internal/source/hashPluginBuildEnvironment.d.ts +7 -3
  81. package/lib/plugin/internal/source/hashPluginBuildEnvironment.js +75 -102
  82. package/lib/plugin/internal/source/hashPluginBuildEnvironment.js.map +1 -1
  83. package/lib/plugin/internal/source/pluginBuildEnvironment.d.ts +8 -3
  84. package/lib/plugin/internal/source/pluginBuildEnvironment.js +8 -4
  85. package/lib/plugin/internal/source/pluginBuildEnvironment.js.map +1 -1
  86. package/lib/plugin/internal/source/pluginBuildEnvironmentWorker.js +12 -2
  87. package/lib/plugin/internal/source/pluginBuildEnvironmentWorker.js.map +1 -1
  88. package/lib/plugin/internal/source/pluginBuildVersions.d.ts +2 -2
  89. package/lib/plugin/internal/source/pluginBuildVersions.js +4 -17
  90. package/lib/plugin/internal/source/pluginBuildVersions.js.map +1 -1
  91. package/lib/plugin/internal/source/pluginModuleReplaceDirectories.d.ts +6 -5
  92. package/lib/plugin/internal/source/pluginModuleReplaceDirectories.js +10 -17
  93. package/lib/plugin/internal/source/pluginModuleReplaceDirectories.js.map +1 -1
  94. package/lib/plugin/internal/source/pluginSourceState.d.ts +6 -2
  95. package/lib/plugin/internal/source/pluginSourceState.js +20 -8
  96. package/lib/plugin/internal/source/pluginSourceState.js.map +1 -1
  97. package/lib/plugin/internal/source/pluginSourceStateHolds.d.ts +7 -2
  98. package/lib/plugin/internal/source/pluginSourceStateHolds.js +12 -7
  99. package/lib/plugin/internal/source/pluginSourceStateHolds.js.map +1 -1
  100. package/lib/plugin/internal/source/processPluginBuildEnvironment.d.ts +7 -2
  101. package/lib/plugin/internal/source/processPluginBuildEnvironment.js +8 -3
  102. package/lib/plugin/internal/source/processPluginBuildEnvironment.js.map +1 -1
  103. package/lib/plugin/internal/source/provenPluginSourceDigest.d.ts +28 -0
  104. package/lib/plugin/internal/source/provenPluginSourceDigest.js +41 -0
  105. package/lib/plugin/internal/source/provenPluginSourceDigest.js.map +1 -0
  106. package/lib/plugin/internal/source/pruneCacheFileRoot.d.ts +3 -2
  107. package/lib/plugin/internal/source/pruneCacheFileRoot.js +3 -2
  108. package/lib/plugin/internal/source/pruneCacheFileRoot.js.map +1 -1
  109. package/lib/plugin/internal/source/ttscPackageVersion.d.ts +26 -0
  110. package/lib/plugin/internal/source/ttscPackageVersion.js +47 -0
  111. package/lib/plugin/internal/source/ttscPackageVersion.js.map +1 -0
  112. package/lib/plugin/internal/writeCapabilityResolution.d.ts +6 -0
  113. package/lib/plugin/internal/writeCapabilityResolution.js +11 -7
  114. package/lib/plugin/internal/writeCapabilityResolution.js.map +1 -1
  115. package/lib/plugin/resolveCapabilityPlugins.js +67 -15
  116. package/lib/plugin/resolveCapabilityPlugins.js.map +1 -1
  117. package/package.json +8 -8
  118. package/src/compiler/internal/build/BuildExecution.ts +46 -13
  119. package/src/compiler/internal/startResidentTransform.ts +12 -3
  120. package/src/compiler/internal/transformProjectInMemory.ts +10 -2
  121. package/src/internal/javascriptRuntimeCapabilities.ts +71 -5
  122. package/src/internal/nativeBinary.ts +3 -3
  123. package/src/internal/pluginSource.ts +1 -0
  124. package/src/internal/resolveNodeBinary.ts +12 -1
  125. package/src/internal/runtimeExecutableIdentity.ts +227 -141
  126. package/src/launcher/internal/runtime/installRuntimeHooks.ts +68 -3
  127. package/src/launcher/internal/ttscserver/captureLSPPluginSelectionInputs.ts +11 -2
  128. package/src/launcher/internal/ttscserver/runTtscserver.ts +18 -1
  129. package/src/plugin/internal/CapabilityResolutionFormat.ts +23 -107
  130. package/src/plugin/internal/load/PluginDescriptorEvaluationCache.ts +14 -4
  131. package/src/plugin/internal/load/loadProjectPlugins.ts +421 -211
  132. package/src/plugin/internal/readCapabilityResolution.ts +17 -6
  133. package/src/plugin/internal/source/GoEnvironmentReading.ts +178 -0
  134. package/src/plugin/internal/source/NativeSourcePackages.ts +365 -48
  135. package/src/plugin/internal/source/PluginBuildEnvironmentReadings.ts +83 -5
  136. package/src/plugin/internal/source/PluginBuildEnvironmentWitness.ts +18 -8
  137. package/src/plugin/internal/source/PluginContentIdentities.ts +563 -0
  138. package/src/plugin/internal/source/PluginLoadAnswers.ts +151 -0
  139. package/src/plugin/internal/source/SourceBuildCacheLayout.ts +14 -0
  140. package/src/plugin/internal/source/SourcePluginWorkspace.ts +148 -25
  141. package/src/plugin/internal/source/buildSourcePlugin.ts +104 -36
  142. package/src/plugin/internal/source/computeCacheKey.ts +129 -55
  143. package/src/plugin/internal/source/hashPluginBuildEnvironment.ts +152 -105
  144. package/src/plugin/internal/source/pluginBuildEnvironment.ts +9 -2
  145. package/src/plugin/internal/source/pluginBuildEnvironmentWorker.ts +18 -2
  146. package/src/plugin/internal/source/pluginBuildVersions.ts +5 -26
  147. package/src/plugin/internal/source/pluginModuleReplaceDirectories.ts +13 -25
  148. package/src/plugin/internal/source/pluginSourceState.ts +28 -12
  149. package/src/plugin/internal/source/pluginSourceStateHolds.ts +15 -8
  150. package/src/plugin/internal/source/processPluginBuildEnvironment.ts +8 -2
  151. package/src/plugin/internal/source/provenPluginSourceDigest.ts +45 -0
  152. package/src/plugin/internal/source/pruneCacheFileRoot.ts +3 -2
  153. package/src/plugin/internal/source/ttscPackageVersion.ts +45 -0
  154. package/src/plugin/internal/writeCapabilityResolution.ts +29 -8
  155. package/src/plugin/resolveCapabilityPlugins.ts +87 -13
@@ -0,0 +1,452 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PluginContentIdentities = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_os_1 = __importDefault(require("node:os"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const SidecarEnvironment_1 = require("../../../compiler/internal/sharedHost/SidecarEnvironment");
12
+ const E2ETrace_1 = require("../../../internal/E2ETrace");
13
+ const SourceBuildCacheLayout_1 = require("./SourceBuildCacheLayout");
14
+ const pluginSourceCovers_1 = require("./pluginSourceCovers");
15
+ const pluginSourceDigest_1 = require("./pluginSourceDigest");
16
+ const pluginSourceFilesSignature_1 = require("./pluginSourceFilesSignature");
17
+ const recordCacheFileUse_1 = require("./recordCacheFileUse");
18
+ const resolveSourceBuildCachePaths_1 = require("./resolveSourceBuildCachePaths");
19
+ const ttscPackageVersion_1 = require("./ttscPackageVersion");
20
+ /**
21
+ * Content identities a plugin load proves from metadata instead of bytes, kept
22
+ * in the plugin cache root so they outlive the process that read them.
23
+ *
24
+ * WARNING (#1721, #1722, #1723): a warm plugin load must not pay for its
25
+ * inputs' bytes. Before this owner existed, every launch, every `ttsx` process,
26
+ * every `@ttsc/unplugin` worker and the build-environment worker re-read the
27
+ * plugin module, the ttsc overlays, the whole GOROOT and the Go and JavaScript
28
+ * runtimes, because each earlier fix (#1186, #1712) kept its reuse inside one
29
+ * process. A process is not the unit of reuse: a CLI launch is one process. Any
30
+ * new content identity on the load path belongs here, and a memo that only
31
+ * lives in module state is not a fix for this class.
32
+ *
33
+ * A record pairs the digest of a selected population with the metadata
34
+ * signature of that population, and is trusted only under the separable-stamp
35
+ * rule settled by #1227 and #1344: every stamp must be strictly older than a
36
+ * reference minted on the same device by this store's own write, so no later
37
+ * write can share a recorded tick. References are minted on the cache root's
38
+ * volume and on the system temporary directory's volume, which together hold
39
+ * the project, its plugins and toolchain, and a system-installed runtime. A
40
+ * record is written only when the signature observed before the content read
41
+ * equals the one observed after it and both are separable. Reuse still assumes
42
+ * the filesystem reports writes in its metadata (identity, size, modification
43
+ * and change times); change time moves on every write and cannot be restored by
44
+ * an ordinary process. A population on a device without a reference, an
45
+ * unseparable stamp, a missing or foreign record, or any observation failure
46
+ * falls back to reading content, exactly as before this owner.
47
+ *
48
+ * Records live in single-file cache parts (`SourceBuildCacheLayout`), so the
49
+ * opportunistic collector ages them out and `ttsc clean` removes them. Their
50
+ * identity includes the record format and the ttsc version, so a release that
51
+ * changes a digest rule never reads another release's records.
52
+ *
53
+ * @evidence contracts/common.md#principled-implementation Metadata stands for recorded content only under the established separable-stamp rule, with before/after agreement around the content read; every unproved premise falls back to the content reader.
54
+ * @evidence contracts/common.md#clear-and-simple-design One store owns opening, record identity, reuse and publication; callers supply only the population observation and the content reader they already own.
55
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts No path-only or process-permanent memo stands for content; failures and unseparable stamps cause the real read rather than a guessed digest.
56
+ * @evidence contracts/common.md#meaningful-documentation Native paragraphs state the regression this owner prevents, the proof premises, the fallback and the storage lifetime.
57
+ * @evidence contracts/portability.md#os-neutral-implementation References are keyed by the native device that minted them and stamps are compared per device; no timestamp precision or platform name is assumed.
58
+ * @evidenceExclude contracts/performance.md#efficient-algorithms The namespace groups operations; each member states its own work.
59
+ * @evidenceExclude contracts/performance.md#reuse-equivalent-work Members define the reuse identity and its validity.
60
+ * @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Members define what they retain; the namespace holds no state.
61
+ */
62
+ var PluginContentIdentities;
63
+ (function (PluginContentIdentities) {
64
+ /**
65
+ * Open the store under a plugin cache root and mint its clock reference, or
66
+ * return `undefined` when the root cannot hold records, so callers read
67
+ * content as they did without one.
68
+ *
69
+ * The root follows the plugin cache policy (`resolveSourceBuildCachePaths`):
70
+ * an explicit `cacheDir`, `TTSC_CACHE_DIR`, or the workspace-local default. A
71
+ * default root is marked as selected before its first write, as every other
72
+ * default writer does, so a later root search never mistakes the new payload
73
+ * for an older orphan. One reference is minted in the root's identity
74
+ * directory, and the store exists only when that write succeeds. Another is
75
+ * minted in a private per-user directory below the system temporary
76
+ * directory, so an executable or SDK on the system volume is separable even
77
+ * when the project lives on another volume.
78
+ *
79
+ * A root inside any of `sources` is refused before anything is written: the
80
+ * build rejects such a cache (`SourcePluginAdmission`), and a record written
81
+ * there would change the very source it describes.
82
+ *
83
+ * @param props.projectRoot Project whose cache root is selected.
84
+ * @param props.cacheDir Explicit caller cache root, when one was given.
85
+ * @param props.env Effective environment selecting `TTSC_CACHE_DIR`.
86
+ * @param props.sources Plugin source directories the root must lie outside.
87
+ * @evidence contracts/common.md#principled-implementation The plugin cache policy selects the root, default roots are marked before payload, and the reference comes from a fresh owned probe; any failure withholds the store so callers keep the content path.
88
+ * @evidence contracts/common.md#clear-and-simple-design Root policy and the probe are delegated to their existing owners; this function composes them once per load.
89
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts No wall clock or historical stamp substitutes for the minted reference.
90
+ * @evidence contracts/common.md#meaningful-documentation Native paragraphs state root selection, the marker ordering and the undefined fallback.
91
+ * @evidence contracts/portability.md#os-neutral-implementation Native path resolution and the probe's device identity carry platform semantics; Windows environment names are read case-insensitively by the shared reader.
92
+ * @evidence contracts/performance.md#efficient-algorithms Root selection can walk ancestors and read manifests; each of the two probes performs one directory creation, one write, one lstat and one removal; the temporary one also checks its directory's ownership. No plugin source is read.
93
+ * @evidenceExclude contracts/performance.md#reuse-equivalent-work Each load needs a freshly minted reference; reusing an older one would defeat the separation premise.
94
+ * @evidence contracts/performance.md#bound-retention-and-release-resources Each probe is removed in its owner's finally; the per-user temporary directory stays, empty, for later loads so the temporary directory itself does not move. The returned store retains at most two device references and two strings.
95
+ */
96
+ function open(props) {
97
+ try {
98
+ const selected = (0, resolveSourceBuildCachePaths_1.resolveSourceBuildCachePaths)(props.projectRoot, props.cacheDir, props.env).root;
99
+ if (coversRoot(selected, props.sources ?? []))
100
+ return undefined;
101
+ const root = props.cacheDir || SidecarEnvironment_1.SidecarEnvironment.read(props.env, "TTSC_CACHE_DIR")
102
+ ? selected
103
+ : SourceBuildCacheLayout_1.SourceBuildCacheLayout.markDefaultWorkspaceCacheRoot(selected);
104
+ const owned = mintReference(node_path_1.default.join(root, SourceBuildCacheLayout_1.SourceBuildCacheLayout.IDENTITY_CACHE_DIRNAME));
105
+ if (owned.size === 0)
106
+ return undefined;
107
+ // The cache root's device covers the project, its installed plugins and
108
+ // the toolchain bundled with them. A runtime or SDK installed elsewhere,
109
+ // typically on the system drive, is judged against a second reference
110
+ // minted in a per-user directory below the system temporary directory.
111
+ const references = new Map([...temporaryReference(), ...owned]);
112
+ // WARNING (#1726): resolve no module here. A descriptor evaluator opens a
113
+ // store under its resolution recorder, and any lookup becomes an input of
114
+ // the descriptor it did not read (`ttscPackageVersion`).
115
+ return { root, references, version: (0, ttscPackageVersion_1.ttscPackageVersion)() };
116
+ }
117
+ catch {
118
+ return undefined;
119
+ }
120
+ }
121
+ PluginContentIdentities.open = open;
122
+ /**
123
+ * The store when its root lies outside every one of `sources`, otherwise
124
+ * `undefined`. A loader opens its store before descriptor evaluation names
125
+ * the plugin sources, then narrows it here before any source is proven, so a
126
+ * misplaced cache, which the build rejects, never receives records inside a
127
+ * user's source tree.
128
+ *
129
+ * @param store The opened store, if any.
130
+ * @param sources Plugin source directories the root must lie outside.
131
+ * @evidence contracts/common.md#principled-implementation The build's own containment predicate (`pluginSourceCovers`) decides, so a root below a pruned directory is admitted exactly as the build admits it.
132
+ * @evidence contracts/common.md#clear-and-simple-design One predicate shared by open and late narrowing.
133
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts A covered root withdraws persistence rather than writing into a source.
134
+ * @evidence contracts/common.md#meaningful-documentation Native prose explains the two-phase opening.
135
+ * @evidence contracts/portability.md#os-neutral-implementation Containment uses native path grammar.
136
+ * @evidence contracts/performance.md#efficient-algorithms One relative-path check per source.
137
+ * @evidenceExclude contracts/performance.md#reuse-equivalent-work A predicate over current arguments.
138
+ * @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Nothing is retained.
139
+ */
140
+ function outside(store, sources) {
141
+ return store === undefined || coversRoot(store.root, sources)
142
+ ? undefined
143
+ : store;
144
+ }
145
+ PluginContentIdentities.outside = outside;
146
+ /**
147
+ * The digest of one population: the recorded one while its metadata still
148
+ * holds and is separable, otherwise a fresh content reading, recorded when
149
+ * its metadata held still and separable around the read.
150
+ *
151
+ * A population whose selection would include the store's own root is never
152
+ * recorded, since writing a record would change what it describes; a root
153
+ * below a pruned directory such as `node_modules` is outside every
154
+ * selection.
155
+ *
156
+ * @param store The opened store, or `undefined` to read content only.
157
+ * @param kind Population family; records of different families never mix.
158
+ * @param subject Absolute population path identifying the record.
159
+ * @param observe Current signature of the population against references.
160
+ * @param read The owning content reader; its result is the digest.
161
+ * @evidence contracts/common.md#principled-implementation A record is used only when the current separable signature equals the recorded one; publication requires equal separable signatures before and after the actual content read.
162
+ * @evidence contracts/common.md#clear-and-simple-design The caller keeps population selection and content hashing; this function owns only lookup, admission and publication.
163
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Corrupt, foreign or unproved records cause the real read; the record cannot widen what the caller's reader covers.
164
+ * @evidence contracts/common.md#meaningful-documentation Native paragraphs state the reuse condition and the self-containment exclusion; parameters describe their roles.
165
+ * @evidence contracts/portability.md#os-neutral-implementation Separability is the observer's per-device judgement; record files use native path joins and atomic same-directory replacement.
166
+ * @evidence contracts/performance.md#efficient-algorithms A hit costs one population observation and one small record read; a miss adds the content read and a second observation. Record identity hashes fixed framing text.
167
+ * @evidence contracts/performance.md#reuse-equivalent-work Processes share a digest only for the same family, subject, version and current separable signature that the producing read was bracketed by.
168
+ * @evidence contracts/performance.md#bound-retention-and-release-resources One small file per subject is published atomically and aged out by the single-file collector; hits refresh its use time; nothing is retained in memory.
169
+ */
170
+ function digest(store, kind, subject, observe, read) {
171
+ if (store === undefined ||
172
+ (0, pluginSourceCovers_1.pluginSourceCovers)(subject, store.root, "directory"))
173
+ return read();
174
+ const file = recordFile(store, kind, subject);
175
+ const before = observe(store.references);
176
+ if (before?.separable === true) {
177
+ const known = readRecord(file);
178
+ if (known !== undefined &&
179
+ known.signature === before.signature &&
180
+ known.version === store.version &&
181
+ known.kind === kind &&
182
+ known.subject === subject) {
183
+ (0, recordCacheFileUse_1.recordCacheFileUse)(file);
184
+ E2ETrace_1.E2ETrace.capabilityResolution("plugin-content-identity", {
185
+ kind,
186
+ subject,
187
+ outcome: "reused",
188
+ });
189
+ return known.digest;
190
+ }
191
+ }
192
+ const value = read();
193
+ const after = observe(store.references);
194
+ const recorded = before?.separable === true &&
195
+ after?.separable === true &&
196
+ before.signature === after.signature;
197
+ if (recorded) {
198
+ try {
199
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(file), { recursive: true });
200
+ SourceBuildCacheLayout_1.SourceBuildCacheLayout.replaceCacheMetadataFile(file, JSON.stringify({
201
+ format: FORMAT,
202
+ version: store.version,
203
+ kind,
204
+ subject,
205
+ signature: after.signature,
206
+ digest: value,
207
+ }));
208
+ }
209
+ catch {
210
+ // A record is an optimization; the digest just read stands.
211
+ }
212
+ }
213
+ E2ETrace_1.E2ETrace.capabilityResolution("plugin-content-identity", {
214
+ kind,
215
+ subject,
216
+ outcome: recorded ? "recorded" : "read",
217
+ });
218
+ return value;
219
+ }
220
+ PluginContentIdentities.digest = digest;
221
+ /**
222
+ * The `pluginSourceDigest` of a plugin source directory, proven from the
223
+ * metadata of exactly the files that digest reads.
224
+ *
225
+ * @param store The opened store, or `undefined` to read content only.
226
+ * @param directory The source directory.
227
+ * @evidence contracts/common.md#principled-implementation The signature walks the same `collectPluginSourceFiles` population the digest reads, with the capability cache's separable-stamp evidence; additions, removals and renames change that population.
228
+ * @evidence contracts/common.md#clear-and-simple-design Selection and hashing remain with their owners; this adapter only names the family and subject.
229
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Links and unreadable files fail as the content reader would; no metadata stands for a file the digest does not read.
230
+ * @evidence contracts/common.md#meaningful-documentation Native prose names the shared population.
231
+ * @evidence contracts/portability.md#os-neutral-implementation Native lstat device/inode/link/mode/size/stamps form each file's signature.
232
+ * @evidence contracts/performance.md#efficient-algorithms A hit enumerates and stats F files without reading content; a miss also reads B bytes and stats again.
233
+ * @evidence contracts/performance.md#reuse-equivalent-work Loads in any process share a directory digest while its separable signature holds.
234
+ * @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Storage belongs to digest.
235
+ */
236
+ function sourceDirectory(store, directory) {
237
+ const resolved = node_path_1.default.resolve(directory);
238
+ return digest(store, "plugin-source", resolved, (references) => (0, pluginSourceFilesSignature_1.pluginSourceFilesSignature)(resolved, sourceEvidence(references)), () => (0, pluginSourceDigest_1.pluginSourceDigest)(resolved));
239
+ }
240
+ PluginContentIdentities.sourceDirectory = sourceDirectory;
241
+ /**
242
+ * One regular file's metadata signature, following links, and whether its
243
+ * stamp is separable; `undefined` when it cannot be stated.
244
+ *
245
+ * @param references The store's device references.
246
+ * @param file The file, normally already resolved to its physical path.
247
+ * @evidence contracts/common.md#principled-implementation Device, inode, mode, size and both stamps move on replacement or write; separability requires a same-device reference strictly newer than the modification stamp.
248
+ * @evidence contracts/common.md#clear-and-simple-design One stat produces both fields used by digest.
249
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts A non-regular or unreadable file yields no observation, so the content reader decides.
250
+ * @evidence contracts/common.md#meaningful-documentation Native prose states the following-link semantics and undefined meaning.
251
+ * @evidence contracts/portability.md#os-neutral-implementation Node bigint stat supplies native identity and nanosecond stamps.
252
+ * @evidence contracts/performance.md#efficient-algorithms One native stat and fixed numeric formatting.
253
+ * @evidenceExclude contracts/performance.md#reuse-equivalent-work This is a fresh observation.
254
+ * @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Nothing is retained.
255
+ */
256
+ function fileObservation(references, file) {
257
+ try {
258
+ const stats = node_fs_1.default.statSync(file, { bigint: true });
259
+ if (!stats.isFile())
260
+ return undefined;
261
+ return {
262
+ separable: separable(references, stats),
263
+ signature: [
264
+ stats.dev,
265
+ stats.ino,
266
+ stats.mode,
267
+ stats.size,
268
+ stats.mtimeNs,
269
+ stats.ctimeNs,
270
+ ].join(":"),
271
+ };
272
+ }
273
+ catch {
274
+ return undefined;
275
+ }
276
+ }
277
+ PluginContentIdentities.fileObservation = fileObservation;
278
+ /**
279
+ * Whether a stamp is strictly older than the reference its device minted.
280
+ *
281
+ * @param references The store's device references.
282
+ * @param stats Observed metadata.
283
+ * @evidence contracts/common.md#principled-implementation Only a strictly newer same-device reference separates the recorded modification tick.
284
+ * @evidence contracts/common.md#clear-and-simple-design One lookup and one comparison.
285
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts A missing reference is never replaced by wall time.
286
+ * @evidence contracts/common.md#meaningful-documentation Native prose states the strict ordering.
287
+ * @evidence contracts/portability.md#os-neutral-implementation References are matched by native device identifier.
288
+ * @evidence contracts/performance.md#efficient-algorithms One map lookup and one bigint comparison.
289
+ * @evidenceExclude contracts/performance.md#reuse-equivalent-work A scalar predicate.
290
+ * @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Nothing is retained.
291
+ */
292
+ function separable(references, stats) {
293
+ const minted = references.get(stats.dev);
294
+ return minted !== undefined && stats.mtimeNs < minted;
295
+ }
296
+ PluginContentIdentities.separable = separable;
297
+ /**
298
+ * A clock reference minted by a write of the cache's own: the modification
299
+ * stamp a fresh probe file got in `directory`, by the device that reported
300
+ * it.
301
+ *
302
+ * A stamp strictly older than the same device's fresh reference satisfies the
303
+ * separation policy. Reuse still assumes the filesystem's reported metadata
304
+ * reflects writes; the comparison cannot certify arbitrary timestamp
305
+ * restoration or future clock behavior. The probe is the cache's own file,
306
+ * named for this call, and removal is attempted at once, so concurrent
307
+ * readers never lend each other a reference. A failed write, or a population
308
+ * on another device, leaves nothing separable, and the proof reads the
309
+ * files.
310
+ *
311
+ * @param directory Cache-owned directory the probe is written in.
312
+ * @evidence contracts/common.md#principled-implementation A unique freshly-written file supplies its native device/mtime reference; acquisition failure clears the witness, and observers require a matching device and strictly older reported stamp under the metadata policy.
313
+ * @evidence contracts/common.md#clear-and-simple-design The function returns only device-to-stamp evidence and owns its transient probe from creation through cleanup.
314
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Random probe identity avoids borrowing a concurrent call's witness; failed acquisition does not substitute wall-clock guesses for device evidence.
315
+ * @evidence contracts/common.md#meaningful-documentation Native JSDoc explains ended ticks, cross-device refusal and probe lifetime in separate paragraphs; tag separation follows the documentation skill.
316
+ * @evidence contracts/portability.md#os-neutral-implementation Native joins and bigint lstat use the actual filesystem's device/stamp values; no fixed timestamp precision or OS-specific temp path is assumed.
317
+ * @evidence contracts/performance.md#efficient-algorithms Probe path/UUID/hrtime text construction and mkdir/write/lstat/removal queries produce a witness without reading any population bytes.
318
+ * @evidenceExclude contracts/performance.md#reuse-equivalent-work Each proof needs a fresh clock reference; sharing an earlier probe would defeat the rollback/separation premise.
319
+ * @evidence contracts/performance.md#bound-retention-and-release-resources The unique call-owned probe is removed in finally even after acquisition failure; removal is best effort and the returned map contains at most its single observed device.
320
+ */
321
+ function mintReference(directory) {
322
+ const references = new Map();
323
+ const probe = node_path_1.default.join(directory, `clock-${process.pid}-${node_crypto_1.default.randomUUID()}.probe`);
324
+ try {
325
+ node_fs_1.default.mkdirSync(directory, { recursive: true });
326
+ node_fs_1.default.writeFileSync(probe, `${process.hrtime.bigint()}\n`);
327
+ const stats = node_fs_1.default.lstatSync(probe, { bigint: true });
328
+ references.set(stats.dev, stats.mtimeNs);
329
+ }
330
+ catch {
331
+ references.clear();
332
+ }
333
+ finally {
334
+ try {
335
+ node_fs_1.default.rmSync(probe, { force: true });
336
+ }
337
+ catch {
338
+ // A leftover probe contains this call's hrtime text, not source data.
339
+ }
340
+ }
341
+ return references;
342
+ }
343
+ PluginContentIdentities.mintReference = mintReference;
344
+ /**
345
+ * One plugin source file's metadata signature, and whether its stamp is
346
+ * separable from `references`, for `pluginSourceFilesSignature`.
347
+ *
348
+ * The files the digest reads are regular files (`collectPluginSourceFiles`),
349
+ * so these fields are the observer's metadata signature. Native metadata
350
+ * reflecting a write/replacement is a reuse premise; the signature is not
351
+ * itself a content hash or proof against arbitrary timestamp restoration.
352
+ *
353
+ * @param references The clock references minted for this proof.
354
+ * @evidence contracts/common.md#principled-implementation lstat device/inode/link/mode/size/timestamps form the regular-file metadata signature; strict mtime-before-reference marks separation for a matching device under the native metadata policy, without observing content.
355
+ * @evidence contracts/common.md#clear-and-simple-design A closure carries one proof's device references and maps each requested file to signature/separation together.
356
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Unreadable files return no witness, and unmatched device or same/newer stamps cannot authorize digest reuse.
357
+ * @evidence contracts/common.md#meaningful-documentation Native JSDoc states the regular-file premise and reference origin, with separate acknowledgment prose following the documentation skill.
358
+ * @evidence contracts/portability.md#os-neutral-implementation Metadata comes from native bigint lstat and actual device IDs; separators join numeric fields only and no host path is manually parsed.
359
+ * @evidence contracts/performance.md#efficient-algorithms Each invocation performs native path/lstat work and formats seven bigint fields without reading content.
360
+ * @evidence contracts/performance.md#reuse-equivalent-work The closure reuses one reference map across files in the same proof, while each file's current metadata is read anew.
361
+ * @evidence contracts/performance.md#bound-retention-and-release-resources The closure retains the supplied reference map until its consumer releases it; no file handle or global population is retained.
362
+ */
363
+ function sourceEvidence(references) {
364
+ return (file) => {
365
+ try {
366
+ const stats = node_fs_1.default.lstatSync(file, { bigint: true });
367
+ return {
368
+ separable: separable(references, stats),
369
+ signature: [
370
+ stats.dev,
371
+ stats.ino,
372
+ stats.nlink,
373
+ stats.mode,
374
+ stats.size,
375
+ stats.mtimeNs,
376
+ stats.ctimeNs,
377
+ ].join(":"),
378
+ };
379
+ }
380
+ catch {
381
+ return undefined;
382
+ }
383
+ };
384
+ }
385
+ PluginContentIdentities.sourceEvidence = sourceEvidence;
386
+ /**
387
+ * Record format tag. Move it whenever the record shape or the meaning of a
388
+ * family's digest changes; the ttsc version already separates releases.
389
+ */
390
+ const FORMAT = "ttsc-content-identity-v1";
391
+ /** Directory below the system temporary directory that holds its probes. */
392
+ const TEMPORARY_REFERENCE_DIRNAME = "ttsc-clock-references";
393
+ // The temporary-volume reference lives in one directory reused by every
394
+ // load: creating and removing an entry of the temporary directory itself on
395
+ // each load would move that directory's metadata, which is the signature of
396
+ // every missing path below it a descriptor proof observed (#1721). A shared
397
+ // directory such as POSIX `/tmp` is writable by every user and a fixed name
398
+ // there could be another user's, so the directory is named for this user,
399
+ // created private, and used only while it is a real directory this user owns
400
+ // that nobody else can write to.
401
+ function temporaryReference() {
402
+ try {
403
+ const uid = typeof process.getuid === "function" ? process.getuid() : undefined;
404
+ const directory = node_path_1.default.join(node_os_1.default.tmpdir(), uid === undefined
405
+ ? TEMPORARY_REFERENCE_DIRNAME
406
+ : `${TEMPORARY_REFERENCE_DIRNAME}-${uid}`);
407
+ try {
408
+ node_fs_1.default.mkdirSync(directory, { mode: 0o700 });
409
+ }
410
+ catch (error) {
411
+ if (error.code !== "EEXIST")
412
+ return new Map();
413
+ }
414
+ const stats = node_fs_1.default.lstatSync(directory);
415
+ if (!stats.isDirectory() ||
416
+ (uid !== undefined && (stats.uid !== uid || (stats.mode & 0o022) !== 0)))
417
+ return new Map();
418
+ return mintReference(directory);
419
+ }
420
+ catch {
421
+ return new Map();
422
+ }
423
+ }
424
+ function coversRoot(root, sources) {
425
+ const resolved = node_path_1.default.resolve(root);
426
+ return sources.some((source) => (0, pluginSourceCovers_1.pluginSourceCovers)(node_path_1.default.resolve(source), resolved, "directory"));
427
+ }
428
+ function recordFile(store, kind, subject) {
429
+ const key = node_crypto_1.default
430
+ .createHash("sha256")
431
+ .update(JSON.stringify([FORMAT, store.version, kind, subject]))
432
+ .digest("hex");
433
+ return node_path_1.default.join(store.root, SourceBuildCacheLayout_1.SourceBuildCacheLayout.IDENTITY_CACHE_DIRNAME, `${key}.json`);
434
+ }
435
+ function readRecord(file) {
436
+ try {
437
+ const value = JSON.parse(node_fs_1.default.readFileSync(file, "utf8"));
438
+ return value.format === FORMAT &&
439
+ typeof value.version === "string" &&
440
+ typeof value.kind === "string" &&
441
+ typeof value.subject === "string" &&
442
+ typeof value.signature === "string" &&
443
+ typeof value.digest === "string"
444
+ ? value
445
+ : undefined;
446
+ }
447
+ catch {
448
+ return undefined;
449
+ }
450
+ }
451
+ })(PluginContentIdentities || (exports.PluginContentIdentities = PluginContentIdentities = {}));
452
+ //# sourceMappingURL=PluginContentIdentities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PluginContentIdentities.js","sourceRoot":"","sources":["../../../../src/plugin/internal/source/PluginContentIdentities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { PluginContentIdentities } from "./PluginContentIdentities";
2
+ /**
3
+ * Answers a plugin load computed from inputs it could identify by content, kept
4
+ * in the plugin cache root under that identity so a later process with equal
5
+ * inputs reads the answer instead of computing it again.
6
+ *
7
+ * WARNING (#1721, #1723): the key is the whole proof. A caller must fold into
8
+ * `identity` every input that can change the answer, as content identities
9
+ * (`PluginContentIdentities`) or the authoritative live probe results, never a
10
+ * path, a timestamp or a value it merely expects to be stable. An answer is
11
+ * written only after the computation succeeded on inputs the caller proved
12
+ * unchanged around it; a failed or unproved computation is never recorded,
13
+ * since a later process could not tell it from a current one.
14
+ *
15
+ * Entries are single files published by rename, aged out by the single-file
16
+ * collector and removed by `ttsc clean`. Their identity includes the format tag
17
+ * and the ttsc version, so another release never reads them.
18
+ *
19
+ * @evidence contracts/common.md#principled-implementation The content-addressed key carries every caller-declared input identity; reads accept only a matching format, version and kind, and writes are refused for unproved computations by the caller contract.
20
+ * @evidence contracts/common.md#clear-and-simple-design One owner stores and loads opaque answers; callers own key composition, validation of the answer shape and the decision to record.
21
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts No answer is guessed; a missing, corrupt or foreign entry is a miss and the caller computes.
22
+ * @evidence contracts/common.md#meaningful-documentation Native paragraphs state the key contract that prevents stale answers, the recording rule and the storage lifetime.
23
+ * @evidence contracts/portability.md#os-neutral-implementation Native path joins and same-directory rename publication; keys are hashed text, independent of path dialect.
24
+ * @evidenceExclude contracts/performance.md#efficient-algorithms Members state their own costs.
25
+ * @evidenceExclude contracts/performance.md#reuse-equivalent-work Members define reuse through the caller's identity.
26
+ * @evidenceExclude contracts/performance.md#bound-retention-and-release-resources Members state retention; the namespace holds no state.
27
+ */
28
+ export declare namespace PluginLoadAnswers {
29
+ /**
30
+ * The answer recorded for `identity`, or `undefined` when none is.
31
+ *
32
+ * @param store The opened store, or `undefined` for no persistence.
33
+ * @param kind Answer family; families never share entries.
34
+ * @param identity Every input identity the answer depends on.
35
+ * @evidence contracts/common.md#principled-implementation An entry is returned only for the same format, version, kind and identity hash; the caller validates the value's shape.
36
+ * @evidence contracts/common.md#clear-and-simple-design One lookup returns an opaque value or undefined.
37
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Unreadable or foreign entries are misses.
38
+ * @evidence contracts/common.md#meaningful-documentation Parameters describe the identity contract.
39
+ * @evidence contracts/portability.md#os-neutral-implementation Native path join and file read.
40
+ * @evidence contracts/performance.md#efficient-algorithms Hashes the serialized identity and reads one small file; a hit refreshes its use time.
41
+ * @evidence contracts/performance.md#reuse-equivalent-work Processes share an answer only for an identical serialized identity under the same version.
42
+ * @evidence contracts/performance.md#bound-retention-and-release-resources Nothing is retained in memory; the collector owns entry lifetime.
43
+ */
44
+ function read(store: PluginContentIdentities.Store | undefined, kind: string, identity: unknown): unknown;
45
+ /**
46
+ * Record `value` as the answer for `identity`. Failures are ignored: the
47
+ * answer just computed stands, and the next process computes it again.
48
+ *
49
+ * @param store The opened store, or `undefined` for no persistence.
50
+ * @param kind Answer family.
51
+ * @param identity Every input identity the answer depends on.
52
+ * @param value JSON-serializable answer the caller proved for `identity`.
53
+ * @evidence contracts/common.md#principled-implementation Publication happens only when the caller decided the computation was proven; the entry records the same identity framing that read checks.
54
+ * @evidence contracts/common.md#clear-and-simple-design One atomic publication through the shared metadata writer.
55
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts A failed write never fails the load or fabricates an entry.
56
+ * @evidence contracts/common.md#meaningful-documentation Native prose states failure behavior.
57
+ * @evidence contracts/portability.md#os-neutral-implementation Same-directory staging and rename through the shared writer.
58
+ * @evidence contracts/performance.md#efficient-algorithms Serializes the identity and value once and writes one small file.
59
+ * @evidenceExclude contracts/performance.md#reuse-equivalent-work Publication creates the reusable entry; read owns reuse.
60
+ * @evidence contracts/performance.md#bound-retention-and-release-resources One file per identity, removed by the single-file collector or `ttsc clean`; staging cleanup belongs to the shared writer.
61
+ */
62
+ function write(store: PluginContentIdentities.Store | undefined, kind: string, identity: unknown, value: unknown): void;
63
+ }