dirsql 0.4.115__tar.gz → 0.4.117__tar.gz

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 (472) hide show
  1. {dirsql-0.4.115 → dirsql-0.4.117}/Cargo.lock +2 -2
  2. {dirsql-0.4.115 → dirsql-0.4.117}/PKG-INFO +1 -1
  3. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/Cargo.toml +1 -1
  4. dirsql-0.4.117/packages/python/e2e-attestations/bot-1477-onelevel-speed-1016.json +7 -0
  5. dirsql-0.4.117/packages/python/e2e-attestations/bot-1480-matcher-speed-1015.json +7 -0
  6. dirsql-0.4.117/packages/python/e2e-attestations/bot-1524-path-eq-1016.json +7 -0
  7. dirsql-0.4.117/packages/python/e2e-attestations/bot-1532-gitignore-fastest-bar-1016.json +7 -0
  8. dirsql-0.4.117/packages/python/e2e-attestations/bot-1534-fm-native-1016.json +7 -0
  9. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/Cargo.toml +1 -1
  10. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/db.rs +71 -51
  11. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/lib.rs +159 -49
  12. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/listing.rs +25 -46
  13. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/scanner.rs +324 -144
  14. dirsql-0.4.117/packages/rust/src/tree_walk.rs +338 -0
  15. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/vtab_scaffold.rs +96 -11
  16. dirsql-0.4.115/packages/rust/src/tree_walk.rs +0 -327
  17. {dirsql-0.4.115 → dirsql-0.4.117}/Cargo.toml +0 -0
  18. {dirsql-0.4.115 → dirsql-0.4.117}/README.md +0 -0
  19. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/__init__.py +0 -0
  20. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/_async.py +0 -0
  21. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/_dirsql.pyi +0 -0
  22. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/cli/__init__.py +0 -0
  23. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/cli/discover_plugins/__init__.py +0 -0
  24. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
  25. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
  26. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
  27. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
  28. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/cli/main.py +0 -0
  29. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/cli/resolve_config_extensions.py +0 -0
  30. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/plan_entry_path.py +0 -0
  31. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/py.typed +0 -0
  32. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/read_config.py +0 -0
  33. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/resolve_configs_extension_specs.py +0 -0
  34. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/resolve_extension.py +0 -0
  35. {dirsql-0.4.115 → dirsql-0.4.117}/dirsql/resolve_package.py +0 -0
  36. {dirsql-0.4.115 → dirsql-0.4.117}/docs/.claude/CLAUDE.md +0 -0
  37. {dirsql-0.4.115 → dirsql-0.4.117}/docs/.vitepress/config.ts +0 -0
  38. {dirsql-0.4.115 → dirsql-0.4.117}/docs/.vitepress/theme/index.ts +0 -0
  39. {dirsql-0.4.115 → dirsql-0.4.117}/docs/.vitepress/theme/lang.ts +0 -0
  40. {dirsql-0.4.115 → dirsql-0.4.117}/docs/AGENTS.md +0 -0
  41. {dirsql-0.4.115 → dirsql-0.4.117}/docs/context/.gitattributes +0 -0
  42. {dirsql-0.4.115 → dirsql-0.4.117}/docs/context/recipes.md +0 -0
  43. {dirsql-0.4.115 → dirsql-0.4.117}/docs/context/troubleshooting.md +0 -0
  44. {dirsql-0.4.115 → dirsql-0.4.117}/docs/context/usage.md +0 -0
  45. {dirsql-0.4.115 → dirsql-0.4.117}/docs/explanation.md +0 -0
  46. {dirsql-0.4.115 → dirsql-0.4.117}/docs/getting-started.md +0 -0
  47. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/agent-skill.md +0 -0
  48. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/columns-from-paths.md +0 -0
  49. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/define-tables.md +0 -0
  50. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/embed.md +0 -0
  51. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/extract-from-contents.md +0 -0
  52. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/load-extension.md +0 -0
  53. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/parse-files-into-columns.md +0 -0
  54. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/persist.md +0 -0
  55. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/query-json.md +0 -0
  56. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/query-without-config.md +0 -0
  57. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/react-to-changes.md +0 -0
  58. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/search-by-meaning.md +0 -0
  59. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/search-indexes.md +0 -0
  60. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/skip-files.md +0 -0
  61. {dirsql-0.4.115 → dirsql-0.4.117}/docs/howto/write-a-plugin.md +0 -0
  62. {dirsql-0.4.115 → dirsql-0.4.117}/docs/index.md +0 -0
  63. {dirsql-0.4.115 → dirsql-0.4.117}/docs/package.json +0 -0
  64. {dirsql-0.4.115 → dirsql-0.4.117}/docs/plugins.md +0 -0
  65. {dirsql-0.4.115 → dirsql-0.4.117}/docs/pnpm-lock.yaml +0 -0
  66. {dirsql-0.4.115 → dirsql-0.4.117}/docs/pnpm-workspace.yaml +0 -0
  67. {dirsql-0.4.115 → dirsql-0.4.117}/docs/reference/cli.md +0 -0
  68. {dirsql-0.4.115 → dirsql-0.4.117}/docs/reference/columns.md +0 -0
  69. {dirsql-0.4.115 → dirsql-0.4.117}/docs/reference/config.md +0 -0
  70. {dirsql-0.4.115 → dirsql-0.4.117}/docs/reference/glob.md +0 -0
  71. {dirsql-0.4.115 → dirsql-0.4.117}/docs/reference/hooks.md +0 -0
  72. {dirsql-0.4.115 → dirsql-0.4.117}/docs/reference/http-api.md +0 -0
  73. {dirsql-0.4.115 → dirsql-0.4.117}/docs/reference/path-tables.md +0 -0
  74. {dirsql-0.4.115 → dirsql-0.4.117}/docs/reference/sdk.md +0 -0
  75. {dirsql-0.4.115 → dirsql-0.4.117}/docs/speed.json +0 -0
  76. {dirsql-0.4.115 → dirsql-0.4.117}/docs/speed.md +0 -0
  77. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/CHANGELOG.md +0 -0
  78. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/MIGRATIONS.md +0 -0
  79. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/README.md +0 -0
  80. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  81. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
  82. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  83. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
  84. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  85. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
  86. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
  87. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
  88. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  89. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
  90. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
  91. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
  92. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
  93. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
  94. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
  95. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
  96. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
  97. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
  98. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
  99. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
  100. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
  101. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
  102. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
  103. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
  104. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
  105. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
  106. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
  107. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
  108. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  109. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  110. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-02-readme-docs-host.md +0 -0
  111. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  112. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-03-path-table-directory-one-level.md +0 -0
  113. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  114. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  115. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-05-cli-context.md +0 -0
  116. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-05-gitignore-requires-repo.md +0 -0
  117. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-05-path-table-node-modules-named.md +0 -0
  118. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-05-path-table-symlinks.md +0 -0
  119. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-05-path-table-trailing-slash.md +0 -0
  120. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-05-unbalanced-brackets-literal.md +0 -0
  121. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-config-braces.md +0 -0
  122. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-config-directory.md +0 -0
  123. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-config-dotnames.md +0 -0
  124. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-config-gitignore.md +0 -0
  125. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
  126. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-config-links.md +0 -0
  127. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-one-glob-compiler.md +0 -0
  128. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-plugin-no-default-records.md +0 -0
  129. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-watch-broadcast.md +0 -0
  130. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-06-zero-match-config-table-warning.md +0 -0
  131. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-bracket-slash-literal.md +0 -0
  132. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-dotdot-and-double-slashes.md +0 -0
  133. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-dotdot-as-written.md +0 -0
  134. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-glob-walks-node-modules.md +0 -0
  135. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-literal-gitignore.md +0 -0
  136. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-on-file-ndjson.md +0 -0
  137. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-parallel-hooks.md +0 -0
  138. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-persist-cache-outside-root.md +0 -0
  139. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-posix-classes-unicode.md +0 -0
  140. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-07-spread-few-large-files.md +0 -0
  141. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-08-small-walks-stay-on-one-thread.md +0 -0
  142. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/2026-10-08-watch-requires-named-table.md +0 -0
  143. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/changelog.d/README.md +0 -0
  144. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/conftest.py +0 -0
  145. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/.claude/CLAUDE.md +0 -0
  146. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/.vitepress/config.ts +0 -0
  147. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/.vitepress/theme/index.ts +0 -0
  148. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
  149. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/AGENTS.md +0 -0
  150. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/context/.gitattributes +0 -0
  151. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/context/recipes.md +0 -0
  152. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/context/troubleshooting.md +0 -0
  153. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/context/usage.md +0 -0
  154. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/explanation.md +0 -0
  155. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/getting-started.md +0 -0
  156. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/agent-skill.md +0 -0
  157. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/columns-from-paths.md +0 -0
  158. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/define-tables.md +0 -0
  159. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/embed.md +0 -0
  160. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/extract-from-contents.md +0 -0
  161. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/load-extension.md +0 -0
  162. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
  163. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/persist.md +0 -0
  164. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/query-json.md +0 -0
  165. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/query-without-config.md +0 -0
  166. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/react-to-changes.md +0 -0
  167. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/search-by-meaning.md +0 -0
  168. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/search-indexes.md +0 -0
  169. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/skip-files.md +0 -0
  170. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/howto/write-a-plugin.md +0 -0
  171. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/index.md +0 -0
  172. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/package.json +0 -0
  173. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/plugins.md +0 -0
  174. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/pnpm-lock.yaml +0 -0
  175. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/pnpm-workspace.yaml +0 -0
  176. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/reference/cli.md +0 -0
  177. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/reference/columns.md +0 -0
  178. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/reference/config.md +0 -0
  179. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/reference/glob.md +0 -0
  180. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/reference/hooks.md +0 -0
  181. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/reference/http-api.md +0 -0
  182. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/reference/path-tables.md +0 -0
  183. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/reference/sdk.md +0 -0
  184. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/speed.json +0 -0
  185. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/docs/speed.md +0 -0
  186. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1334-listing-exemptions.json +0 -0
  187. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1397-watch-broadcast.json +0 -0
  188. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1398-inotify-error.json +0 -0
  189. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1399-server-cors.json +0 -0
  190. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1401-watch-scope.json +0 -0
  191. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1406-watch-no-tables-1008.json +0 -0
  192. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1407-child-place-depth.json +0 -0
  193. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1414-stat-speed.json +0 -0
  194. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1415-server-speed.json +0 -0
  195. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1416-watch-speed-1008.json +0 -0
  196. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1418-node-modules.json +0 -0
  197. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1419-dotdot-slashes.json +0 -0
  198. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1420-bracket-slash.json +0 -0
  199. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1421-posix-unicode.json +0 -0
  200. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1422-literal-gitignore.json +0 -0
  201. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1426-walk-spawn-threshold-1008.json +0 -0
  202. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1428-ndjson-hooks.json +0 -0
  203. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1429-parallel-hooks.json +0 -0
  204. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1430-dotdot-as-written.json +0 -0
  205. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1431-persist-cache-dir.json +0 -0
  206. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1437-test-cache-isolation.json +0 -0
  207. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1440-fix-main-build.json +0 -0
  208. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1448-wildcard-ignored-prefix.json +0 -0
  209. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1451-named-dir-never-hidden.json +0 -0
  210. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1454-split-few-files.json +0 -0
  211. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1457-incremental-refresh-1008.json +0 -0
  212. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1459-rescan-on-overflow-1008.json +0 -0
  213. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1461-row-footprint-1008.json +0 -0
  214. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1461-wide-read-1015.json +0 -0
  215. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1462-paired-speed-harness-1008.json +0 -0
  216. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1464-fastest-native-1008.json +0 -0
  217. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1469-ci-speed-sanity-1009.json +0 -0
  218. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1470-perf-suite-1009.json +0 -0
  219. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1470-speed-page-1011.json +0 -0
  220. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1474-vtab-speed-1014.json +0 -0
  221. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1477-onelevel-speed-1015.json +0 -0
  222. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1481-gitrepo-speed-1015.json +0 -0
  223. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1483-fm-speed-1015.json +0 -0
  224. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1484-jsonl-speed-1015.json +0 -0
  225. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1487-frontend-query-1011.json +0 -0
  226. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1488-frontend-metadata-1011.json +0 -0
  227. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1489-frontend-browse-1013.json +0 -0
  228. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1503-bench-watch-1011.json +0 -0
  229. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1504-bench-names-1011.json +0 -0
  230. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1514-watch-rerun-inline-1015.json +0 -0
  231. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-1526-main-red-1016.json +0 -0
  232. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-fix-main-place-depth-20261007.json +0 -0
  233. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-issue-1486-frontend-20261009.json +0 -0
  234. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-speed-gap-childpath-1011.json +0 -0
  235. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-speed-parse-overlap-1011.json +0 -0
  236. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-speed-parse-paths-1009.json +0 -0
  237. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-speed-parse-pragmas-1011.json +0 -0
  238. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-speed-sql-valueref-1013.json +0 -0
  239. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-speed-walk-components-1011.json +0 -0
  240. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-speed-walk-rowpath-1011.json +0 -0
  241. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-speed-walk-rows-1013.json +0 -0
  242. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/bot-speed-walk-sched-1009.json +0 -0
  243. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
  244. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
  245. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
  246. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
  247. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
  248. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
  249. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
  250. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
  251. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
  252. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
  253. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
  254. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
  255. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
  256. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
  257. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
  258. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
  259. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
  260. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
  261. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
  262. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
  263. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
  264. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1184-win-rel-paths.json +0 -0
  265. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +0 -0
  266. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1186-win-test-harness.json +0 -0
  267. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1196-join-index.json +0 -0
  268. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1199-glob-prefix.json +0 -0
  269. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1201-single-walk.json +0 -0
  270. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1204-embed-batch.json +0 -0
  271. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1207-win-argv-quote.json +0 -0
  272. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1208-win-nonverbatim-paths.json +0 -0
  273. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1215-on-file-batch.json +0 -0
  274. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1216-on-file-cleanup.json +0 -0
  275. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1223-config-glob-rule.json +0 -0
  276. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1223-dir-one-level.json +0 -0
  277. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1225-plugin-no-default.json +0 -0
  278. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1226-stale-docs.json +0 -0
  279. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1232-anchor-plumbing.json +0 -0
  280. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1232-config-anchor.json +0 -0
  281. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1232-multi-watch.json +0 -0
  282. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1232-zero-match.json +0 -0
  283. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1238-parallel-walk.json +0 -0
  284. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1241-content-prefetch.json +0 -0
  285. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1243-ingest-perf.json +0 -0
  286. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1249-dotfiles.json +0 -0
  287. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1256-symlinks.json +0 -0
  288. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1257-trailing-slash.json +0 -0
  289. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1258-config-braces.json +0 -0
  290. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1258-config-directory.json +0 -0
  291. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1258-config-dotnames.json +0 -0
  292. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1258-config-gitignore.json +0 -0
  293. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1258-config-links.json +0 -0
  294. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1258-one-pattern.json +0 -0
  295. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1262-brace-literal.json +0 -0
  296. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1264-context.json +0 -0
  297. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1267-posix-classes.json +0 -0
  298. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1268-unbalanced-brackets.json +0 -0
  299. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1269-utf8-chars.json +0 -0
  300. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1271-node-modules-named.json +0 -0
  301. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1272-ancestor-gitignore.json +0 -0
  302. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1273-walk-prune.json +0 -0
  303. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1285-ingest-fast.json +0 -0
  304. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1286-nested-repo.json +0 -0
  305. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1305-glob-speed.json +0 -0
  306. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1308-glob-speed.json +0 -0
  307. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1310-glob-speed.json +0 -0
  308. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1311-glob-speed.json +0 -0
  309. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1312-glob-speed.json +0 -0
  310. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1318-lazy-stat.json +0 -0
  311. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1320-walk-speed.json +0 -0
  312. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1322-walk-readdir.json +0 -0
  313. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1325-parallel-walk.json +0 -0
  314. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1326-stream-rows.json +0 -0
  315. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1330-python-dirsql-patch.json +0 -0
  316. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1330-python-extensions-patch.json +0 -0
  317. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1330-scanner-effects.json +0 -0
  318. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1330-scanner-gitignore.json +0 -0
  319. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1330-vtab-prefetch-flag.json +0 -0
  320. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1330-vtab-read.json +0 -0
  321. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-1351-dot-dirs.json +0 -0
  322. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
  323. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
  324. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
  325. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
  326. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
  327. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
  328. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
  329. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
  330. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
  331. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
  332. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
  333. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
  334. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
  335. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
  336. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
  337. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  338. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  339. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  340. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
  341. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
  342. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
  343. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  344. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
  345. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
  346. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
  347. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  348. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  349. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-02-readme-docs-host.md +0 -0
  350. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  351. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-03-path-table-directory-one-level.md +0 -0
  352. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  353. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  354. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-05-cli-context.md +0 -0
  355. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-05-gitignore-requires-repo.md +0 -0
  356. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-05-path-table-node-modules-named.md +0 -0
  357. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-05-path-table-symlinks.md +0 -0
  358. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-05-path-table-trailing-slash.md +0 -0
  359. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-05-unbalanced-brackets-literal.md +0 -0
  360. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-config-braces.md +0 -0
  361. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-config-directory.md +0 -0
  362. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-config-dotnames.md +0 -0
  363. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-config-gitignore.md +0 -0
  364. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
  365. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-config-links.md +0 -0
  366. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-one-glob-compiler.md +0 -0
  367. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-plugin-no-default-records.md +0 -0
  368. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-watch-broadcast.md +0 -0
  369. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-06-zero-match-config-table-warning.md +0 -0
  370. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-bracket-slash-literal.md +0 -0
  371. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-dotdot-and-double-slashes.md +0 -0
  372. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-dotdot-as-written.md +0 -0
  373. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-glob-walks-node-modules.md +0 -0
  374. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-literal-gitignore.md +0 -0
  375. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-on-file-ndjson.md +0 -0
  376. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-parallel-hooks.md +0 -0
  377. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-persist-cache-outside-root.md +0 -0
  378. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-posix-classes-unicode.md +0 -0
  379. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-07-spread-few-large-files.md +0 -0
  380. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-08-small-walks-stay-on-one-thread.md +0 -0
  381. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/2026-10-08-watch-requires-named-table.md +0 -0
  382. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/migrations.d/README.md +0 -0
  383. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/src/lib.rs +0 -0
  384. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/testing-conventions.toml +0 -0
  385. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/__init__.py +0 -0
  386. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/conftest.py +0 -0
  387. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/e2e/__init__.py +0 -0
  388. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/e2e/bench_report.py +0 -0
  389. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/e2e/bench_suite.py +0 -0
  390. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
  391. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
  392. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/e2e/speed_of_light.py +0 -0
  393. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/integration/__init__.py +0 -0
  394. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/integration/binding/__init__.py +0 -0
  395. {dirsql-0.4.115 → dirsql-0.4.117}/packages/python/tests/integration/hermetic/__init__.py +0 -0
  396. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/CHANGELOG.md +0 -0
  397. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/MIGRATIONS.md +0 -0
  398. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/README.md +0 -0
  399. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/benches/db_bench.rs +0 -0
  400. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/benches/differ_bench.rs +0 -0
  401. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/benches/matcher_bench.rs +0 -0
  402. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/benches/scanner_bench.rs +0 -0
  403. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/context/.gitattributes +0 -0
  404. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/context/recipes.md +0 -0
  405. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/context/troubleshooting.md +0 -0
  406. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/context/usage.md +0 -0
  407. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/explanation.md +0 -0
  408. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/getting-started.md +0 -0
  409. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/agent-skill.md +0 -0
  410. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/columns-from-paths.md +0 -0
  411. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/define-tables.md +0 -0
  412. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/embed.md +0 -0
  413. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/extract-from-contents.md +0 -0
  414. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/load-extension.md +0 -0
  415. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
  416. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/persist.md +0 -0
  417. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/query-json.md +0 -0
  418. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/query-without-config.md +0 -0
  419. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/react-to-changes.md +0 -0
  420. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/search-by-meaning.md +0 -0
  421. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/search-indexes.md +0 -0
  422. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/skip-files.md +0 -0
  423. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/howto/write-a-plugin.md +0 -0
  424. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/index.md +0 -0
  425. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/plugins.md +0 -0
  426. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/reference/cli.md +0 -0
  427. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/reference/columns.md +0 -0
  428. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/reference/config.md +0 -0
  429. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/reference/glob.md +0 -0
  430. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/reference/hooks.md +0 -0
  431. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/reference/http-api.md +0 -0
  432. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/reference/path-tables.md +0 -0
  433. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/reference/sdk.md +0 -0
  434. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/speed.json +0 -0
  435. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/docs/speed.md +0 -0
  436. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/bin/dirsql.rs +0 -0
  437. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/brace.rs +0 -0
  438. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/context.rs +0 -0
  439. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/execute.rs +0 -0
  440. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/frontend.html +0 -0
  441. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/frontend.js +0 -0
  442. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/init.rs +0 -0
  443. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/mod.rs +0 -0
  444. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/repl.rs +0 -0
  445. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/router.rs +0 -0
  446. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/run.rs +0 -0
  447. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/serialize.rs +0 -0
  448. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/server.rs +0 -0
  449. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/cli/table.rs +0 -0
  450. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/command.rs +0 -0
  451. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/config.rs +0 -0
  452. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/default_config.toml +0 -0
  453. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/differ.rs +0 -0
  454. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/extension_resolution.rs +0 -0
  455. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/functions.rs +0 -0
  456. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/gitignore_frame.rs +0 -0
  457. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/infer.rs +0 -0
  458. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/launcher.rs +0 -0
  459. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/matcher.rs +0 -0
  460. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/on_file.rs +0 -0
  461. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/parsed_vtab.rs +0 -0
  462. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/path_table.rs +0 -0
  463. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/per_thread.rs +0 -0
  464. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/persist.rs +0 -0
  465. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/posix_class.rs +0 -0
  466. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/progress.rs +0 -0
  467. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/row_event_flat.rs +0 -0
  468. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/row_stream.rs +0 -0
  469. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/sql_literal.rs +0 -0
  470. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/vtab.rs +0 -0
  471. {dirsql-0.4.115 → dirsql-0.4.117}/packages/rust/src/watcher.rs +0 -0
  472. {dirsql-0.4.115 → dirsql-0.4.117}/pyproject.toml +0 -0
