ttsc 0.26.2 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/README.md +9 -0
  2. package/cmd/graphbench/main.go +26 -16
  3. package/cmd/graphdump/main.go +37 -12
  4. package/cmd/graphdump/run_declares_the_capability_its_output_carries_test.go +137 -0
  5. package/cmd/graphdump/run_reports_an_unknown_flag_without_exiting_the_process_test.go +56 -0
  6. package/cmd/graphdump/run_reports_an_unloadable_project_without_printing_a_dump_test.go +46 -0
  7. package/cmd/ttsc/api_transform.go +28 -3
  8. package/cmd/ttscgraph/auxiliary_identity_state_tracks_retargets_not_source_contents_test.go +85 -0
  9. package/cmd/ttscgraph/disk_realpath_other.go +16 -0
  10. package/cmd/ttscgraph/disk_realpath_windows.go +56 -0
  11. package/cmd/ttscgraph/dump.go +43 -11
  12. package/cmd/ttscgraph/run_dump_claims_artifacts_only_when_it_asked_test.go +135 -0
  13. package/cmd/ttscgraph/run_dump_declares_the_capability_its_output_carries_test.go +96 -0
  14. package/cmd/ttscgraph/serve.go +357 -60
  15. package/cmd/ttscgraph/serve_adopts_a_republished_artifact_set_test.go +348 -0
  16. package/cmd/ttscgraph/serve_projects_an_artifact_no_source_owns_test.go +90 -0
  17. package/cmd/ttscgraph/serve_shards.go +31 -9
  18. package/driver/config_discovery.go +121 -0
  19. package/driver/emit_plugin.go +77 -11
  20. package/driver/graph.go +64 -11
  21. package/driver/input_observation.go +273 -0
  22. package/driver/input_observation_test.go +149 -0
  23. package/driver/plugins.go +506 -15
  24. package/driver/program.go +54 -1
  25. package/driver/resolution_candidates.go +13 -5
  26. package/driver/rewrite.go +45 -2
  27. package/driver/transform_dependencies.go +283 -0
  28. package/driver/transform_dependencies_declares_every_file_without_a_contributor_test.go +28 -0
  29. package/driver/transform_dependencies_drops_a_self_reported_dependency_test.go +21 -0
  30. package/driver/transform_dependencies_keys_a_reported_path_like_the_envelope_test.go +46 -0
  31. package/driver/transform_dependencies_requires_every_contributor_to_declare_test.go +38 -0
  32. package/driver/transform_dependencies_stays_silent_for_an_undeclared_contributor_test.go +23 -0
  33. package/driver/transform_dependencies_withdraws_completeness_after_an_unusable_dependency_test.go +37 -0
  34. package/internal/graph/artifacts.go +230 -0
  35. package/internal/graph/artifacts_index_what_a_plugin_published_test.go +154 -0
  36. package/internal/graph/artifacts_survive_a_partial_rebuild_test.go +89 -0
  37. package/internal/graph/build.go +35 -0
  38. package/internal/graph/build_releases_the_scratch_it_no_longer_reads_test.go +118 -0
  39. package/internal/graph/doc_refs_are_the_use_the_checker_already_counts_test.go +93 -0
  40. package/internal/graph/doc_refs_resolve_documentation_links_test.go +335 -0
  41. package/internal/graph/doc_tags.go +416 -0
  42. package/internal/graph/doc_tags_are_claimed_before_they_are_read_test.go +131 -0
  43. package/internal/graph/doc_tags_capture_every_unrecognized_tag_test.go +165 -0
  44. package/internal/graph/doc_tags_read_only_what_the_parser_attached_test.go +97 -0
  45. package/internal/graph/doc_tags_stop_at_the_external_boundary_test.go +59 -0
  46. package/internal/graph/doc_tags_survive_line_endings_and_repeated_blocks_test.go +146 -0
  47. package/internal/graph/dump.go +60 -13
  48. package/internal/graph/dump_checkout_paths_are_stable_test.go +2 -2
  49. package/internal/graph/dump_paths.go +2 -2
  50. package/internal/graph/dump_paths_are_portable_and_injective_test.go +1 -1
  51. package/internal/graph/edge_kinds_names_every_declared_kind_test.go +49 -0
  52. package/internal/graph/edges.go +1 -0
  53. package/internal/graph/graph.go +79 -4
  54. package/internal/graph/provenance.go +29 -2
  55. package/lib/TtscCompiler.d.ts +12 -11
  56. package/lib/TtscCompiler.js +44 -29
  57. package/lib/TtscCompiler.js.map +1 -1
  58. package/lib/compiler/internal/captureProcessOutput.js +2 -2
  59. package/lib/compiler/internal/captureProcessOutput.js.map +1 -1
  60. package/lib/compiler/internal/compileProjectInMemory.js +4 -3
  61. package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
  62. package/lib/compiler/internal/project/createNativeProjectContextArgs.d.ts +9 -0
  63. package/lib/compiler/internal/project/createNativeProjectContextArgs.js +16 -4
  64. package/lib/compiler/internal/project/createNativeProjectContextArgs.js.map +1 -1
  65. package/lib/compiler/internal/resolveEmittedJavaScript.d.ts +2 -0
  66. package/lib/compiler/internal/resolveEmittedJavaScript.js +3 -0
  67. package/lib/compiler/internal/resolveEmittedJavaScript.js.map +1 -1
  68. package/lib/compiler/internal/runBuild.d.ts +1 -1
  69. package/lib/compiler/internal/runBuild.js +80 -34
  70. package/lib/compiler/internal/runBuild.js.map +1 -1
  71. package/lib/compiler/internal/runSingleFileEmit.js +2 -2
  72. package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
  73. package/lib/compiler/internal/sharedHostHelpers.d.ts +28 -0
  74. package/lib/compiler/internal/sharedHostHelpers.js +39 -0
  75. package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
  76. package/lib/compiler/internal/startResidentTransform.js +12 -4
  77. package/lib/compiler/internal/startResidentTransform.js.map +1 -1
  78. package/lib/compiler/internal/transformProjectInMemory.d.ts +3 -0
  79. package/lib/compiler/internal/transformProjectInMemory.js +239 -35
  80. package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
  81. package/lib/flags/schema.js +12 -5
  82. package/lib/flags/schema.js.map +1 -1
  83. package/lib/index.d.ts +1 -0
  84. package/lib/index.js +1 -0
  85. package/lib/index.js.map +1 -1
  86. package/lib/internal/createCanonicalTempDirectory.d.ts +17 -0
  87. package/lib/internal/createCanonicalTempDirectory.js +42 -0
  88. package/lib/internal/createCanonicalTempDirectory.js.map +1 -0
  89. package/lib/internal/projectInputPathIdentity.d.ts +3 -0
  90. package/lib/internal/projectInputPathIdentity.js +11 -5
  91. package/lib/internal/projectInputPathIdentity.js.map +1 -1
  92. package/lib/internal/resolveNodeBinary.d.ts +14 -0
  93. package/lib/internal/resolveNodeBinary.js +150 -0
  94. package/lib/internal/resolveNodeBinary.js.map +1 -0
  95. package/lib/internal/resolveSafeCacheCleanupTargets.d.ts +15 -0
  96. package/lib/internal/resolveSafeCacheCleanupTargets.js +61 -0
  97. package/lib/internal/resolveSafeCacheCleanupTargets.js.map +1 -0
  98. package/lib/launcher/internal/prepareExecution.d.ts +3 -0
  99. package/lib/launcher/internal/prepareExecution.js +42 -14
  100. package/lib/launcher/internal/prepareExecution.js.map +1 -1
  101. package/lib/launcher/internal/runTtsc.js +25 -13
  102. package/lib/launcher/internal/runTtsc.js.map +1 -1
  103. package/lib/launcher/internal/runTtscserver.js +18 -3
  104. package/lib/launcher/internal/runTtscserver.js.map +1 -1
  105. package/lib/launcher/internal/runTtsx.js +2 -0
  106. package/lib/launcher/internal/runTtsx.js.map +1 -1
  107. package/lib/launcher/internal/runtimeHooks.d.ts +47 -3
  108. package/lib/launcher/internal/runtimeHooks.js +746 -64
  109. package/lib/launcher/internal/runtimeHooks.js.map +1 -1
  110. package/lib/plugin/internal/buildSourcePlugin.d.ts +62 -8
  111. package/lib/plugin/internal/buildSourcePlugin.js +754 -72
  112. package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
  113. package/lib/plugin/internal/capabilityResolutionCache.d.ts +76 -0
  114. package/lib/plugin/internal/capabilityResolutionCache.js +224 -0
  115. package/lib/plugin/internal/capabilityResolutionCache.js.map +1 -0
  116. package/lib/plugin/internal/loadProjectPlugins.d.ts +17 -5
  117. package/lib/plugin/internal/loadProjectPlugins.js +1339 -77
  118. package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
  119. package/lib/plugin/resolveCapabilityPlugins.d.ts +55 -0
  120. package/lib/plugin/resolveCapabilityPlugins.js +118 -0
  121. package/lib/plugin/resolveCapabilityPlugins.js.map +1 -0
  122. package/lib/register.d.ts +1 -0
  123. package/lib/register.js +46 -0
  124. package/lib/register.js.map +1 -0
  125. package/lib/structures/ITtscCompilerContext.d.ts +6 -3
  126. package/lib/structures/ITtscCompilerTransformation.d.ts +38 -0
  127. package/lib/structures/ITtscPlugin.d.ts +33 -0
  128. package/package.json +16 -9
  129. package/shim/ast/parent.go +16 -3
  130. package/shim/checker/enums_gen.go +11 -0
  131. package/shim/checker/go.mod +9 -0
  132. package/shim/checker/go.sum +22 -0
  133. package/shim/checker/shim.go +78 -0
  134. package/shim/compiler/emithook.go +10 -0
  135. package/shim/compiler/incremental.go +45 -8
  136. package/src/TtscCompiler.ts +55 -33
  137. package/src/compiler/internal/captureProcessOutput.ts +3 -2
  138. package/src/compiler/internal/compileProjectInMemory.ts +4 -3
  139. package/src/compiler/internal/project/createNativeProjectContextArgs.ts +19 -4
  140. package/src/compiler/internal/resolveEmittedJavaScript.ts +6 -0
  141. package/src/compiler/internal/runBuild.ts +102 -39
  142. package/src/compiler/internal/runSingleFileEmit.ts +2 -2
  143. package/src/compiler/internal/sharedHostHelpers.ts +44 -0
  144. package/src/compiler/internal/startResidentTransform.ts +12 -3
  145. package/src/compiler/internal/transformProjectInMemory.ts +410 -39
  146. package/src/flags/schema.ts +12 -5
  147. package/src/index.ts +1 -0
  148. package/src/internal/createCanonicalTempDirectory.ts +53 -0
  149. package/src/internal/projectInputPathIdentity.ts +17 -4
  150. package/src/internal/resolveNodeBinary.ts +173 -0
  151. package/src/internal/resolveSafeCacheCleanupTargets.ts +85 -0
  152. package/src/launcher/internal/prepareExecution.ts +50 -14
  153. package/src/launcher/internal/runTtsc.ts +24 -13
  154. package/src/launcher/internal/runTtscserver.ts +18 -3
  155. package/src/launcher/internal/runTtsx.ts +2 -0
  156. package/src/launcher/internal/runtimeHooks.ts +934 -68
  157. package/src/plugin/internal/buildSourcePlugin.ts +984 -79
  158. package/src/plugin/internal/capabilityResolutionCache.ts +305 -0
  159. package/src/plugin/internal/loadProjectPlugins.ts +1718 -104
  160. package/src/plugin/resolveCapabilityPlugins.ts +171 -0
  161. package/src/register.ts +47 -0
  162. package/src/structures/ITtscCompilerContext.ts +6 -3
  163. package/src/structures/ITtscCompilerTransformation.ts +46 -0
  164. package/src/structures/ITtscPlugin.ts +36 -0
  165. package/tools/shim_audit/baseline.json +0 -2
  166. package/utility/host.go +18 -3
  167. package/lib/internal/assertSafeExplicitCacheDirectory.d.ts +0 -5
  168. package/lib/internal/assertSafeExplicitCacheDirectory.js +0 -26
  169. package/lib/internal/assertSafeExplicitCacheDirectory.js.map +0 -1
  170. package/src/internal/assertSafeExplicitCacheDirectory.ts +0 -29
