@flyingrobots/graft 0.11.0 → 0.12.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 (209) hide show
  1. package/CHANGELOG.md +198 -0
  2. package/README.md +7 -0
  3. package/dist/adapters/node-fs.d.ts.map +1 -1
  4. package/dist/adapters/node-fs.js +6 -0
  5. package/dist/adapters/node-fs.js.map +1 -1
  6. package/dist/api/index.d.ts +2 -2
  7. package/dist/api/index.d.ts.map +1 -1
  8. package/dist/api/index.js +2 -2
  9. package/dist/api/index.js.map +1 -1
  10. package/dist/api/repo-workspace.d.ts.map +1 -1
  11. package/dist/api/repo-workspace.js +3 -0
  12. package/dist/api/repo-workspace.js.map +1 -1
  13. package/dist/cli/cli-error.d.ts.map +1 -1
  14. package/dist/cli/cli-error.js +4 -1
  15. package/dist/cli/cli-error.js.map +1 -1
  16. package/dist/cli/command-parser.d.ts.map +1 -1
  17. package/dist/cli/command-parser.js +5 -0
  18. package/dist/cli/command-parser.js.map +1 -1
  19. package/dist/cli/structural-review-render.d.ts.map +1 -1
  20. package/dist/cli/structural-review-render.js +5 -0
  21. package/dist/cli/structural-review-render.js.map +1 -1
  22. package/dist/contracts/capabilities.d.ts +5 -5
  23. package/dist/contracts/capabilities.d.ts.map +1 -1
  24. package/dist/contracts/capabilities.js +10 -0
  25. package/dist/contracts/capabilities.js.map +1 -1
  26. package/dist/contracts/output-schema-cli.d.ts +56 -0
  27. package/dist/contracts/output-schema-cli.d.ts.map +1 -1
  28. package/dist/contracts/output-schema-cli.js +1 -0
  29. package/dist/contracts/output-schema-cli.js.map +1 -1
  30. package/dist/contracts/output-schema-mcp.d.ts +79 -1
  31. package/dist/contracts/output-schema-mcp.d.ts.map +1 -1
  32. package/dist/contracts/output-schema-mcp.js +27 -0
  33. package/dist/contracts/output-schema-mcp.js.map +1 -1
  34. package/dist/contracts/output-schema-meta.d.ts +7 -4
  35. package/dist/contracts/output-schema-meta.d.ts.map +1 -1
  36. package/dist/contracts/output-schema-meta.js +8 -2
  37. package/dist/contracts/output-schema-meta.js.map +1 -1
  38. package/dist/contracts/output-schemas.d.ts +3 -5
  39. package/dist/contracts/output-schemas.d.ts.map +1 -1
  40. package/dist/contracts/output-schemas.js +9 -34
  41. package/dist/contracts/output-schemas.js.map +1 -1
  42. package/dist/echo/structural-reading-adapter.d.ts.map +1 -1
  43. package/dist/echo/structural-reading-adapter.js +42 -0
  44. package/dist/echo/structural-reading-adapter.js.map +1 -1
  45. package/dist/echo/structural-reading-generated-model.d.ts.map +1 -1
  46. package/dist/echo/structural-reading-generated-model.js +7 -3
  47. package/dist/echo/structural-reading-generated-model.js.map +1 -1
  48. package/dist/mcp/burden.d.ts.map +1 -1
  49. package/dist/mcp/burden.js +1 -0
  50. package/dist/mcp/burden.js.map +1 -1
  51. package/dist/mcp/repo-workspace.d.ts.map +1 -1
  52. package/dist/mcp/repo-workspace.js +5 -1
  53. package/dist/mcp/repo-workspace.js.map +1 -1
  54. package/dist/mcp/server-invocation.d.ts.map +1 -1
  55. package/dist/mcp/server-invocation.js +46 -11
  56. package/dist/mcp/server-invocation.js.map +1 -1
  57. package/dist/mcp/server-tool-access.d.ts +2 -0
  58. package/dist/mcp/server-tool-access.d.ts.map +1 -1
  59. package/dist/mcp/server-tool-access.js +5 -0
  60. package/dist/mcp/server-tool-access.js.map +1 -1
  61. package/dist/mcp/tool-registry.d.ts.map +1 -1
  62. package/dist/mcp/tool-registry.js +2 -0
  63. package/dist/mcp/tool-registry.js.map +1 -1
  64. package/dist/mcp/tools/changed-since.d.ts.map +1 -1
  65. package/dist/mcp/tools/changed-since.js +8 -63
  66. package/dist/mcp/tools/changed-since.js.map +1 -1
  67. package/dist/mcp/tools/code-find.d.ts.map +1 -1
  68. package/dist/mcp/tools/code-find.js +1 -0
  69. package/dist/mcp/tools/code-find.js.map +1 -1
  70. package/dist/mcp/tools/code-refs.d.ts.map +1 -1
  71. package/dist/mcp/tools/code-refs.js +1 -0
  72. package/dist/mcp/tools/code-refs.js.map +1 -1
  73. package/dist/mcp/tools/code-show.d.ts.map +1 -1
  74. package/dist/mcp/tools/code-show.js +17 -10
  75. package/dist/mcp/tools/code-show.js.map +1 -1
  76. package/dist/mcp/tools/file-outline.d.ts.map +1 -1
  77. package/dist/mcp/tools/file-outline.js +18 -39
  78. package/dist/mcp/tools/file-outline.js.map +1 -1
  79. package/dist/mcp/tools/graft-diff.js +1 -1
  80. package/dist/mcp/tools/graft-diff.js.map +1 -1
  81. package/dist/mcp/tools/import-diagnostics.d.ts +3 -0
  82. package/dist/mcp/tools/import-diagnostics.d.ts.map +1 -0
  83. package/dist/mcp/tools/import-diagnostics.js +25 -0
  84. package/dist/mcp/tools/import-diagnostics.js.map +1 -0
  85. package/dist/mcp/tools/map.d.ts.map +1 -1
  86. package/dist/mcp/tools/map.js +1 -0
  87. package/dist/mcp/tools/map.js.map +1 -1
  88. package/dist/mcp/tools/precision-live.d.ts +8 -0
  89. package/dist/mcp/tools/precision-live.d.ts.map +1 -1
  90. package/dist/mcp/tools/precision-live.js +16 -3
  91. package/dist/mcp/tools/precision-live.js.map +1 -1
  92. package/dist/mcp/tools/precision.d.ts +1 -1
  93. package/dist/mcp/tools/precision.d.ts.map +1 -1
  94. package/dist/mcp/tools/precision.js +1 -1
  95. package/dist/mcp/tools/precision.js.map +1 -1
  96. package/dist/mcp/tools/read-range.d.ts.map +1 -1
  97. package/dist/mcp/tools/read-range.js +23 -8
  98. package/dist/mcp/tools/read-range.js.map +1 -1
  99. package/dist/mcp/tools/safe-read.js +1 -1
  100. package/dist/mcp/tools/safe-read.js.map +1 -1
  101. package/dist/mcp/tools/since.d.ts.map +1 -1
  102. package/dist/mcp/tools/since.js +1 -0
  103. package/dist/mcp/tools/since.js.map +1 -1
  104. package/dist/mcp/tools/structural-review.d.ts.map +1 -1
  105. package/dist/mcp/tools/structural-review.js +16 -13
  106. package/dist/mcp/tools/structural-review.js.map +1 -1
  107. package/dist/mcp/workspace-read-observation-model.d.ts +1 -0
  108. package/dist/mcp/workspace-read-observation-model.d.ts.map +1 -1
  109. package/dist/mcp/workspace-read-observation-model.js +1 -0
  110. package/dist/mcp/workspace-read-observation-model.js.map +1 -1
  111. package/dist/mcp/workspace-read-observation.d.ts.map +1 -1
  112. package/dist/mcp/workspace-read-observation.js +3 -1
  113. package/dist/mcp/workspace-read-observation.js.map +1 -1
  114. package/dist/mcp/workspace-router-model.d.ts +4 -0
  115. package/dist/mcp/workspace-router-model.d.ts.map +1 -1
  116. package/dist/mcp/workspace-router-model.js +7 -0
  117. package/dist/mcp/workspace-router-model.js.map +1 -1
  118. package/dist/mcp/workspace-router.d.ts +8 -1
  119. package/dist/mcp/workspace-router.d.ts.map +1 -1
  120. package/dist/mcp/workspace-router.js +81 -2
  121. package/dist/mcp/workspace-router.js.map +1 -1
  122. package/dist/operations/file-outline.d.ts +13 -4
  123. package/dist/operations/file-outline.d.ts.map +1 -1
  124. package/dist/operations/file-outline.js +12 -7
  125. package/dist/operations/file-outline.js.map +1 -1
  126. package/dist/operations/read-range.d.ts +9 -4
  127. package/dist/operations/read-range.d.ts.map +1 -1
  128. package/dist/operations/read-range.js +12 -7
  129. package/dist/operations/read-range.js.map +1 -1
  130. package/dist/operations/repo-workspace.d.ts +53 -3
  131. package/dist/operations/repo-workspace.d.ts.map +1 -1
  132. package/dist/operations/repo-workspace.js +125 -65
  133. package/dist/operations/repo-workspace.js.map +1 -1
  134. package/dist/operations/safe-read.d.ts +8 -5
  135. package/dist/operations/safe-read.d.ts.map +1 -1
  136. package/dist/operations/safe-read.js +34 -26
  137. package/dist/operations/safe-read.js.map +1 -1
  138. package/dist/operations/structural-review.d.ts +7 -1
  139. package/dist/operations/structural-review.d.ts.map +1 -1
  140. package/dist/operations/structural-review.js +13 -2
  141. package/dist/operations/structural-review.js.map +1 -1
  142. package/dist/operations/workspace-read-view.d.ts +208 -0
  143. package/dist/operations/workspace-read-view.d.ts.map +1 -0
  144. package/dist/operations/workspace-read-view.js +302 -0
  145. package/dist/operations/workspace-read-view.js.map +1 -0
  146. package/dist/ports/filesystem.d.ts +2 -0
  147. package/dist/ports/filesystem.d.ts.map +1 -1
  148. package/dist/ports/structural-reading.d.ts +21 -1
  149. package/dist/ports/structural-reading.d.ts.map +1 -1
  150. package/dist/ports/structural-reading.js.map +1 -1
  151. package/dist/warp/ast-emitter.d.ts +4 -0
  152. package/dist/warp/ast-emitter.d.ts.map +1 -1
  153. package/dist/warp/ast-emitter.js +16 -10
  154. package/dist/warp/ast-emitter.js.map +1 -1
  155. package/dist/warp/ast-import-resolver.d.ts +7 -0
  156. package/dist/warp/ast-import-resolver.d.ts.map +1 -1
  157. package/dist/warp/ast-import-resolver.js +41 -20
  158. package/dist/warp/ast-import-resolver.js.map +1 -1
  159. package/dist/warp/committed-reference-scan.d.ts +38 -0
  160. package/dist/warp/committed-reference-scan.d.ts.map +1 -0
  161. package/dist/warp/committed-reference-scan.js +346 -0
  162. package/dist/warp/committed-reference-scan.js.map +1 -0
  163. package/dist/warp/go-reference-context.d.ts +8 -0
  164. package/dist/warp/go-reference-context.d.ts.map +1 -0
  165. package/dist/warp/go-reference-context.js +209 -0
  166. package/dist/warp/go-reference-context.js.map +1 -0
  167. package/dist/warp/import-diagnostic.d.ts +17 -0
  168. package/dist/warp/import-diagnostic.d.ts.map +1 -0
  169. package/dist/warp/import-diagnostic.js +2 -0
  170. package/dist/warp/import-diagnostic.js.map +1 -0
  171. package/dist/warp/index-head.d.ts.map +1 -1
  172. package/dist/warp/index-head.js +34 -8
  173. package/dist/warp/index-head.js.map +1 -1
  174. package/dist/warp/python-import-resolver.d.ts +10 -0
  175. package/dist/warp/python-import-resolver.d.ts.map +1 -0
  176. package/dist/warp/python-import-resolver.js +100 -0
  177. package/dist/warp/python-import-resolver.js.map +1 -0
  178. package/dist/warp/qualified-reference-bindings.d.ts +11 -0
  179. package/dist/warp/qualified-reference-bindings.d.ts.map +1 -0
  180. package/dist/warp/qualified-reference-bindings.js +483 -0
  181. package/dist/warp/qualified-reference-bindings.js.map +1 -0
  182. package/dist/warp/qualified-reference-contract.d.ts +76 -0
  183. package/dist/warp/qualified-reference-contract.d.ts.map +1 -0
  184. package/dist/warp/qualified-reference-contract.js +2 -0
  185. package/dist/warp/qualified-reference-contract.js.map +1 -0
  186. package/dist/warp/qualified-reference-language-adapters.d.ts +4 -0
  187. package/dist/warp/qualified-reference-language-adapters.d.ts.map +1 -0
  188. package/dist/warp/qualified-reference-language-adapters.js +148 -0
  189. package/dist/warp/qualified-reference-language-adapters.js.map +1 -0
  190. package/dist/warp/qualified-reference-resolver.d.ts +10 -0
  191. package/dist/warp/qualified-reference-resolver.d.ts.map +1 -0
  192. package/dist/warp/qualified-reference-resolver.js +222 -0
  193. package/dist/warp/qualified-reference-resolver.js.map +1 -0
  194. package/dist/warp/qualified-reference-shadows.d.ts +5 -0
  195. package/dist/warp/qualified-reference-shadows.d.ts.map +1 -0
  196. package/dist/warp/qualified-reference-shadows.js +601 -0
  197. package/dist/warp/qualified-reference-shadows.js.map +1 -0
  198. package/dist/warp/structural-reading-adapter.d.ts +2 -1
  199. package/dist/warp/structural-reading-adapter.d.ts.map +1 -1
  200. package/dist/warp/structural-reading-adapter.js +79 -27
  201. package/dist/warp/structural-reading-adapter.js.map +1 -1
  202. package/docs/CLI.md +10 -1
  203. package/docs/MCP.md +9 -1
  204. package/docs/SETUP.md +7 -0
  205. package/package.json +9 -7
  206. package/dist/operations/import-reference-impact.d.ts +0 -13
  207. package/dist/operations/import-reference-impact.d.ts.map +0 -1
  208. package/dist/operations/import-reference-impact.js +0 -101
  209. package/dist/operations/import-reference-impact.js.map +0 -1