@@ -573,7 +573,7 @@ dependencies = [
573
573
 
574
574
  [[package]]
575
575
  name = "dirsql"
576
- version = "0.4.115"
576
+ version = "0.4.117"
577
577
  dependencies = [
578
578
  "assert_cmd",
579
579
  "axum",
@@ -625,7 +625,7 @@ dependencies = [
625
625
 
626
626
  [[package]]
627
627
  name = "dirsql-py-ext"
628
- version = "0.4.115"
628
+ version = "0.4.117"
629
629
  dependencies = [
630
630
  "dirsql",
631
631
  "pyo3",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirsql
3
- Version: 0.4.115
3
+ Version: 0.4.117
4
4
  Requires-Dist: bin-shim>=0.1
5
5
  Summary: Ephemeral SQL index over a local directory
6
6
  Keywords: sql,filesystem,directory,sqlite,index
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
4
4
  # pypi/maturin handler can rewrite it via `write-version` before
5
5
  # `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
6
6
  # and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
7
- version = "0.4.115"
7
+ version = "0.4.117"
8
8
  # abi3 note: the `abi3-py310` pyo3 feature (below) builds ONE stable-ABI
9
9
  # `cp310-abi3` wheel per platform that loads on every CPython >= 3.10
10
10
  # (matching `pyproject.toml`'s `requires-python = ">=3.10"`), instead of
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/glob_speed_depth_bound_test.py tests/e2e/glob_speed_one_level_test.py tests/e2e/glob_speed_recursive_test.py tests/e2e/glob_speed_matchers_test.py tests/e2e/glob_speed_dotfiles_test.py tests/e2e/glob_speed_gitignore_test.py tests/e2e/glob_speed_node_modules_test.py tests/e2e/glob_speed_symlink_test.py tests/e2e/query_contract_test.py tests/e2e/fanout_test.py tests/e2e/use_case_join_test.py -q -s",
3
+ "ran_at": 1792409702,
4
+ "exit_code": 0,
5
+ "commit": "f500062c3a69da8d29e351d1a5580cff8f5af696",
6
+ "branch": "bot/1477-onelevel-speed-1016"
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/glob_speed_matchers_test.py tests/e2e/glob_speed_recursive_test.py tests/e2e/glob_speed_gitignore_test.py tests/e2e/glob_speed_depth_bound_test.py tests/e2e/glob_speed_one_level_test.py tests/e2e/query_contract_test.py -q",
3
+ "ran_at": 1792158925,
4
+ "exit_code": 0,
5
+ "commit": "e01da64bd1c48112f77059fab894961c5dc241ce",
6
+ "branch": "bot/1480-matcher-speed-1015"
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/glob_speed_recursive_test.py tests/e2e/use_case_join_test.py -x -q",
3
+ "ran_at": 1792151597,
4
+ "exit_code": 0,
5
+ "commit": "05acaa67201b49a50f43b35cd3f3204d13a6a544",
6
+ "branch": "bot/1524-path-eq-1016"
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/glob_speed_gitignore_test.py -x -q -s",
3
+ "ran_at": 1792155745,
4
+ "exit_code": 0,
5
+ "commit": "fb06f3cf1239d66c0cc2fff6a297448cbd12365a",
6
+ "branch": "bot/1532-gitignore-fastest-bar-1016"
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run python -m pytest tests/e2e/frontmatter_parse_speed_test.py tests/e2e/jsonl_parse_speed_test.py tests/e2e/on_file_query_test.py tests/e2e/fanout_test.py tests/e2e/declared_table_name_test.py tests/e2e/query_contract_test.py tests/e2e/use_case_notebook_test.py tests/e2e/use_case_transcripts_test.py tests/e2e/sigint_interrupt_test.py -q -s",
3
+ "ran_at": 1792158472,
4
+ "exit_code": 0,
5
+ "commit": "4eaa7f0c26fa324fdb9b161e90fdb3fe22b8774f",
6
+ "branch": "bot/1534-fm-native-1016"
7
+ }
@@ -6,7 +6,7 @@ description = "Ephemeral SQL index over a local directory"
6
6
  # version stays for the binding crates (publish = false). The literal
7
7
  # intentionally lags the published version: putitoutthere rewrites it to
8
8
  # the planned release version at build time and never commits it back.
9
- version = "0.4.115"
9
+ version = "0.4.117"
10
10
  edition.workspace = true
11
11
  # Literal `license` (not `license.workspace = true`) because
12
12
  # putitoutthere's preflight check reads `[package].license` directly
@@ -312,6 +312,63 @@ impl ShapedRows {
312
312
  }
313
313
  }
314
314
 
315
+ /// [`Db::shape_rows`] against `columns`, the table's columns in DDL order,
316
+ /// so rows can be shaped off the connection's thread.
317
+ pub(crate) fn shape_json_rows(
318
+ table: &str,
319
+ columns: Vec<String>,
320
+ rows: Vec<JsonRow>,
321
+ strict: bool,
322
+ ) -> Result<ShapedRows> {
323
+ let mut cells = Vec::with_capacity(rows.len());
324
+ for row in rows {
325
+ if strict {
326
+ for (key, _) in &row.0 {
327
+ validate_identifier(key)?;
328
+ }
329
+ let extra: Vec<&str> = row
330
+ .0
331
+ .iter()
332
+ .map(|(key, _)| &**key)
333
+ .filter(|key| !columns.iter().any(|c| c == key))
334
+ .collect();
335
+ if !extra.is_empty() {
336
+ return Err(DbError::SchemaMismatch(format!(
337
+ "extra columns not in table {}: {}",
338
+ table,
339
+ extra.join(", ")
340
+ )));
341
+ }
342
+ let missing: Vec<&str> = columns
343
+ .iter()
344
+ .map(String::as_str)
345
+ .filter(|c| !row.0.iter().any(|(key, _)| **key == **c))
346
+ .collect();
347
+ if !missing.is_empty() {
348
+ return Err(DbError::SchemaMismatch(format!(
349
+ "missing columns for table {}: {}",
350
+ table,
351
+ missing.join(", ")
352
+ )));
353
+ }
354
+ }
355
+ let in_order = row.0.len() == columns.len()
356
+ && row.0.iter().zip(&columns).all(|((key, _), c)| **key == **c);
357
+ if in_order {
358
+ cells.push(row.0.into_iter().map(|(_, v)| json_into_value(v)).collect());
359
+ continue;
360
+ }
361
+ let mut shaped = vec![Value::Null; columns.len()];
362
+ for (key, value) in row.0 {
363
+ if let Some(i) = columns.iter().position(|c| **c == *key) {
364
+ shaped[i] = json_into_value(value);
365
+ }
366
+ }
367
+ cells.push(shaped);
368
+ }
369
+ Ok(ShapedRows { columns, cells })
370
+ }
371
+
315
372
  fn json_into_value(value: serde_json::Value) -> Value {
316
373
  match value {
317
374
  serde_json::Value::String(s) => Value::Text(s),
@@ -566,9 +623,10 @@ impl Db {
566
623
  /// Return the column names declared in `table`'s DDL.
567
624
  pub fn get_table_columns(&self, table: &str) -> Result<Vec<String>> {
568
625
  validate_identifier(table)?;
569
- let mut stmt = self
570
- .conn
571
- .prepare(&format!("PRAGMA table_info({})", table))?;
626
+ let mut stmt = self.conn.prepare(&format!(
627
+ "PRAGMA table_info({})",
628
+ crate::sql_literal::quote_identifier(table)
629
+ ))?;
572
630
  let columns: Vec<String> = stmt
573
631
  .query_map([], |row| row.get::<_, String>(1))?
574
632
  .filter_map(|r| r.ok())
@@ -714,54 +772,7 @@ impl Db {
714
772
  /// a less-actionable "extra columns" mismatch. Every row is shaped before
715
773
  /// any is returned, so a hook that got one row wrong fails as a unit.
716
774
  pub fn shape_rows(&self, table: &str, rows: Vec<JsonRow>, strict: bool) -> Result<ShapedRows> {
717
- let columns = self.get_table_columns(table)?;
718
- let mut cells = Vec::with_capacity(rows.len());
719
- for row in rows {
720
- if strict {
721
- for (key, _) in &row.0 {
722
- validate_identifier(key)?;
723
- }
724
- let extra: Vec<&str> = row
725
- .0
726
- .iter()
727
- .map(|(key, _)| &**key)
728
- .filter(|key| !columns.iter().any(|c| c == key))
729
- .collect();
730
- if !extra.is_empty() {
731
- return Err(DbError::SchemaMismatch(format!(
732
- "extra columns not in table {}: {}",
733
- table,
734
- extra.join(", ")
735
- )));
736
- }
737
- let missing: Vec<&str> = columns
738
- .iter()
739
- .map(String::as_str)
740
- .filter(|c| !row.0.iter().any(|(key, _)| **key == **c))
741
- .collect();
742
- if !missing.is_empty() {
743
- return Err(DbError::SchemaMismatch(format!(
744
- "missing columns for table {}: {}",
745
- table,
746
- missing.join(", ")
747
- )));
748
- }
749
- }
750
- let in_order = row.0.len() == columns.len()
751
- && row.0.iter().zip(&columns).all(|((key, _), c)| **key == **c);
752
- if in_order {
753
- cells.push(row.0.into_iter().map(|(_, v)| json_into_value(v)).collect());
754
- continue;
755
- }
756
- let mut shaped = vec![Value::Null; columns.len()];
757
- for (key, value) in row.0 {
758
- if let Some(i) = columns.iter().position(|c| **c == *key) {
759
- shaped[i] = json_into_value(value);
760
- }
761
- }
762
- cells.push(shaped);
763
- }
764
- Ok(ShapedRows { columns, cells })
775
+ shape_json_rows(table, self.get_table_columns(table)?, rows, strict)
765
776
  }
766
777
 
767
778
  /// Insert every row of `rows` under `file_path`, in order, through one
@@ -2476,6 +2487,15 @@ mod tests {
2476
2487
  assert!(result.is_err());
2477
2488
  }
2478
2489
 
2490
+ #[test]
2491
+ fn get_table_columns_reads_a_table_named_by_a_keyword() {
2492
+ let db = Db::new().unwrap();
2493
+ db.create_table("order", "CREATE TABLE \"order\" (name TEXT)")
2494
+ .unwrap();
2495
+ let cols = db.get_table_columns("order").unwrap();
2496
+ assert!(cols.contains(&"name".to_string()), "{cols:?}");
2497
+ }
2498
+
2479
2499
  #[test]
2480
2500
  fn get_table_columns_nonexistent_table_returns_empty() {
2481
2501
  let db = Db::new().unwrap();
@@ -1288,20 +1288,11 @@ impl DirSQL {
1288
1288
  // (and that pass the racy-window check) are trusted instead of
1289
1289
  // re-parsed.
1290
1290
  let (scanned_files, deleted) = match &persist_ctx {
1291
- None => {
1292
- let files = scanned
1293
- .into_iter()
1294
- .map(|found| ScannedFile {
1295
- abs_path: found.path,
1296
- rel_path: found.rel_path,
1297
- table_name: found.table_name,
1298
- stat: None,
1299
- trusted: false,
1300
- })
1301
- .collect();
1302
- (files, Vec::new())
1291
+ None => (Scanned::Found(scanned), Vec::new()),
1292
+ Some(ctx) => {
1293
+ let (files, deleted) = reconcile_scan(scanned, ctx, &RealFs)?;
1294
+ (Scanned::Files(files), deleted)
1303
1295
  }
1304
- Some(ctx) => reconcile_scan(scanned, ctx, &RealFs)?,
1305
1296
  };
1306
1297
 
1307
1298
  Ok(PreparedBuild {
@@ -1482,17 +1473,22 @@ impl DirSQL {
1482
1473
  let mut batch_files: HashMap<String, Vec<String>> = HashMap::new();
1483
1474
 
1484
1475
  // Grouping walks every scanned file, so it runs beside the early
1485
- // hooks' inserts instead of ahead of them.
1476
+ // hooks' inserts instead of ahead of them, and settles the early
1477
+ // tables' file lists there too.
1478
+ let early_tables: HashSet<String> = early.keys().cloned().collect();
1486
1479
  let (grouped, streamed) = std::thread::scope(|scope| {
1487
- let grouping = scope.spawn(|| group_scanned(scanned_files, &on_file_map));
1480
+ let grouping = scope.spawn(|| {
1481
+ group_scanned(scanned_files.into_files(), &on_file_map)
1482
+ .map(|(per_file, batches)| (per_file, split_streamed(batches, &early_tables)))
1483
+ });
1488
1484
  let streamed = stream_early(&db, early, &strict_map);
1489
1485
  (
1490
1486
  grouping.join().expect("grouping scanned files panicked"),
1491
1487
  streamed,
1492
1488
  )
1493
1489
  });
1494
- let streamed = streamed?;
1495
- let (per_file, batches) = grouped?;
1490
+ streamed?;
1491
+ let (per_file, (batches, streamed)) = grouped?;
1496
1492
 
1497
1493
  // The phase a user actually waits on: one `on_file` round trip per
1498
1494
  // file or per table, plus whatever the table's DDL triggers on insert.
@@ -1501,8 +1497,15 @@ impl DirSQL {
1501
1497
  + batches
1502
1498
  .iter()
1503
1499
  .map(|(_, _, files)| files.len())
1504
- .sum::<usize>()) as u64;
1500
+ .sum::<usize>()
1501
+ + streamed.iter().map(|(_, rel)| rel.len()).sum::<usize>())
1502
+ as u64;
1505
1503
  let mut done: u64 = 0;
1504
+ for (table_name, rel_paths) in streamed {
1505
+ progress.update(done, Some(total_files));
1506
+ done += rel_paths.len() as u64;
1507
+ batch_files.insert(table_name, rel_paths);
1508
+ }
1506
1509
  for (
1507
1510
  ScannedFile {
1508
1511
  rel_path,
@@ -1580,7 +1583,7 @@ impl DirSQL {
1580
1583
  let current = persist_ready.as_ref().is_some_and(|(deleted, _, _)| {
1581
1584
  files.iter().all(|f| f.trusted) && !deleted.iter().any(|(_, t)| *t == table_name)
1582
1585
  });
1583
- if !current && !streamed.contains(&table_name) {
1586
+ if !current {
1584
1587
  let table_root = anchors.of(&table_name);
1585
1588
  let production = start_hook(hook, abs_paths.into_iter());
1586
1589
  let outcome = stream_table_rows(&db, &table_name, production, strict)
@@ -2004,6 +2007,33 @@ pub struct ScannedFile {
2004
2007
  pub trusted: bool,
2005
2008
  }
2006
2009
 
2010
+ /// The files the startup scan found: as the walk found them, or already
2011
+ /// reconciled against the persistent cache.
2012
+ enum Scanned {
2013
+ Found(Vec<Found>),
2014
+ Files(Vec<ScannedFile>),
2015
+ }
2016
+
2017
+ impl Scanned {
2018
+ /// Every file as a [`ScannedFile`]. A fresh walk's are made here rather
2019
+ /// than in prepare, so the copy runs off the thread that inserts rows.
2020
+ fn into_files(self) -> Vec<ScannedFile> {
2021
+ match self {
2022
+ Self::Found(found) => found
2023
+ .into_iter()
2024
+ .map(|found| ScannedFile {
2025
+ abs_path: found.path,
2026
+ rel_path: found.rel_path,
2027
+ table_name: found.table_name,
2028
+ stat: None,
2029
+ trusted: false,
2030
+ })
2031
+ .collect(),
2032
+ Self::Files(files) => files,
2033
+ }
2034
+ }
2035
+ }
2036
+
2007
2037
  /// Intermediate state produced by [`DirSQL::prepare_resolved`] and consumed
2008
2038
  /// by [`DirSQL::finish_build`]. Opaque on purpose; fields are only visible
2009
2039
  /// to the in-workspace bindings.
@@ -2020,7 +2050,7 @@ pub struct PreparedBuild {
2020
2050
  /// The configured skip rules, carried through so path-table scans apply
2021
2051
  /// the same ones declared tables do.
2022
2052
  ignore: Vec<String>,
2023
- scanned_files: Vec<ScannedFile>,
2053
+ scanned_files: Scanned,
2024
2054
  /// Per-table hooks already running over the paths the scan found, by table.
2025
2055
  early: HashMap<String, Production>,
2026
2056
  persist: Option<PreparedPersist>,
@@ -2437,9 +2467,10 @@ fn collect_table_rows(
2437
2467
 
2438
2468
  /// Replace a per-table hook's rows under [`BATCH_OWNER`], storing each chunk
2439
2469
  /// the hook emits while the hook, on its own thread, goes on producing the
2440
- /// next. The caller's open transaction keeps a failure from being seen: the
2441
- /// outer `Err` is SQLite's, the inner one the hook's or a row's. A hook
2442
- /// failure outranks a row that failed to shape.
2470
+ /// next. Chunks are shaped on a thread of their own, in order, so shaping one
2471
+ /// overlaps inserting the last. The caller's open transaction keeps a failure
2472
+ /// from being seen: the outer `Err` is SQLite's, the inner one the hook's or a
2473
+ /// row's. A hook failure outranks a row that failed to shape.
2443
2474
  fn stream_table_rows(
2444
2475
  db: &Db,
2445
2476
  table: &str,
@@ -2447,17 +2478,32 @@ fn stream_table_rows(
2447
2478
  strict: bool,
2448
2479
  ) -> db::Result<std::result::Result<(), String>> {
2449
2480
  db.delete_rows_by_file(table, BATCH_OWNER)?;
2450
- let mut shaped = Ok(());
2451
- for chunk in production.chunks {
2452
- if shaped.is_err() {
2453
- continue;
2481
+ let columns = db.get_table_columns(table)?;
2482
+ let Production { chunks, handle } = production;
2483
+ let (shaped_tx, shaped_rx) = std::sync::mpsc::channel();
2484
+ let shaper = std::thread::spawn({
2485
+ let table = table.to_string();
2486
+ move || {
2487
+ for chunk in chunks {
2488
+ let shaped = db::shape_json_rows(&table, columns.clone(), chunk, strict);
2489
+ if shaped_tx.send(shaped).is_err() {
2490
+ return;
2491
+ }
2492
+ }
2454
2493
  }
2455
- match db.shape_rows(table, chunk, strict) {
2494
+ });
2495
+ let mut shaped = Ok(());
2496
+ for rows in shaped_rx {
2497
+ match rows {
2456
2498
  Ok(rows) => db.insert_rows(table, &rows, BATCH_OWNER)?,
2457
- Err(e) => shaped = Err(e.to_string()),
2499
+ Err(e) => {
2500
+ shaped = Err(e.to_string());
2501
+ break;
2502
+ }
2458
2503
  }
2459
2504
  }
2460
- let produced = production.handle.join().expect("per-table hook panicked");
2505
+ shaper.join().expect("shaping a hook's rows panicked");
2506
+ let produced = handle.join().expect("per-table hook panicked");
2461
2507
  Ok(produced.and(shaped))
2462
2508
  }
2463
2509
 
@@ -2591,14 +2637,12 @@ fn group_scanned(
2591
2637
  Ok((per_file, batches))
2592
2638
  }
2593
2639
 
2594
- /// Insert the rows of every hook started before the scan, returning the
2595
- /// tables streamed.
2640
+ /// Insert the rows of every hook started before the scan.
2596
2641
  fn stream_early(
2597
2642
  db: &Db,
2598
2643
  early: HashMap<String, Production>,
2599
2644
  strict_map: &HashMap<String, bool>,
2600
- ) -> Result<HashSet<String>> {
2601
- let mut streamed = HashSet::new();
2645
+ ) -> Result<()> {
2602
2646
  for (table_name, production) in early {
2603
2647
  let strict = *strict_map.get(&table_name).unwrap_or(&false);
2604
2648
  if let Err(message) =
@@ -2609,9 +2653,30 @@ fn stream_early(
2609
2653
  message,
2610
2654
  });
2611
2655
  }
2612
- streamed.insert(table_name);
2613
2656
  }
2614
- Ok(streamed)
2657
+ Ok(())
2658
+ }
2659
+
2660
+ /// Split off the batches of tables whose hooks already ran, keeping only
2661
+ /// each one's relative paths in scan order.
2662
+ #[allow(clippy::type_complexity)]
2663
+ fn split_streamed(
2664
+ batches: Vec<(String, Arc<OnFilesFn>, Vec<ScannedFile>)>,
2665
+ streamed: &HashSet<String>,
2666
+ ) -> (
2667
+ Vec<(String, Arc<OnFilesFn>, Vec<ScannedFile>)>,
2668
+ Vec<(String, Vec<String>)>,
2669
+ ) {
2670
+ let mut rest = Vec::new();
2671
+ let mut done = Vec::new();
2672
+ for (table_name, hook, mut files) in batches {
2673
+ if streamed.contains(&table_name) {
2674
+ done.push((table_name, batch_paths(&mut files, false).0));
2675
+ } else {
2676
+ rest.push((table_name, hook, files));
2677
+ }
2678
+ }
2679
+ (rest, done)
2615
2680
  }
2616
2681
 
2617
2682
  fn batch_paths(files: &mut [ScannedFile], keep_rel: bool) -> (Vec<String>, Vec<PathBuf>) {
@@ -3154,7 +3219,7 @@ mod internal_tests {
3154
3219
  0,
3155
3220
  "zero tables can match nothing, so the startup walk is pure waste"
3156
3221
  );
3157
- assert!(prepared.scanned_files.is_empty());
3222
+ assert!(prepared.scanned_files.into_files().is_empty());
3158
3223
  }
3159
3224
 
3160
3225
  /// The skip is narrow: one declared table still walks, and prepare still
@@ -3175,10 +3240,11 @@ mod internal_tests {
3175
3240
  .unwrap();
3176
3241
 
3177
3242
  assert_eq!(scan.calls.get(), 1);
3178
- let found: Vec<&str> = prepared
3243
+ let found: Vec<String> = prepared
3179
3244
  .scanned_files
3180
- .iter()
3181
- .map(|f| f.rel_path.as_str())
3245
+ .into_files()
3246
+ .into_iter()
3247
+ .map(|f| f.rel_path)
3182
3248
  .collect();
3183
3249
  assert_eq!(found, vec!["a.txt"]);
3184
3250
  }
@@ -3295,13 +3361,13 @@ mod internal_tests {
3295
3361
  functions: Vec::new(),
3296
3362
  groups: Vec::new(),
3297
3363
  anchors: TableAnchors::at_root(dir.path()),
3298
- scanned_files: vec![ScannedFile {
3364
+ scanned_files: Scanned::Files(vec![ScannedFile {
3299
3365
  abs_path: PathBuf::new(),
3300
3366
  rel_path: "ghost.txt".into(),
3301
3367
  table_name: "ghost".into(),
3302
3368
  stat: None,
3303
3369
  trusted: false,
3304
- }],
3370
+ }]),
3305
3371
  early: HashMap::new(),
3306
3372
  poll_interval: DEFAULT_POLL_INTERVAL,
3307
3373
  persist: None,
@@ -5367,13 +5433,15 @@ mod internal_tests {
5367
5433
  scanned_files: Vec<ScannedFile>,
5368
5434
  persist: Option<PreparedPersist>,
5369
5435
  ) -> PreparedBuild {
5370
- let scanned_files = scanned_files
5371
- .into_iter()
5372
- .map(|mut file| {
5373
- file.abs_path = root.join(&file.rel_path);
5374
- file
5375
- })
5376
- .collect();
5436
+ let scanned_files = Scanned::Files(
5437
+ scanned_files
5438
+ .into_iter()
5439
+ .map(|mut file| {
5440
+ file.abs_path = root.join(&file.rel_path);
5441
+ file
5442
+ })
5443
+ .collect(),
5444
+ );
5377
5445
  PreparedBuild {
5378
5446
  ignore: Vec::new(),
5379
5447
  root: root.to_path_buf(),
@@ -5710,6 +5778,48 @@ mod internal_tests {
5710
5778
  }
5711
5779
  }
5712
5780
 
5781
+ #[test]
5782
+ fn finish_build_counts_the_files_of_a_hook_started_before_the_scan_toward_the_ingest_total() {
5783
+ let dir = TempDir::new().unwrap();
5784
+ let out = Captured::default();
5785
+ let progress = Progress::new(
5786
+ "indexing",
5787
+ "indexed",
5788
+ "files",
5789
+ Box::new(out.clone()),
5790
+ Box::new(progress::SystemClock),
5791
+ progress::Mode::Always,
5792
+ false,
5793
+ );
5794
+ let notes = Table::new("notes", "CREATE TABLE notes (name TEXT)", "*.md", |_| {
5795
+ Vec::new()
5796
+ });
5797
+ let (items, _) = recording_per_table("items", "*.txt");
5798
+ let (feeds, early) = start_per_table_hooks(std::slice::from_ref(&items));
5799
+ for name in ["a.txt", "b.txt"] {
5800
+ feeds["items"].send(dir.path().join(name)).unwrap();
5801
+ }
5802
+ drop(feeds);
5803
+ let scanned = vec![
5804
+ scanned("a.txt", "items", false),
5805
+ scanned("b.txt", "items", false),
5806
+ scanned("n.md", "notes", false),
5807
+ ];
5808
+ let mut prepared = prepared_build(dir.path(), vec![notes, items], scanned, None);
5809
+ prepared.early = early;
5810
+
5811
+ DirSQL::finish_build_with_fs(prepared, Arc::new(FakeFs::default()), progress).unwrap();
5812
+
5813
+ let text = out.text();
5814
+ for line in [
5815
+ "dirsql: indexing 0/3 files (0%)",
5816
+ "dirsql: indexing 2/3 files (66%)",
5817
+ "dirsql: indexed 3 files in",
5818
+ ] {
5819
+ assert!(text.contains(line), "missing {line:?} in {text:?}");
5820
+ }
5821
+ }
5822
+
5713
5823
  #[test]
5714
5824
  fn finish_build_skips_a_per_file_hook_for_a_file_the_cache_holds() {
5715
5825
  let dir = TempDir::new().unwrap();