@@ -3,12 +3,51 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TSGO_ARGS_ENV = void 0;
7
+ exports.clearInheritedTsgoArgs = clearInheritedTsgoArgs;
8
+ exports.inheritedSidecarEnv = inheritedSidecarEnv;
6
9
  exports.resolvePluginConfigDir = resolvePluginConfigDir;
7
10
  exports.isLinkedTransform = isLinkedTransform;
8
11
  exports.assertSharedHostCompatibility = assertSharedHostCompatibility;
9
12
  exports.selectSharedHostPlugin = selectSharedHostPlugin;
10
13
  exports.linkedTransformPlugins = linkedTransformPlugins;
11
14
  const node_path_1 = __importDefault(require("node:path"));
15
+ /**
16
+ * Environment channel carrying the JSON-encoded tsgo argv ttsc forwards to a
17
+ * native sidecar. Mirrors `driver.TsgoArgsEnv` on the Go side; see
18
+ * `runBuild.ts::createNativeTsgoArgs` for why the payload is not a CLI flag.
19
+ */
20
+ exports.TSGO_ARGS_ENV = "TTSC_TSGO_ARGS";
21
+ /**
22
+ * Drop a forwarded-tsgo payload this invocation did not publish itself.
23
+ *
24
+ * Every sidecar env starts from `process.env`, so a ttsc that is itself running
25
+ * inside a plugin sidecar — `@ttsc/lint` evaluating a config file through
26
+ * `ttsx`, for instance — would otherwise hand the outer run's `--strict` to its
27
+ * own sidecars, and `driver.LoadProgram` would apply it. The forwarded argv is
28
+ * per-invocation state the spawning host owns, the same rule
29
+ * `TTSC_PLUGIN_CONFIG_DIR` already follows. A caller that named the variable
30
+ * explicitly keeps it.
31
+ */
32
+ function clearInheritedTsgoArgs(env, callerEnv) {
33
+ if (callerEnv?.[exports.TSGO_ARGS_ENV] === undefined) {
34
+ delete env[exports.TSGO_ARGS_ENV];
35
+ }
36
+ }
37
+ /**
38
+ * The `{ ...process.env, ...callerEnv }` a child process inherits, minus a
39
+ * forwarded-tsgo payload this lane never published.
40
+ *
41
+ * Use it at every spawn whose child can reach `driver.LoadProgram` — the
42
+ * `api-compile` / `api-transform` hosts, and the plugin loader, whose `ttsx`
43
+ * descriptor evaluation compiles a project of its own. One rule at every site
44
+ * beats four sites each reasoning about whether the variable could be present.
45
+ */
46
+ function inheritedSidecarEnv(callerEnv) {
47
+ const env = { ...process.env, ...callerEnv };
48
+ clearInheritedTsgoArgs(env, callerEnv);
49
+ return env;
50
+ }
12
51
  /**
13
52
  * Resolve the caller-declared plugin config anchor to an absolute path, or
14
53
  * `undefined` when the caller did not declare one.
@@ -1 +1 @@
1
- {"version":3,"file":"sharedHostHelpers.js","sourceRoot":"","sources":["../../../src/compiler/internal/sharedHostHelpers.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,0DAA6B;AAI7B;;;;;;;;;;;GAWG;AACH,gCAAuC,OAGtC;IACC,IAAI,OAAO,CAAC,eAAe,KAAK,SAAS,IAAI,OAAO,CAAC,eAAe,KAAK,EAAE,EAAE,CAAC;QAC5E,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;AAC7E,CAAC;AAED;;;GAGG;AACH,2BAAkC,MAA+B;IAC/D,OAAO,MAAM,CAAC,KAAK,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,uCACE,OAA2C,EAC3C,IAAiC;IAEjC,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACtE,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO;IACT,CAAC;IACD,MAAM,aAAa,GAAG;QACpB,GAAG,IAAI,GAAG,CACR,OAAO;aACJ,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;aAC9C,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAClC;KACF,CAAC;IACF,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC9B,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GACV,IAAI,KAAK,MAAM;QACb,CAAC,CAAC,8DAA8D;QAChE,CAAC,CAAC,2EAA2E,CAAC;IAClF,MAAM,IAAI,KAAK,CACb,QAAQ;QACN,MAAM;QACN,iEAAiE,CACpE,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,gCACE,OAA2C;IAE3C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAE,CAAC;AAC7E,CAAC;AAED;;;;GAIG;AACH,gCACE,OAA2C;IAE3C,OAAO,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"sharedHostHelpers.js","sourceRoot":"","sources":["../../../src/compiler/internal/sharedHostHelpers.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,0DAA6B;AAI7B;;;;GAIG;AACU,QAAA,aAAa,GAAG,gBAAgB,CAAC;AAE9C;;;;;;;;;;GAUG;AACH,gCACE,GAAsB,EACtB,SAAwC;IAExC,IAAI,SAAS,EAAE,CAAC,QAAA,aAAa,CAAC,KAAK,SAAS,EAAE,CAAC;QAC7C,OAAO,GAAG,CAAC,QAAA,aAAa,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,6BACE,SAAwC;IAExC,MAAM,GAAG,GAAsB,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IAChE,sBAAsB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACvC,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;GAWG;AACH,gCAAuC,OAGtC;IACC,IAAI,OAAO,CAAC,eAAe,KAAK,SAAS,IAAI,OAAO,CAAC,eAAe,KAAK,EAAE,EAAE,CAAC;QAC5E,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,mBAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;AAC7E,CAAC;AAED;;;GAGG;AACH,2BAAkC,MAA+B;IAC/D,OAAO,MAAM,CAAC,KAAK,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,uCACE,OAA2C,EAC3C,IAAiC;IAEjC,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACtE,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO;IACT,CAAC;IACD,MAAM,aAAa,GAAG;QACpB,GAAG,IAAI,GAAG,CACR,OAAO;aACJ,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;aAC9C,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAClC;KACF,CAAC;IACF,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC9B,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GACV,IAAI,KAAK,MAAM;QACb,CAAC,CAAC,8DAA8D;QAChE,CAAC,CAAC,2EAA2E,CAAC;IAClF,MAAM,IAAI,KAAK,CACb,QAAQ;QACN,MAAM;QACN,iEAAiE,CACpE,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,gCACE,OAA2C;IAE3C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAE,CAAC;AAC7E,CAAC;AAED;;;;GAIG;AACH,gCACE,OAA2C;IAE3C,OAAO,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAC3C,CAAC"}
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.startResidentTransform = startResidentTransform;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
+ const resolveNodeBinary_1 = require("../../internal/resolveNodeBinary");
8
9
  const loadProjectPlugins_1 = require("../../plugin/internal/loadProjectPlugins");
9
10
  const readProjectConfig_1 = require("./project/readProjectConfig");
10
11
  const residentTransformProcess_1 = require("./residentTransformProcess");
@@ -38,7 +39,7 @@ function startResidentTransform(context) {
38
39
  cacheDir: context.cacheDir ?? context.env?.TTSC_CACHE_DIR,
39
40
  cwd,
40
41
  entries: context.plugins,
41
- env: { ...process.env, ...context.env },
42
+ env: (0, sharedHostHelpers_1.inheritedSidecarEnv)(context.env),
42
43
  pluginConfigDir: context.pluginConfigDir,
43
44
  projectRoot: context.projectRoot,
44
45
  tsconfig: project.path,
@@ -60,7 +61,7 @@ function startResidentTransform(context) {
60
61
  ],
61
62
  binary: host.binary,
62
63
  cwd: project.root,
63
- env: residentEnv(context, tsgoBinary, loaded.nativePlugins),
64
+ env: residentEnv(context, project.root, tsgoBinary, loaded.nativePlugins),
64
65
  });
65
66
  return { process: resident, projectRoot: project.root };
66
67
  }
@@ -73,11 +74,10 @@ function startResidentTransform(context) {
73
74
  * wrapper's temp-dir ancestry, and forwards linked transform plugins via
74
75
  * `TTSC_LINKED_PLUGINS_JSON`.
75
76
  */