@@ -1,10 +1,14 @@
1
1
  import type { FileSystem } from "../ports/filesystem.js";
2
2
  import type { GitClient } from "../ports/git.js";
3
+ import type { StructuralReferenceWarning } from "../ports/structural-reading.js";
3
4
  export interface ReferenceCountResult {
4
5
  readonly referenceCount: number;
5
6
  readonly referencingFiles: readonly string[];
7
+ readonly warnings?: readonly ReferenceWarning[];
8
+ readonly confidence?: "complete" | "partial";
6
9
  }
7
- export type ReferenceCounter = (symbolName: string, filePath: string) => Promise<ReferenceCountResult>;
10
+ export type ReferenceWarning = StructuralReferenceWarning;
11
+ export type ReferenceCounter = (symbolName: string, filePath: string, candidateTargetFilePaths: readonly string[]) => Promise<ReferenceCountResult>;
8
12
  export type ReviewCategory = "structural" | "formatting" | "test" | "docs" | "config";
9
13
  export interface ReviewFile {
10
14
  readonly path: string;
@@ -24,6 +28,8 @@ export interface BreakingChange {
24
28
  readonly newSignature?: string;
25
29
  readonly impactedFiles: number;
26
30
  readonly impactedFilePaths: readonly string[];
31
+ readonly referenceWarnings: readonly ReferenceWarning[];
32
+ readonly referenceConfidence: "complete" | "partial";
27
33
  }
28
34
  export interface StructuralReviewResult {
29
35
  readonly base: string;
@@ -1 +1 @@
1
- {"version":3,"file":"structural-review.d.ts","sourceRoot":"","sources":["../../src/operations/structural-review.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAMjD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAGnC,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEtF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,iBAAiB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAClF;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,gBAAgB,GAAG,mBAAmB,GAAG,cAAc,CAAC;IAC7E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,QAAQ,CAAC,eAAe,EAAE,SAAS,cAAc,EAAE,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,sBAAsB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,eAAe,EAAE,gBAAgB,CAAC;CAC5C;AAmKD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,sBAAsB,CAAC,CA4FjC"}
1
+ {"version":3,"file":"structural-review.d.ts","sourceRoot":"","sources":["../../src/operations/structural-review.ts"],"names":[],"mappings":"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"}
@@ -50,12 +50,13 @@ function isConfigFile(filePath) {
50
50
  // ---- Breaking change detection --------------------------------------------
51
51
  async function detectBreakingChanges(structuralFiles, countReferences) {
52
52
  const breaking = [];
53
+ const candidateTargetFilePaths = structuralFiles.map((file) => file.path);
53
54
  for (const file of structuralFiles) {
54
55
  // Removed exports → breaking
55
56
  for (const removed of file.diff.removed) {
56
57
  if (removed.exported !== true)
57
58
  continue;
58
- const refs = await countReferences(removed.name, file.path);
59
+ const refs = await countReferences(removed.name, file.path, candidateTargetFilePaths);
59
60
  breaking.push({
60
61
  symbol: removed.name,
61
62
  kind: removed.kind,
@@ -64,6 +65,8 @@ async function detectBreakingChanges(structuralFiles, countReferences) {
64
65
  ...(removed.signature !== undefined ? { previousSignature: removed.signature } : {}),
65
66
  impactedFiles: refs.referenceCount,
66
67
  impactedFilePaths: refs.referencingFiles,
68
+ referenceWarnings: refs.warnings ?? [],
69
+ referenceConfidence: refs.confidence ?? "complete",
67
70
  });
68
71
  }
69
72
  // Changed exported symbol signatures → potentially breaking
@@ -72,7 +75,7 @@ async function detectBreakingChanges(structuralFiles, countReferences) {
72
75
  continue;
73
76
  if (changed.oldSignature !== undefined && changed.signature !== undefined &&
74
77
  changed.oldSignature !== changed.signature) {
75
- const refs = await countReferences(changed.name, file.path);
78
+ const refs = await countReferences(changed.name, file.path, candidateTargetFilePaths);
76
79
  breaking.push({
77
80
  symbol: changed.name,
78
81
  kind: changed.kind,
@@ -82,6 +85,8 @@ async function detectBreakingChanges(structuralFiles, countReferences) {
82
85
  newSignature: changed.signature,
83
86
  impactedFiles: refs.referenceCount,
84
87
  impactedFilePaths: refs.referencingFiles,
88
+ referenceWarnings: refs.warnings ?? [],
89
+ referenceConfidence: refs.confidence ?? "complete",
85
90
  });
86
91
  }
87
92
  }
@@ -139,6 +144,12 @@ function renderSummary(base, head, categories, breakingChanges, totalFiles, stru
139
144
  }
140
145
  }
141
146
  parts.push(` Impact: referenced by ${String(bc.impactedFiles)} files`);
147
+ if (bc.referenceConfidence === "partial") {
148
+ const reason = bc.referenceWarnings.length === 0
149
+ ? "unresolved or unsupported reference analysis may hide callers"
150
+ : `${String(bc.referenceWarnings.length)} excluded shadowed access${bc.referenceWarnings.length === 1 ? "" : "es"}`;
151
+ parts.push(` Confidence: partial (${reason})`);
152
+ }
142
153
  }
143
154
  return parts.join("\n");
144
155
  }
@@ -1 +1 @@
1
- {"version":3,"file":"structural-review.js","sourceRoot":"","sources":["../../src/operations/structural-review.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6EAA6E;AAC7E,8EAA8E;AAI9E,OAAO,EAAE,SAAS,EAAwC,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAsD3D,8EAA8E;AAE9E,MAAM,eAAe,GAAG;IACtB,cAAc;IACd,UAAU;IACV,QAAQ;IACR,aAAa;IACb,eAAe;IACf,eAAe;IACf,aAAa;IACb,eAAe;IACf,aAAa;IACb,gBAAgB;IAChB,cAAc;IACd,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,YAAY;IACZ,gBAAgB;IAChB,gBAAgB;IAChB,qBAAqB;IACrB,WAAW;IACX,mBAAmB;IACnB,UAAU;IACV,YAAY;IACZ,gBAAgB;CACjB,CAAC;AAEF,MAAM,aAAa,GAAG;IACpB,QAAQ;IACR,SAAS;IACT,aAAa;IACb,QAAQ;IACR,QAAQ;IACR,QAAQ;CACT,CAAC;AAEF,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,8EAA8E;AAE9E,KAAK,UAAU,qBAAqB,CAClC,eAAoC,EACpC,eAAiC;IAEjC,MAAM,QAAQ,GAAqB,EAAE,CAAC;IAEtC,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,6BAA6B;QAC7B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI;gBAAE,SAAS;YACxC,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,OAAO,CAAC,IAAI;gBACpB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,UAAU,EAAE,gBAAgB;gBAC5B,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpF,aAAa,EAAE,IAAI,CAAC,cAAc;gBAClC,iBAAiB,EAAE,IAAI,CAAC,gBAAgB;aACzC,CAAC,CAAC;QACL,CAAC;QAED,4DAA4D;QAC5D,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI;gBAAE,SAAS;YACxC,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS;gBACrE,OAAO,CAAC,YAAY,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;gBAC/C,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5D,QAAQ,CAAC,IAAI,CAAC;oBACZ,MAAM,EAAE,OAAO,CAAC,IAAI;oBACpB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,QAAQ,EAAE,IAAI,CAAC,IAAI;oBACnB,UAAU,EAAE,mBAAmB;oBAC/B,iBAAiB,EAAE,OAAO,CAAC,YAAY;oBACvC,YAAY,EAAE,OAAO,CAAC,SAAS;oBAC/B,aAAa,EAAE,IAAI,CAAC,cAAc;oBAClC,iBAAiB,EAAE,IAAI,CAAC,gBAAgB;iBACzC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,8EAA8E;AAE9E,SAAS,aAAa,CACpB,IAAY,EACZ,IAAY,EACZ,UAA0C,EAC1C,eAA0C,EAC1C,UAAkB,EAClB,eAAoC;IAEpC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,KAAK,IAAI,MAAM,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAChF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,qBAAqB;IACrB,IAAI,UAAU,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAChF,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACpF,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACpF,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,UAAU,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QACtE,IAAI,YAAY,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QAC1E,IAAI,YAAY,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC7D,CAAC;IAED,mBAAmB;IACnB,KAAK,MAAM,EAAE,IAAI,eAAe,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,EAAE,CAAC,UAAU,KAAK,gBAAgB,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,MAAM,mBAAmB,CAAC,CAAC;YAC1D,IAAI,EAAE,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;gBACvC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,MAAM,sBAAsB,CAAC,CAAC;YAC7D,IAAI,EAAE,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;gBACvC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;YACjD,CAAC;YACD,IAAI,EAAE,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBAClC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,6BAA6B,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAA6B;IAE7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC;IAEjC,yBAAyB;IACzB,MAAM,QAAQ,GAAqB;QACjC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;QACnD,IAAI;QACJ,IAAI;KACL,CAAC;IACF,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IAE7C,iDAAiD;IACjD,MAAM,iBAAiB,GAAG,MAAM,yBAAyB,CAAC;QACxD,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,IAAI;QACJ,IAAI;KACL,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE7D,kDAAkD;IAClD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAErE,kCAAkC;IAClC,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;QACvC,iEAAiE;QACjE,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC5C,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;YACnD,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,CAAC;QAC5B,MAAM,oBAAoB,GAAG,IAAI,KAAK,SAAS;YAC7C,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEhF,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrD,CAAC;aAAM,IAAI,oBAAoB,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,YAAY;gBACtB,iBAAiB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;aAC5G,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,MAAM,UAAU,GAAmC;QACjD,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,CAAC;QACb,IAAI,EAAE,CAAC;QACP,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,CAAC;KACV,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC9B,CAAC;IAED,iDAAiD;IACjD,MAAM,mBAAmB,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACxD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CACvD,CAAC;IACF,MAAM,eAAe,GAAG,MAAM,qBAAqB,CAAC,mBAAmB,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IAE/F,oBAAoB;IACpB,MAAM,OAAO,GAAG,aAAa,CAC3B,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,eAAe,EACf,eAAe,CAAC,MAAM,EACtB,UAAU,CAAC,KAAK,CACjB,CAAC;IAEF,OAAO;QACL,IAAI;QACJ,IAAI;QACJ,UAAU,EAAE,eAAe,CAAC,MAAM;QAClC,UAAU;QACV,KAAK;QACL,eAAe;QACf,OAAO;KACR,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"structural-review.js","sourceRoot":"","sources":["../../src/operations/structural-review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,208 @@
1
+ import type { FileSystem } from "../ports/filesystem.js";
2
+ /**
3
+ * The bytes Graft analysis is permitted to see, and nothing else.
4
+ *
5
+ * Analysis previously received a general `FileSystem` and reached through it to
6
+ * the live disk, so "read the workspace" and "read anything" were one
7
+ * authority. A read view separates them, which is what will let analysis run
8
+ * after an observation has settled rather than racing the disk it is
9
+ * describing.
10
+ *
11
+ * The seam is landed; the settled side of it is not. Both production
12
+ * composition roots pass `LiveWorkspaceReadSource`, so what this interface
13
+ * buys today is that the authority is named and singular, not that it is
14
+ * settled. See `AdmittedWorkspaceSnapshot` for what is still missing.
15
+ *
16
+ * The primitive is bytes, not text. A basis identifies bytes, so a seam that
17
+ * decoded on the way through could not honour it: an undecodable file would
18
+ * either throw at the boundary or arrive silently replaced, and neither is the
19
+ * observed content. Decoding is an analysis projection, applied above.
20
+ */
21
+ export interface WorkspaceReadView {
22
+ /** Returns the bytes for a path. Rejects if it cannot produce them. */
23
+ readBytes(path: string): Promise<Uint8Array>;
24
+ }
25
+ /**
26
+ * What an observation retained about itself.
27
+ *
28
+ * Analysis has to be attributable to the observation that produced it. A
29
+ * result carrying no request or settlement identity cannot be replayed, and
30
+ * cannot be told apart from bytes someone assembled.
31
+ */
32
+ export interface WorkspaceReadEvidence {
33
+ readonly requestId: string;
34
+ readonly settlementId: string;
35
+ readonly workspaceRoot: string;
36
+ /** Identity of the exact bytes the observation settled. */
37
+ readonly basisDigest: string;
38
+ }
39
+ /**
40
+ * A read view over bytes an observation settled.
41
+ *
42
+ * Separate from `WorkspaceReadView` because fetching bytes and possessing
43
+ * settled bytes are not the same capability, and a single interface for both
44
+ * forced the live filesystem to inhabit a contract it cannot satisfy. It has
45
+ * no basis, so it supplied a sentinel in the field whose contract is "the
46
+ * identity of the exact bytes" — a value meaning "this is not a basis" living
47
+ * where the basis goes. One of these performs an effect and the other carries
48
+ * evidence; they are not substitutable.
49
+ */
50
+ export interface AdmittedWorkspaceReadView extends WorkspaceReadView {
51
+ readonly evidence: WorkspaceReadEvidence;
52
+ /** Every path the request admitted, in the order it declared them. */
53
+ admittedPaths(): readonly string[];
54
+ }
55
+ /**
56
+ * One file as a single observation saw it.
57
+ *
58
+ * Operations take this rather than a filesystem so that policy evaluation,
59
+ * cache comparison, and projection all describe the same bytes. When each
60
+ * step fetched its own copy, a file rewritten between two of them could be
61
+ * authorised in one version and returned in another, and the cache would
62
+ * record the hash of one beside the outline of the other.
63
+ *
64
+ * `utf8` is null when the bytes are not valid UTF-8. It is a separate field
65
+ * rather than a decode at the point of use because a basis identifies bytes:
66
+ * substituting replacement characters would return content the observation
67
+ * never settled, under the identity of content it did.
68
+ */
69
+ export interface ObservedFile {
70
+ readonly path: string;
71
+ readonly bytes: Uint8Array;
72
+ readonly utf8: string | null;
73
+ }
74
+ /**
75
+ * The size an observation has, whether or not it decodes as text.
76
+ *
77
+ * Policy must be evaluated for every observation, including bytes with no
78
+ * faithful text projection: a binary or banned path is refused for being
79
+ * binary or banned, and skipping the check when decoding fails would let it
80
+ * through to a projection instead. Counting 0x0A is exact for any byte
81
+ * sequence, because a newline byte cannot occur inside a multi-byte UTF-8
82
+ * sequence.
83
+ */
84
+ export declare function observedActual(file: ObservedFile): {
85
+ lines: number;
86
+ bytes: number;
87
+ };
88
+ /** Observes a path exactly once. Rejects if the view cannot produce it. */
89
+ export declare function observeFile(view: WorkspaceReadView, path: string): Promise<ObservedFile>;
90
+ declare const admittedSnapshotBrand: unique symbol;
91
+ /**
92
+ * An immutable observation, shaped as Echo would settle one.
93
+ *
94
+ * NOT YET PRODUCED IN PRODUCTION. There is no decoder that turns an Echo
95
+ * settlement into one of these, and no composition root constructs one. The
96
+ * only constructor is the test constructor below, so today every value of this
97
+ * type is admitted by assertion. Every production Graft read still goes through
98
+ * `LiveWorkspaceReadSource` to the live disk. Building the decoder is the
99
+ * remaining work in #228; until it exists, this type describes the destination,
100
+ * not the current state.
101
+ *
102
+ * The brand is compile-time friction, not runtime evidence. It stops a caller
103
+ * assembling one inline and having analysis treat it as settled, but a brand
104
+ * cannot attest that Echo settled anything — only a decoder validating the
105
+ * settlement envelope can, and that is what does not exist yet.
106
+ *
107
+ * The request-side fields are retained because analysis must be attributable
108
+ * to the observation that produced it: a snapshot with no request or
109
+ * settlement identity cannot be replayed, and cannot be told apart from bytes
110
+ * someone assembled.
111
+ */
112
+ interface WorkspaceSnapshotDescriptor {
113
+ readonly requestId: string;
114
+ readonly settlementId: string;
115
+ readonly workspaceRoot: string;
116
+ readonly basisDigest: string;
117
+ /** The exact paths the request admitted. */
118
+ readonly aperture: readonly string[];
119
+ readonly byteBudget: number;
120
+ readonly symlinkPolicy: "refuse";
121
+ }
122
+ export interface AdmittedWorkspaceSnapshot extends WorkspaceSnapshotDescriptor {
123
+ readonly [admittedSnapshotBrand]: true;
124
+ }
125
+ export interface WorkspaceSnapshotFields extends WorkspaceSnapshotDescriptor {
126
+ /** The settled files, keyed by workspace-relative path. */
127
+ readonly files: ReadonlyMap<string, SettledFile>;
128
+ }
129
+ /**
130
+ * One file as the observation recorded it.
131
+ *
132
+ * The entry kind is carried rather than assumed because refusing symlinks is a
133
+ * claim about what was observed, and a claim with nowhere to record its
134
+ * subject cannot be checked. A settlement that reports a symlink while
135
+ * declaring `symlinkPolicy: "refuse"` is self-contradictory, and the only
136
+ * place that contradiction is visible is here.
137
+ */
138
+ export interface SettledFile {
139
+ readonly bytes: Uint8Array;
140
+ readonly entryKind: "regular" | "symlink";
141
+ }
142
+ export type SnapshotAdmissionErrorCode = "INVALID_BYTE_BUDGET" | "DUPLICATE_APERTURE_PATH" | "MISSING_APERTURE_BYTES" | "OUTSIDE_APERTURE" | "SYMLINK_REFUSED" | "BYTE_BUDGET_EXCEEDED" | "MISSING_RETAINED_FILES";
143
+ /** A snapshot that contradicts a field it declares. */
144
+ export declare class SnapshotAdmissionError extends Error {
145
+ readonly code: SnapshotAdmissionErrorCode;
146
+ readonly detail: string;
147
+ constructor(code: SnapshotAdmissionErrorCode, detail: string);
148
+ }
149
+ /**
150
+ * Builds a snapshot that is admitted by assertion rather than by settlement.
151
+ *
152
+ * Named for what it is so that a production composition root using it is
153
+ * obvious in review. The assertion is only about provenance: no Echo
154
+ * settlement stands behind this value. The fields it declares are still
155
+ * checked, because a test fixture that could contradict itself would prove
156
+ * analysis works against observations that cannot occur.
157
+ *
158
+ * Copies its input, so a caller mutating the maps and arrays it passed cannot
159
+ * reach the snapshot afterwards.
160
+ */
161
+ export declare function unsafeAdmittedWorkspaceSnapshotForTest(fields: WorkspaceSnapshotFields): AdmittedWorkspaceSnapshot;
162
+ /** A path the snapshot does not admit. */
163
+ export declare class UnadmittedPathError extends Error {
164
+ readonly path: string;
165
+ readonly code: "UNADMITTED_PATH";
166
+ constructor(path: string);
167
+ }
168
+ /** A path the snapshot admits but for which it carries no bytes. */
169
+ export declare class MissingSnapshotBytesError extends Error {
170
+ readonly path: string;
171
+ readonly code: "MISSING_SETTLED_BYTES";
172
+ constructor(path: string);
173
+ }
174
+ /**
175
+ * A read view over settled snapshot bytes.
176
+ *
177
+ * Refuses rather than falling back: a path outside the aperture is a request
178
+ * for authority the observation did not grant, and answering it from disk
179
+ * would silently reintroduce the coupling this type exists to remove.
180
+ */
181
+ export declare class SnapshotWorkspaceReadView implements AdmittedWorkspaceReadView {
182
+ readonly evidence: WorkspaceReadEvidence;
183
+ constructor(snapshot: AdmittedWorkspaceSnapshot);
184
+ readBytes(path: string): Promise<Uint8Array>;
185
+ admittedPaths(): readonly string[];
186
+ }
187
+ /**
188
+ * Bytes read from the live filesystem at the moment of the call.
189
+ *
190
+ * This is the behaviour Graft had before observations were admitted, kept as
191
+ * an explicitly named adapter rather than as a default. It is deliberately
192
+ * **not** an `AdmittedWorkspaceReadView`: nothing about it is settled. The
193
+ * bytes it returns describe the disk when it was asked, so two reads can
194
+ * disagree, no basis over them means anything, and it has no admitted path set
195
+ * to enumerate. It offers neither, so a caller needing either fails to compile
196
+ * rather than receiving a sentinel or a rejected promise.
197
+ *
198
+ * Every production composition root still uses this. That is the remaining
199
+ * work in #228, and it is visible by name at each one.
200
+ */
201
+ export declare class LiveWorkspaceReadSource implements WorkspaceReadView {
202
+ private readonly fs;
203
+ readonly workspaceRoot: string;
204
+ constructor(fs: Pick<FileSystem, "isFileNotFoundError" | "readFile">, workspaceRoot: string);
205
+ readBytes(path: string): Promise<Uint8Array>;
206
+ }
207
+ export {};
208
+ //# sourceMappingURL=workspace-read-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-read-view.d.ts","sourceRoot":"","sources":["../../src/operations/workspace-read-view.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,302 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // © James Ross Ω FLYING•ROBOTS <https://github.com/flyingrobots>
3
+ /**
4
+ * The size an observation has, whether or not it decodes as text.
5
+ *
6
+ * Policy must be evaluated for every observation, including bytes with no
7
+ * faithful text projection: a binary or banned path is refused for being
8
+ * binary or banned, and skipping the check when decoding fails would let it
9
+ * through to a projection instead. Counting 0x0A is exact for any byte
10
+ * sequence, because a newline byte cannot occur inside a multi-byte UTF-8
11
+ * sequence.
12
+ */
13
+ export function observedActual(file) {
14
+ return {
15
+ lines: file.utf8 !== null
16
+ ? file.utf8.split("\n").length
17
+ : file.bytes.reduce((count, byte) => (byte === 0x0a ? count + 1 : count), 1),
18
+ bytes: file.bytes.byteLength,
19
+ };
20
+ }
21
+ /** Observes a path exactly once. Rejects if the view cannot produce it. */
22
+ export async function observeFile(view, path) {
23
+ const bytes = await view.readBytes(path);
24
+ let utf8;
25
+ try {
26
+ utf8 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
27
+ }
28
+ catch {
29
+ utf8 = null;
30
+ }
31
+ return { path, bytes, utf8 };
32
+ }
33
+ const retainedFilesBySnapshot = new WeakMap();
34
+ /** A snapshot that contradicts a field it declares. */
35
+ export class SnapshotAdmissionError extends Error {
36
+ code;
37
+ detail;
38
+ constructor(code, detail) {
39
+ super(`snapshot contradicts its own declaration: ${detail}`);
40
+ this.code = code;
41
+ this.detail = detail;
42
+ this.name = "SnapshotAdmissionError";
43
+ }
44
+ }
45
+ /**
46
+ * Checks a snapshot against the fields it declares.
47
+ *
48
+ * Every check here is internal consistency: it asks whether the settlement
49
+ * honours the request it claims to answer, not whether Echo settled it. That
50
+ * second question needs the settlement envelope, and belongs to the decoder
51
+ * that does not exist yet. Both callers want these checks, so they live apart
52
+ * from either.
53
+ *
54
+ * Refusing at construction rather than at read time is the point. A snapshot
55
+ * that passes here is total over its aperture, so analysis can treat the
56
+ * observation as complete instead of discovering a hole partway through and
57
+ * having to decide what an absent admitted path means.
58
+ */
59
+ function checkSnapshotFields(fields) {
60
+ if (!Number.isSafeInteger(fields.byteBudget) || fields.byteBudget < 0) {
61
+ throw new SnapshotAdmissionError("INVALID_BYTE_BUDGET", `byte budget is not a non-negative safe integer: ${String(fields.byteBudget)}`);
62
+ }
63
+ const admitted = new Set();
64
+ for (const path of fields.aperture) {
65
+ if (admitted.has(path)) {
66
+ throw new SnapshotAdmissionError("DUPLICATE_APERTURE_PATH", `aperture lists a duplicate path: ${path}`);
67
+ }
68
+ admitted.add(path);
69
+ }
70
+ for (const path of admitted) {
71
+ if (!fields.files.has(path)) {
72
+ throw new SnapshotAdmissionError("MISSING_APERTURE_BYTES", `aperture path carries no settled bytes: ${path}`);
73
+ }
74
+ }
75
+ let settledBytes = 0;
76
+ for (const [path, file] of fields.files) {
77
+ if (!admitted.has(path)) {
78
+ throw new SnapshotAdmissionError("OUTSIDE_APERTURE", `settled bytes for a path outside the aperture: ${path}`);
79
+ }
80
+ // Unconditional because `symlinkPolicy` admits exactly one value today.
81
+ // Branching on it would read as though a snapshot could permit symlinks,
82
+ // and the first reader to add a second policy value would find the branch
83
+ // already written and assume it had been thought through.
84
+ if (file.entryKind === "symlink") {
85
+ throw new SnapshotAdmissionError("SYMLINK_REFUSED", `symlink recorded under a policy that refuses symlinks: ${path}`);
86
+ }
87
+ settledBytes += file.bytes.byteLength;
88
+ }
89
+ if (settledBytes > fields.byteBudget) {
90
+ throw new SnapshotAdmissionError("BYTE_BUDGET_EXCEEDED", `settled bytes exceed the declared byte budget: ` +
91
+ `${String(settledBytes)} > ${String(fields.byteBudget)}`);
92
+ }
93
+ }
94
+ function copySnapshotFields(fields) {
95
+ const files = new Map();
96
+ for (const [path, file] of fields.files) {
97
+ files.set(path, {
98
+ bytes: Uint8Array.from(file.bytes),
99
+ entryKind: file.entryKind,
100
+ });
101
+ }
102
+ return {
103
+ requestId: fields.requestId,
104
+ settlementId: fields.settlementId,
105
+ workspaceRoot: fields.workspaceRoot,
106
+ basisDigest: fields.basisDigest,
107
+ aperture: [...fields.aperture],
108
+ byteBudget: fields.byteBudget,
109
+ symlinkPolicy: fields.symlinkPolicy,
110
+ files,
111
+ };
112
+ }
113
+ /**
114
+ * Builds a snapshot that is admitted by assertion rather than by settlement.
115
+ *
116
+ * Named for what it is so that a production composition root using it is
117
+ * obvious in review. The assertion is only about provenance: no Echo
118
+ * settlement stands behind this value. The fields it declares are still
119
+ * checked, because a test fixture that could contradict itself would prove
120
+ * analysis works against observations that cannot occur.
121
+ *
122
+ * Copies its input, so a caller mutating the maps and arrays it passed cannot
123
+ * reach the snapshot afterwards.
124
+ */
125
+ export function unsafeAdmittedWorkspaceSnapshotForTest(fields) {
126
+ const copiedFields = copySnapshotFields(fields);
127
+ checkSnapshotFields(copiedFields);
128
+ const snapshot = Object.freeze({
129
+ requestId: copiedFields.requestId,
130
+ settlementId: copiedFields.settlementId,
131
+ workspaceRoot: copiedFields.workspaceRoot,
132
+ basisDigest: copiedFields.basisDigest,
133
+ aperture: Object.freeze([...copiedFields.aperture]),
134
+ byteBudget: copiedFields.byteBudget,
135
+ symlinkPolicy: copiedFields.symlinkPolicy,
136
+ });
137
+ retainedFilesBySnapshot.set(snapshot, copiedFields.files);
138
+ return snapshot;
139
+ }
140
+ /** A path the snapshot does not admit. */
141
+ export class UnadmittedPathError extends Error {
142
+ path;
143
+ code = "UNADMITTED_PATH";
144
+ constructor(path) {
145
+ super(`path is outside the admitted snapshot aperture: ${path}`);
146
+ this.path = path;
147
+ this.name = "UnadmittedPathError";
148
+ }
149
+ }
150
+ /** A path the snapshot admits but for which it carries no bytes. */
151
+ export class MissingSnapshotBytesError extends Error {
152
+ path;
153
+ code = "MISSING_SETTLED_BYTES";
154
+ constructor(path) {
155
+ super(`admitted path carries no settled bytes: ${path}`);
156
+ this.path = path;
157
+ this.name = "MissingSnapshotBytesError";
158
+ }
159
+ }
160
+ const retainedReadStateByView = new WeakMap();
161
+ function retainedReadState(view) {
162
+ const state = retainedReadStateByView.get(view);
163
+ if (state === undefined) {
164
+ throw new Error("SnapshotWorkspaceReadView has no retained read state");
165
+ }
166
+ return state;
167
+ }
168
+ /**
169
+ * Snapshot evidence has no platform tag yet. Drive roots and backslash-UNC
170
+ * roots are unambiguously Windows; slash-rooted paths remain POSIX so a legal
171
+ * backslash in a POSIX filename cannot become authority over another path.
172
+ */
173
+ function usesWindowsPathSyntax(workspaceRoot) {
174
+ return /^[A-Za-z]:[\\/]/u.test(workspaceRoot) || workspaceRoot.startsWith("\\\\");
175
+ }
176
+ function snapshotLookupPath(workspaceRoot, requestedPath) {
177
+ const windowsPathSyntax = usesWindowsPathSyntax(workspaceRoot);
178
+ const normalizedRoot = (windowsPathSyntax ? workspaceRoot.replaceAll("\\", "/") : workspaceRoot)
179
+ .replace(/\/+$/u, "");
180
+ const normalizedRequest = windowsPathSyntax
181
+ ? requestedPath.replaceAll("\\", "/")
182
+ : requestedPath;
183
+ const rootPrefix = normalizedRoot.length === 0 ? "/" : `${normalizedRoot}/`;
184
+ return normalizedRequest.startsWith(rootPrefix)
185
+ ? normalizedRequest.slice(rootPrefix.length)
186
+ : requestedPath;
187
+ }
188
+ /**
189
+ * A read view over settled snapshot bytes.
190
+ *
191
+ * Refuses rather than falling back: a path outside the aperture is a request
192
+ * for authority the observation did not grant, and answering it from disk
193
+ * would silently reintroduce the coupling this type exists to remove.
194
+ */
195
+ export class SnapshotWorkspaceReadView {
196
+ evidence;
197
+ constructor(snapshot) {
198
+ if (new.target !== SnapshotWorkspaceReadView) {
199
+ throw new TypeError("SnapshotWorkspaceReadView does not support subclass construction");
200
+ }
201
+ this.evidence = Object.freeze({
202
+ requestId: snapshot.requestId,
203
+ settlementId: snapshot.settlementId,
204
+ workspaceRoot: snapshot.workspaceRoot,
205
+ basisDigest: snapshot.basisDigest,
206
+ });
207
+ Object.defineProperty(this, "evidence", {
208
+ writable: false,
209
+ configurable: false,
210
+ });
211
+ const retainedFiles = retainedFilesBySnapshot.get(snapshot);
212
+ if (retainedFiles === undefined) {
213
+ throw new SnapshotAdmissionError("MISSING_RETAINED_FILES", "snapshot has no retained settled bytes");
214
+ }
215
+ // Copied on the way in, so a snapshot assembled from a caller's mutable
216
+ // maps cannot change underneath the view once it exists.
217
+ const bytes = new Map();
218
+ for (const [path, file] of retainedFiles) {
219
+ bytes.set(path, Uint8Array.from(file.bytes));
220
+ }
221
+ retainedReadStateByView.set(this, {
222
+ bytes,
223
+ aperture: [...snapshot.aperture],
224
+ admitted: new Set(snapshot.aperture),
225
+ });
226
+ Object.freeze(this);
227
+ }
228
+ // Asynchronous because a filesystem-backed view cannot read lazily behind a
229
+ // synchronous signature, and both must satisfy one interface for
230
+ // RepoWorkspace analysis methods to depend on exactly one read view.
231
+ readBytes(path) {
232
+ const state = retainedReadState(this);
233
+ const lookupPath = snapshotLookupPath(this.evidence.workspaceRoot, path);
234
+ if (!state.admitted.has(lookupPath)) {
235
+ return Promise.reject(new UnadmittedPathError(path));
236
+ }
237
+ const content = state.bytes.get(lookupPath);
238
+ if (content === undefined) {
239
+ // Unreachable: admission requires the aperture and the settled-file set
240
+ // to agree exactly. Kept as a guard so a future decoder that skipped
241
+ // that check would fail loudly here rather than return absent bytes.
242
+ return Promise.reject(new MissingSnapshotBytesError(path));
243
+ }
244
+ // Copied on the way out, so a caller writing through the returned array
245
+ // cannot rewrite the retained evidence.
246
+ return Promise.resolve(Uint8Array.from(content));
247
+ }
248
+ admittedPaths() {
249
+ // From the aperture, which is what the request admitted — not from the
250
+ // byte entries that happen to be present. Answering from the latter is how
251
+ // a partial settlement would report itself as a complete one.
252
+ return [...retainedReadState(this).aperture];
253
+ }
254
+ }
255
+ Object.freeze(SnapshotWorkspaceReadView.prototype);
256
+ /**
257
+ * Bytes read from the live filesystem at the moment of the call.
258
+ *
259
+ * This is the behaviour Graft had before observations were admitted, kept as
260
+ * an explicitly named adapter rather than as a default. It is deliberately
261
+ * **not** an `AdmittedWorkspaceReadView`: nothing about it is settled. The
262
+ * bytes it returns describe the disk when it was asked, so two reads can
263
+ * disagree, no basis over them means anything, and it has no admitted path set
264
+ * to enumerate. It offers neither, so a caller needing either fails to compile
265
+ * rather than receiving a sentinel or a rejected promise.
266
+ *
267
+ * Every production composition root still uses this. That is the remaining
268
+ * work in #228, and it is visible by name at each one.
269
+ */
270
+ export class LiveWorkspaceReadSource {
271
+ fs;
272
+ workspaceRoot;
273
+ constructor(fs, workspaceRoot) {
274
+ this.fs = fs;
275
+ this.workspaceRoot = workspaceRoot;
276
+ }
277
+ async readBytes(path) {
278
+ try {
279
+ return Uint8Array.from(await this.fs.readFile(path));
280
+ }
281
+ catch (error) {
282
+ const isMissing = this.fs.isFileNotFoundError !== undefined
283
+ ? this.fs.isFileNotFoundError(error)
284
+ : isPortableFileNotFoundError(error);
285
+ if (isMissing) {
286
+ throw Object.assign(new Error(`Workspace file not found: ${path}`), {
287
+ code: "ENOENT",
288
+ cause: error,
289
+ });
290
+ }
291
+ throw error;
292
+ }
293
+ }
294
+ }
295
+ function isPortableFileNotFoundError(error) {
296
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
297
+ return true;
298
+ }
299
+ return error instanceof Error
300
+ && (error.name === "NotFoundError" || /^(?:file )?not found(?:\b|:)/i.test(error.message));
301
+ }
302
+ //# sourceMappingURL=workspace-read-view.js.map