76
- function residentEnv(context, tsgoBinary, nativePlugins) {
77
+ function residentEnv(context, projectRoot, tsgoBinary, nativePlugins) {
77
78
  const pluginConfigDir = (0, sharedHostHelpers_1.resolvePluginConfigDir)(context);
78
79
  const env = {
79
80
  ...process.env,
80
- TTSC_NODE_BINARY: process.env.TTSC_NODE_BINARY ?? process.execPath,
81
81
  ...(pluginConfigDir === undefined
82
82
  ? {}
83
83
  : { TTSC_PLUGIN_CONFIG_DIR: pluginConfigDir }),
@@ -86,6 +86,11 @@ function residentEnv(context, tsgoBinary, nativePlugins) {
86
86
  node_path_1.default.join(__dirname, "..", "..", "launcher", "ttsx.js"),
87
87
  ...context.env,
88
88
  };
89
+ const node = (0, resolveNodeBinary_1.resolveNodeBinary)(env, projectRoot);
90
+ if (node === undefined)
91
+ delete env.TTSC_NODE_BINARY;
92
+ else
93
+ env.TTSC_NODE_BINARY = node;
89
94
  // The anchor is per-invocation state owned by this host: when this run
90
95
  // declared none (and the caller's env does not name one), drop any value
91
96
  // inherited from an ancestor ttsc process so a nested build never
@@ -94,6 +99,9 @@ function residentEnv(context, tsgoBinary, nativePlugins) {
94
99
  context.env?.TTSC_PLUGIN_CONFIG_DIR === undefined) {
95
100
  delete env.TTSC_PLUGIN_CONFIG_DIR;
96
101
  }
102
+ // This lane forwards no tsgo argv of its own, so anything inherited belongs
103
+ // to an outer ttsc run and must not reach the resident sidecar.
104
+ (0, sharedHostHelpers_1.clearInheritedTsgoArgs)(env, context.env);
97
105
  const linked = (0, sharedHostHelpers_1.linkedTransformPlugins)(nativePlugins);
98
106
  if (linked.length !== 0) {
99
107
  env.TTSC_LINKED_PLUGINS_JSON = serializeNativePlugins(linked);
@@ -1 +1 @@
1
- {"version":3,"file":"startResidentTransform.js","sourceRoot":"","sources":["../../../src/compiler/internal/startResidentTransform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"startResidentTransform.js","sourceRoot":"","sources":["../../../src/compiler/internal/startResidentTransform.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,9 @@ export declare function transformProjectInMemory(options: ITtscCompilerContext):
20
20
  dependencies?: Record<string, string[]>;
21
21
  dependenciesComplete?: string[];
22
22
  graph?: ITtscCompilerTransformation.IReferenceGraph;
23
+ hostInputHashes?: Record<string, string | null>;
24
+ hostInputRealpaths?: Record<string, string | null>;
25
+ hostInputs?: string[];
23
26
  result: TtscBuildResult;
24
27
  typescript: Record<string, string>;
25
28
  volatile?: string[];
@@ -5,11 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.transformProjectInMemory = transformProjectInMemory;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
+ const resolveNodeBinary_1 = require("../../internal/resolveNodeBinary");
8
9
  const loadProjectPlugins_1 = require("../../plugin/internal/loadProjectPlugins");
9
10
  const buildNativeCompiler_1 = require("./buildNativeCompiler");
10
11
  const paths_1 = require("./paths");
11
12
  const createNativeProjectContextArgs_1 = require("./project/createNativeProjectContextArgs");
12
- const readProjectConfig_1 = require("./project/readProjectConfig");
13
13
  const resolveBinary_1 = require("./resolveBinary");
14
14
  const resolveTsgo_1 = require("./resolveTsgo");
15
15
  const runBuild_1 = require("./runBuild");
@@ -32,26 +32,39 @@ const spawnNative_1 = require("./spawnNative");
32
32
  */
33
33
  function transformProjectInMemory(options) {
34
34
  const cwd = node_path_1.default.resolve(options.cwd ?? process.cwd());
35
- const project = (0, readProjectConfig_1.readProjectConfig)({
35
+ const loaded = (0, loadProjectPlugins_1.loadProjectPlugins)({
36
+ binary: (0, resolveBinary_1.resolveBinary)(options) ?? "",
37
+ cacheDir: options.cacheDir ?? options.env?.TTSC_CACHE_DIR,
36
38
  cwd,
39
+ entries: options.plugins,
40
+ env: (0, sharedHostHelpers_1.inheritedSidecarEnv)(options.env),
41
+ pluginConfigDir: options.pluginConfigDir,
37
42
  projectRoot: options.projectRoot,
38
43
  tsconfig: options.tsconfig,
39
44
  });
40
- if (hasConfiguredPlugins(options, project)) {
41
- return transformProjectWithPlugins(options, cwd, project);
45
+ if (loaded.nativePlugins.length !== 0) {
46
+ return transformProjectWithPlugins(options, loaded);
42
47
  }
43
- return transformProjectWithNativeHost(options, project);
44
- }
45
- /** Return true when the project or the call-level options declare any plugins. */
46
- function hasConfiguredPlugins(options, project) {
47
- return (0, loadProjectPlugins_1.hasProjectPluginEntries)(project, options.plugins);
48
+ return transformProjectWithNativeHost(options, loaded.project, loaded);
48
49
  }
49
50
  /**
50
51
  * Transform via the built-in native compiler host (`cmd/ttsc api-transform`).
51
52
  * Used when no user plugins are configured, or as the fallback transformer when
52
53
  * check-stage plugins pass and no transform-stage plugins are declared.
53
54
  */
54
- function transformProjectWithNativeHost(options, project) {
55
+ function transformProjectWithNativeHost(options, project, baseline) {
56
+ // Capture the project inputs before the native host observes them. Pairing a
57
+ // post-build hash with an earlier result can bless a torn generation when a
58
+ // config changes during the child process.
59
+ // Plugin discovery already ran in loadProjectPlugins. The native host only
60
+ // consumes the resolved config chain here, so dependency package manifests
61
+ // must not become per-project universal inputs a second time.
62
+ const projectHostInputs = (0, loadProjectPlugins_1.collectProjectHostInputs)(project, false);
63
+ const projectHostInputHashes = (0, loadProjectPlugins_1.hashHostInputPaths)(projectHostInputs);
64
+ const projectHostInputRealpaths = (0, loadProjectPlugins_1.realpathHostInputPaths)(projectHostInputs);
65
+ const observedHostInputs = mergeHostInputs(baseline?.hostInputs, projectHostInputs);
66
+ const observedHostInputHashes = mergeCompatibleHostInputHashes(baseline?.hostInputHashes ?? {}, projectHostInputHashes, baseline?.hostInputs ?? [], projectHostInputs);
67
+ const observedHostInputRealpaths = mergeCompatibleHostInputHashes(baseline?.hostInputRealpaths ?? {}, projectHostInputRealpaths, baseline?.hostInputs ?? [], projectHostInputs);
55
68
  const binary = (0, buildNativeCompiler_1.buildNativeCompiler)({
56
69
  cacheBaseDir: project.root,
57
70
  cacheDir: options.cacheDir ?? options.env?.TTSC_CACHE_DIR,
@@ -59,14 +72,21 @@ function transformProjectWithNativeHost(options, project) {
59
72
  });
60
73
  const res = (0, spawnNative_1.spawnNative)(binary, ["api-transform", "--cwd", project.root, "--tsconfig", project.path], {
61
74
  cwd: project.root,
62
- env: { ...process.env, ...options.env },
75
+ env: (0, sharedHostHelpers_1.inheritedSidecarEnv)(options.env),
63
76
  });
64
77
  if (res.error) {
65
78
  throw new Error(`ttsc: failed to spawn native compiler host ${binary}: ${res.error.message}`);
66
79
  }
67
80
  const output = parseNativeTransformOutput((0, spawnNative_1.outputText)(res.stdout), (0, spawnNative_1.outputText)(res.stderr));
81
+ const finalObservedHostInputHashes = revalidateHostInputHashes(observedHostInputHashes, observedHostInputs);
82
+ const finalOutputHostInputHashes = revalidateHostInputHashes(output.hostInputHashes ?? {}, output.hostInputs ?? []);
83
+ const finalObservedHostInputRealpaths = revalidateHostInputRealpaths(observedHostInputRealpaths, observedHostInputs);
84
+ const finalOutputHostInputRealpaths = revalidateHostInputRealpaths(output.hostInputRealpaths ?? {}, output.hostInputs ?? []);
68
85
  return {
69
86
  ...envelopeSideChannels(output),
87
+ hostInputHashes: mergeCompatibleHostInputHashes(finalObservedHostInputHashes, finalOutputHostInputHashes, observedHostInputs, output.hostInputs),
88
+ hostInputRealpaths: mergeCompatibleHostInputHashes(finalObservedHostInputRealpaths, finalOutputHostInputRealpaths, observedHostInputs, output.hostInputs),
89
+ hostInputs: mergeHostInputs(observedHostInputs, output.hostInputs),
70
90
  result: {
71
91
  diagnostics: output.diagnostics,
72
92
  status: res.status ?? 1,
@@ -76,17 +96,8 @@ function transformProjectWithNativeHost(options, project) {
76
96
  typescript: output.typescript,
77
97
  };
78
98
  }
79
- function transformProjectWithPlugins(options, cwd, project) {
80
- const loaded = (0, loadProjectPlugins_1.loadProjectPlugins)({
81
- binary: (0, resolveBinary_1.resolveBinary)(options) ?? "",
82
- cacheDir: options.cacheDir ?? options.env?.TTSC_CACHE_DIR,
83
- cwd,
84
- entries: options.plugins,
85
- env: { ...process.env, ...options.env },
86
- pluginConfigDir: options.pluginConfigDir,
87
- projectRoot: options.projectRoot,
88
- tsconfig: project.path,
89
- });
99
+ function transformProjectWithPlugins(options, loaded) {
100
+ const { project } = loaded;
90
101
  const checks = loaded.nativePlugins.filter((plugin) => plugin.stage === "check");
91
102
  const transformers = loaded.nativePlugins.filter((plugin) => plugin.stage === "transform");
92
103
  const tsgoBinary = loaded.nativePlugins.length === 0
@@ -95,14 +106,22 @@ function transformProjectWithPlugins(options, cwd, project) {
95
106
  const checked = runNativeChecks(options, project, tsgoBinary, loaded.nativePlugins, checks);
96
107
  if (checked.status !== 0) {
97
108
  return {
109
+ hostInputHashes: revalidateHostInputHashes(loaded.hostInputHashes, loaded.hostInputs),
110
+ hostInputRealpaths: revalidateHostInputRealpaths(loaded.hostInputRealpaths, loaded.hostInputs),
111
+ hostInputs: loaded.hostInputs,
98
112
  result: checked,
99
113
  typescript: {},
100
114
  };
101
115
  }
102
116
  if (transformers.length === 0) {
103
117
  const transformed = transformProjectWithNativeHost(options, project);
118
+ const finalLoadedHostInputHashes = revalidateHostInputHashes(loaded.hostInputHashes, loaded.hostInputs);
119
+ const finalLoadedHostInputRealpaths = revalidateHostInputRealpaths(loaded.hostInputRealpaths, loaded.hostInputs);
104
120
  return {
105
121
  ...envelopeSideChannels(transformed),
122
+ hostInputHashes: mergeCompatibleHostInputHashes(finalLoadedHostInputHashes, transformed.hostInputHashes, loaded.hostInputs, transformed.hostInputs),
123
+ hostInputRealpaths: mergeCompatibleHostInputHashes(finalLoadedHostInputRealpaths, transformed.hostInputRealpaths, loaded.hostInputs, transformed.hostInputs),
124
+ hostInputs: mergeHostInputs(loaded.hostInputs, transformed.hostInputs),
106
125
  result: (0, runBuild_1.appendBuildOutput)(checked, transformed.result),
107
126
  typescript: transformed.typescript,
108
127
  };
@@ -111,7 +130,7 @@ function transformProjectWithPlugins(options, cwd, project) {
111
130
  const plugin = (0, sharedHostHelpers_1.selectSharedHostPlugin)(transformers);
112
131
  const res = (0, spawnNative_1.spawnNative)(plugin.binary, createNativeTransformArgs(project, transformers, (0, sharedHostHelpers_1.resolvePluginConfigDir)(options)), {
113
132
  cwd: project.root,
114
- env: nativePluginEnv(options, tsgoBinary, loaded.nativePlugins, plugin),
133
+ env: nativePluginEnv(options, project.root, tsgoBinary, loaded.nativePlugins, plugin),
115
134
  });
116
135
  if (res.error) {
117
136
  throw new Error(`ttsc.transform: failed to spawn ${plugin.binary}: ${res.error.message}`);
@@ -123,12 +142,41 @@ function transformProjectWithPlugins(options, cwd, project) {
123
142
  stdout: "",
124
143
  stderr: (0, spawnNative_1.outputText)(res.stderr),
125
144
  };
145
+ const finalLoadedHostInputHashes = revalidateHostInputHashes(loaded.hostInputHashes, loaded.hostInputs);
146
+ const finalOutputHostInputHashes = revalidateHostInputHashes(output.hostInputHashes ?? {}, output.hostInputs ?? []);
147
+ const finalLoadedHostInputRealpaths = revalidateHostInputRealpaths(loaded.hostInputRealpaths, loaded.hostInputs);
148
+ const finalOutputHostInputRealpaths = revalidateHostInputRealpaths(output.hostInputRealpaths ?? {}, output.hostInputs ?? []);
126
149
  return {
127
150
  ...envelopeSideChannels(output),
151
+ hostInputHashes: mergeCompatibleHostInputHashes(finalLoadedHostInputHashes, finalOutputHostInputHashes, loaded.hostInputs, output.hostInputs),
152
+ hostInputRealpaths: mergeCompatibleHostInputHashes(finalLoadedHostInputRealpaths, finalOutputHostInputRealpaths, loaded.hostInputs, output.hostInputs),
153
+ hostInputs: mergeHostInputs(loaded.hostInputs, output.hostInputs),
128
154
  result: (0, runBuild_1.appendBuildOutput)(checked, result),
129
155
  typescript: output.typescript,
130
156
  };
131
157
  }
158
+ /** Keep evaluation proof only when the same input still has the same state. */
159
+ function revalidateHostInputHashes(initial, inputs) {
160
+ const current = (0, loadProjectPlugins_1.hashHostInputPaths)(inputs);
161
+ return Object.fromEntries(inputs.flatMap((input) => {
162
+ const absolute = node_path_1.default.resolve(input);
163
+ return Object.prototype.hasOwnProperty.call(initial, absolute) &&
164
+ initial[absolute] === current[absolute]
165
+ ? [[absolute, current[absolute]]]
166
+ : [];
167
+ }));
168
+ }
169
+ /** Keep evaluation proof only while each lexical path selects the same target. */
170
+ function revalidateHostInputRealpaths(initial, inputs) {
171
+ const current = (0, loadProjectPlugins_1.realpathHostInputPaths)(inputs);
172
+ return Object.fromEntries(inputs.flatMap((input) => {
173
+ const absolute = node_path_1.default.resolve(input);
174
+ return Object.prototype.hasOwnProperty.call(initial, absolute) &&
175
+ initial[absolute] === current[absolute]
176
+ ? [[absolute, current[absolute]]]
177
+ : [];
178
+ }));
179
+ }
132
180
  /**
133
181
  * Collect the optional advisory envelope fields (`dependencies`,
134
182
  * `dependenciesComplete`, `graph`, `volatile`) into a spreadable object,
@@ -147,6 +195,54 @@ function envelopeSideChannels(output) {
147
195
  ...(output.volatile === undefined ? {} : { volatile: output.volatile }),
148
196
  };
149
197
  }
198
+ /** Merge JavaScript- and native-host universal inputs by absolute path. */
199
+ function mergeHostInputs(...groups) {
200
+ return [
201
+ ...new Set(groups.flatMap((group) => (group ?? []).map((file) => node_path_1.default.resolve(file)))),
202
+ ].sort();
203
+ }
204
+ /** Keep only native/descriptor fingerprints that agree on shared paths. */
205
+ function mergeCompatibleHostInputHashes(first, second, firstInputs, secondInputs) {
206
+ const firstDeclared = new Set(firstInputs.map((input) => node_path_1.default.resolve(input)));
207
+ const secondDeclared = new Set((secondInputs ?? []).map((input) => node_path_1.default.resolve(input)));
208
+ const output = Object.fromEntries(Object.entries(first).flatMap(([file, hash]) => {
209
+ const absolute = node_path_1.default.resolve(file);
210
+ return firstDeclared.has(absolute) ? [[absolute, hash]] : [];
211
+ }));
212
+ const unproven = new Set();
213
+ for (const input of firstInputs) {
214
+ const absolute = node_path_1.default.resolve(input);
215
+ if (!Object.prototype.hasOwnProperty.call(first, absolute)) {
216
+ delete output[absolute];
217
+ unproven.add(absolute);
218
+ }
219
+ }
220
+ for (const input of secondInputs ?? []) {
221
+ const absolute = node_path_1.default.resolve(input);
222
+ if (!Object.prototype.hasOwnProperty.call(second ?? {}, absolute)) {
223
+ delete output[absolute];
224
+ unproven.add(absolute);
225
+ }
226
+ }
227
+ for (const [file, hash] of Object.entries(second ?? {})) {
228
+ const absolute = node_path_1.default.resolve(file);
229
+ if (!secondDeclared.has(absolute))
230
+ continue;
231
+ if (unproven.has(absolute))
232
+ continue;
233
+ if (Object.prototype.hasOwnProperty.call(output, absolute) &&
234
+ output[absolute] !== hash) {
235
+ // Two evaluation stages observed different states. Dropping proof makes
236
+ // persistent adapters replace the generation without turning advisory
237
+ // cache metadata into a user-facing compile failure.
238
+ delete output[absolute];
239
+ unproven.add(absolute);
240
+ continue;
241
+ }
242
+ output[absolute] = hash;
243
+ }
244
+ return output;
245
+ }
150
246
  /**
151
247
  * Run every check-stage plugin in sequence, short-circuiting on the first
152
248
  * failure. Returns the aggregated `TtscBuildResult` (status 0 when all pass).
@@ -161,7 +257,7 @@ function runNativeChecks(options, project, tsgoBinary, nativePlugins, checks) {
161
257
  for (const plugin of checks) {
162
258
  const res = (0, spawnNative_1.spawnNative)(plugin.binary, createNativeCheckArgs(project, nativePlugins, plugin, (0, sharedHostHelpers_1.resolvePluginConfigDir)(options)), {
163
259
  cwd: project.root,
164
- env: nativePluginEnv(options, tsgoBinary, nativePlugins, plugin),
260
+ env: nativePluginEnv(options, project.root, tsgoBinary, nativePlugins, plugin),
165
261
  });
166
262
  if (res.error) {
167
263
  throw new Error(`ttsc.transform.check: failed to spawn ${plugin.binary}: ${res.error.message}`);
@@ -223,11 +319,10 @@ function serializeNativePlugins(plugins) {
223
319
  * instead of the wrapper's temp-dir ancestry. For transform plugins, also
224
320
  * passes `TTSC_LINKED_PLUGINS_JSON` when linked sources are present.
225
321
  */
226
- function nativePluginEnv(options, tsgoBinary, nativePlugins, plugin) {
322
+ function nativePluginEnv(options, projectRoot, tsgoBinary, nativePlugins, plugin) {
227
323
  const pluginConfigDir = (0, sharedHostHelpers_1.resolvePluginConfigDir)(options);
228
324
  const env = {
229
325
  ...process.env,
230
- TTSC_NODE_BINARY: process.env.TTSC_NODE_BINARY ?? process.execPath,
231
326
  ...(pluginConfigDir === undefined
232
327
  ? {}
233
328
  : { TTSC_PLUGIN_CONFIG_DIR: pluginConfigDir }),
@@ -236,6 +331,11 @@ function nativePluginEnv(options, tsgoBinary, nativePlugins, plugin) {
236
331
  node_path_1.default.join(__dirname, "..", "..", "launcher", "ttsx.js"),
237
332
  ...options.env,
238
333
  };
334
+ const node = (0, resolveNodeBinary_1.resolveNodeBinary)(env, projectRoot);
335
+ if (node === undefined)
336
+ delete env.TTSC_NODE_BINARY;
337
+ else
338
+ env.TTSC_NODE_BINARY = node;
239
339
  // The anchor is per-invocation state owned by this host: when this run
240
340
  // declared none (and the caller's env does not name one), drop any value
241
341
  // inherited from an ancestor ttsc process so a nested build never
@@ -244,6 +344,9 @@ function nativePluginEnv(options, tsgoBinary, nativePlugins, plugin) {
244
344
  options.env?.TTSC_PLUGIN_CONFIG_DIR === undefined) {
245
345
  delete env.TTSC_PLUGIN_CONFIG_DIR;
246
346
  }
347
+ // This lane forwards no tsgo argv of its own, so anything inherited belongs
348
+ // to an outer ttsc run and must not reach these sidecars.
349
+ (0, sharedHostHelpers_1.clearInheritedTsgoArgs)(env, options.env);
247
350
  if (plugin?.stage === "transform") {
248
351
  const linked = (0, sharedHostHelpers_1.linkedTransformPlugins)(nativePlugins ?? []);
249
352
  if (linked.length !== 0) {
@@ -277,11 +380,17 @@ function parseNativeTransformOutput(stdout, stderr) {
277
380
  const dependencies = parseDependencyLists(parsed.dependencies);
278
381
  const dependenciesComplete = parseFileList(parsed.dependenciesComplete);
279
382
  const graph = parseReferenceGraph(parsed.graph);
383
+ const hostInputHashes = parseHostInputHashes(parsed.hostInputHashes);
384
+ const hostInputRealpaths = parseHostInputRealpaths(parsed.hostInputRealpaths);
385
+ const hostInputs = parseFileList(parsed.hostInputs);
280
386
  const volatile = parseFileList(parsed.volatile);
281
387
  return {
282
388
  ...(dependencies === undefined ? {} : { dependencies }),
283
389
  ...(dependenciesComplete === undefined ? {} : { dependenciesComplete }),
284
390
  ...(graph === undefined ? {} : { graph }),
391
+ ...(hostInputHashes === undefined ? {} : { hostInputHashes }),
392
+ ...(hostInputRealpaths === undefined ? {} : { hostInputRealpaths }),
393
+ ...(hostInputs === undefined ? {} : { hostInputs }),
285
394
  ...(volatile === undefined ? {} : { volatile }),
286
395
  diagnostics: Array.isArray(parsed.diagnostics) ? parsed.diagnostics : [],
287
396
  typescript: parsed.typescript,
@@ -295,6 +404,39 @@ function parseNativeTransformOutput(stdout, stderr) {
295
404
  "ttsc: native transform host returned no output");
296
405
  }
297
406
  }
407
+ /** Parse native evaluation-time SHA-256/null host-input fingerprints. */
408
+ function parseHostInputHashes(value) {
409
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
410
+ return undefined;
411
+ }
412
+ const output = {};
413
+ for (const [file, hash] of Object.entries(value)) {
414
+ if (!node_path_1.default.isAbsolute(file) ||
415
+ (hash !== null &&
416
+ (typeof hash !== "string" || !/^[0-9a-f]{64}$/.test(hash)))) {
417
+ continue;
418
+ }
419
+ output[node_path_1.default.resolve(file)] = hash;
420
+ }
421
+ return Object.keys(output).length === 0 ? undefined : output;
422
+ }
423
+ /** Parse native evaluation-time realpath/null host-input identities. */
424
+ function parseHostInputRealpaths(value) {
425
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
426
+ return undefined;
427
+ }
428
+ const output = {};
429
+ for (const [file, realpath] of Object.entries(value)) {
430
+ if (!node_path_1.default.isAbsolute(file) ||
431
+ (realpath !== null &&
432
+ (typeof realpath !== "string" || !node_path_1.default.isAbsolute(realpath)))) {
433
+ continue;
434
+ }
435
+ output[node_path_1.default.resolve(file)] =
436
+ realpath === null ? null : node_path_1.default.resolve(realpath);
437
+ }
438
+ return Object.keys(output).length === 0 ? undefined : output;
439
+ }
298
440
  /**
299
441
  * Normalize the optional `dependencies` envelope field into a record of string
300
442
  * arrays, or `undefined` when absent or carrying nothing usable.
@@ -315,11 +457,34 @@ function parseDependencyLists(value) {
315
457
  }
316
458
  return Object.keys(output).length === 0 ? undefined : output;
317
459
  }
460
+ /**
461
+ * Normalize graph adjacency while retaining every well-formed node key.
462
+ *
463
+ * A leaf is intentionally encoded as an empty target array. Its key still
464
+ * declares graph membership and lets persistent hosts bind the compiler-time
465
+ * input proof for that source. A node needs a non-empty source key and an array
466
+ * value; invalid array members are filtered without erasing a valid node.
467
+ */
468
+ function parseGraphEdges(value) {
469
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
470
+ return undefined;
471
+ }
472
+ const output = {};
473
+ for (const [key, entries] of Object.entries(value)) {
474
+ if (key.length === 0 || !Array.isArray(entries)) {
475
+ continue;
476
+ }
477
+ output[key] = entries.filter((entry) => typeof entry === "string");
478
+ }
479
+ return Object.keys(output).length === 0 ? undefined : output;
480
+ }
318
481
  /**
319
482
  * Normalize the optional `graph` envelope section with the same tolerance as
320
- * `dependencies`: non-object sections are dropped, edge entries that are not
321
- * string arrays are dropped, and non-string list members are filtered. A
322
- * section carrying nothing usable collapses to `undefined`.
483
+ * `dependencies`: non-object sections are dropped, empty source keys and edge
484
+ * entries that are not arrays are dropped, and non-string list members are
485
+ * filtered. Empty arrays remain as graph nodes because leaf membership binds
486
+ * compiler input proof. A section carrying nothing usable collapses to
487
+ * `undefined`.
323
488
  *
324
489
  * `candidates` is the one optional member, so an empty one is left off the
325
490
  * result instead of being materialized as `{}`. The host omits the key when it
@@ -333,23 +498,62 @@ function parseReferenceGraph(value) {
333
498
  }
334
499
  const section = value;
335
500
  const candidates = parseDependencyLists(section.candidates) ?? {};
336
- const edges = parseDependencyLists(section.edges) ?? {};
501
+ const edges = parseGraphEdges(section.edges) ?? {};
337
502
  const globals = parseFileList(section.globals) ?? [];
338
503
  const configs = parseFileList(section.configs) ?? [];
504
+ const inputHashes = parseGraphInputHashes(section.inputHashes);
505
+ const inputRealpaths = parseGraphInputRealpaths(section.inputRealpaths);
339
506
  if (Object.keys(candidates).length === 0 &&
340
507
  Object.keys(edges).length === 0 &&
341
508
  globals.length === 0 &&
342
509
  configs.length === 0) {
343
510
  return undefined;
344
511
  }
345
- return Object.keys(candidates).length === 0
346
- ? { configs, edges, globals }
347
- : { candidates, configs, edges, globals };
512
+ return {
513
+ ...(Object.keys(candidates).length === 0 ? {} : { candidates }),
514
+ configs,
515
+ edges,
516
+ globals,
517
+ ...(inputHashes === undefined ? {} : { inputHashes }),
518
+ ...(inputRealpaths === undefined ? {} : { inputRealpaths }),
519
+ };
520
+ }
521
+ /** Parse graph-keyed compiler-time content/null observations. */
522
+ function parseGraphInputHashes(value) {
523
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
524
+ return undefined;
525
+ }
526
+ const output = {};
527
+ for (const [file, hash] of Object.entries(value)) {
528
+ if (file.length === 0 ||
529
+ (hash !== null &&
530
+ (typeof hash !== "string" || !/^[0-9a-f]{64}$/.test(hash)))) {
531
+ continue;
532
+ }
533
+ output[file] = hash;
534
+ }
535
+ return Object.keys(output).length === 0 ? undefined : output;
536
+ }
537
+ /** Parse graph-keyed compiler-time physical/null identities. */
538
+ function parseGraphInputRealpaths(value) {
539
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
540
+ return undefined;
541
+ }
542
+ const output = {};
543
+ for (const [file, realpath] of Object.entries(value)) {
544
+ if (file.length === 0 ||
545
+ (realpath !== null &&
546
+ (typeof realpath !== "string" || !node_path_1.default.isAbsolute(realpath)))) {
547
+ continue;
548
+ }
549
+ output[file] = realpath === null ? null : node_path_1.default.resolve(realpath);
550
+ }
551
+ return Object.keys(output).length === 0 ? undefined : output;
348
552
  }
349
553
  /**
350
554
  * Normalize an optional string-list envelope field (`dependenciesComplete`,
351
- * `volatile`, and the `globals`/`configs` graph sections), or `undefined` when
352
- * absent or carrying nothing usable.
555
+ * `hostInputs`, `volatile`, and the `globals`/`configs` graph sections), or
556
+ * `undefined` when absent or carrying nothing usable.
353
557
  */
354
558
  function parseFileList(value) {
355
559
  if (!Array.isArray(value)) {