dirsql 0.4.129__tar.gz → 0.4.131__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 (493) hide show
  1. {dirsql-0.4.129 → dirsql-0.4.131}/Cargo.lock +2 -2
  2. {dirsql-0.4.129 → dirsql-0.4.131}/PKG-INFO +1 -1
  3. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/Cargo.toml +1 -1
  4. dirsql-0.4.131/packages/python/e2e-attestations/bot-1475-prefix-speed-1016.json +7 -0
  5. dirsql-0.4.131/packages/python/e2e-attestations/bot-1560-scan-insert-1102.json +7 -0
  6. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/Cargo.toml +1 -1
  7. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/run.rs +32 -1
  8. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/db.rs +1 -1
  9. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/lib.rs +329 -55
  10. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/tree_walk.rs +24 -3
  11. {dirsql-0.4.129 → dirsql-0.4.131}/Cargo.toml +0 -0
  12. {dirsql-0.4.129 → dirsql-0.4.131}/README.md +0 -0
  13. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/__init__.py +0 -0
  14. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/_async.py +0 -0
  15. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/_dirsql.pyi +0 -0
  16. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/cli/__init__.py +0 -0
  17. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/cli/discover_plugins/__init__.py +0 -0
  18. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
  19. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
  20. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
  21. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
  22. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/cli/main.py +0 -0
  23. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/cli/resolve_config_extensions.py +0 -0
  24. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/plan_entry_path.py +0 -0
  25. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/py.typed +0 -0
  26. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/read_config.py +0 -0
  27. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/resolve_configs_extension_specs.py +0 -0
  28. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/resolve_extension.py +0 -0
  29. {dirsql-0.4.129 → dirsql-0.4.131}/dirsql/resolve_package.py +0 -0
  30. {dirsql-0.4.129 → dirsql-0.4.131}/docs/.claude/CLAUDE.md +0 -0
  31. {dirsql-0.4.129 → dirsql-0.4.131}/docs/.vitepress/config.ts +0 -0
  32. {dirsql-0.4.129 → dirsql-0.4.131}/docs/.vitepress/theme/index.ts +0 -0
  33. {dirsql-0.4.129 → dirsql-0.4.131}/docs/.vitepress/theme/lang.ts +0 -0
  34. {dirsql-0.4.129 → dirsql-0.4.131}/docs/AGENTS.md +0 -0
  35. {dirsql-0.4.129 → dirsql-0.4.131}/docs/context/.gitattributes +0 -0
  36. {dirsql-0.4.129 → dirsql-0.4.131}/docs/context/recipes.md +0 -0
  37. {dirsql-0.4.129 → dirsql-0.4.131}/docs/context/troubleshooting.md +0 -0
  38. {dirsql-0.4.129 → dirsql-0.4.131}/docs/context/usage.md +0 -0
  39. {dirsql-0.4.129 → dirsql-0.4.131}/docs/explanation.md +0 -0
  40. {dirsql-0.4.129 → dirsql-0.4.131}/docs/getting-started.md +0 -0
  41. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/agent-skill.md +0 -0
  42. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/columns-from-paths.md +0 -0
  43. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/define-tables.md +0 -0
  44. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/embed.md +0 -0
  45. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/extract-from-contents.md +0 -0
  46. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/load-extension.md +0 -0
  47. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/parse-files-into-columns.md +0 -0
  48. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/persist.md +0 -0
  49. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/query-json.md +0 -0
  50. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/query-without-config.md +0 -0
  51. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/react-to-changes.md +0 -0
  52. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/search-by-meaning.md +0 -0
  53. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/search-indexes.md +0 -0
  54. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/skip-files.md +0 -0
  55. {dirsql-0.4.129 → dirsql-0.4.131}/docs/howto/write-a-plugin.md +0 -0
  56. {dirsql-0.4.129 → dirsql-0.4.131}/docs/index.md +0 -0
  57. {dirsql-0.4.129 → dirsql-0.4.131}/docs/package.json +0 -0
  58. {dirsql-0.4.129 → dirsql-0.4.131}/docs/plugins.md +0 -0
  59. {dirsql-0.4.129 → dirsql-0.4.131}/docs/pnpm-lock.yaml +0 -0
  60. {dirsql-0.4.129 → dirsql-0.4.131}/docs/pnpm-workspace.yaml +0 -0
  61. {dirsql-0.4.129 → dirsql-0.4.131}/docs/reference/cli.md +0 -0
  62. {dirsql-0.4.129 → dirsql-0.4.131}/docs/reference/columns.md +0 -0
  63. {dirsql-0.4.129 → dirsql-0.4.131}/docs/reference/config.md +0 -0
  64. {dirsql-0.4.129 → dirsql-0.4.131}/docs/reference/glob.md +0 -0
  65. {dirsql-0.4.129 → dirsql-0.4.131}/docs/reference/hooks.md +0 -0
  66. {dirsql-0.4.129 → dirsql-0.4.131}/docs/reference/http-api.md +0 -0
  67. {dirsql-0.4.129 → dirsql-0.4.131}/docs/reference/path-tables.md +0 -0
  68. {dirsql-0.4.129 → dirsql-0.4.131}/docs/reference/sdk.md +0 -0
  69. {dirsql-0.4.129 → dirsql-0.4.131}/docs/speed.json +0 -0
  70. {dirsql-0.4.129 → dirsql-0.4.131}/docs/speed.md +0 -0
  71. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/CHANGELOG.md +0 -0
  72. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/MIGRATIONS.md +0 -0
  73. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/README.md +0 -0
  74. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  75. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
  76. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  77. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
  78. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  79. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
  80. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
  81. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
  82. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  83. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
  84. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
  85. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
  86. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
  87. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
  88. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
  89. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
  90. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-08-04-cli-in-process.md +0 -0
  91. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-08-20-curtaincall-dev-dependency.md +0 -0
  92. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-08-20-declared-table-name.md +0 -0
  93. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-04-config-paths-from-argv-module.md +0 -0
  94. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-05-config-extension-loader-split.md +0 -0
  95. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-05-resolve-config-extensions-split.md +0 -0
  96. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-05-resolve-extension-split.md +0 -0
  97. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-09-launcher-config-path-scan.md +0 -0
  98. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-17-extension-resolution-via-core.md +0 -0
  99. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-18-export-scan-failure.md +0 -0
  100. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-18-flatten-row-event-in-core.md +0 -0
  101. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-18-programmatic-extension-plan.md +0 -0
  102. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  103. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  104. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-02-readme-docs-host.md +0 -0
  105. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  106. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-03-path-table-directory-one-level.md +0 -0
  107. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  108. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  109. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-05-cli-context.md +0 -0
  110. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-05-gitignore-requires-repo.md +0 -0
  111. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-05-path-table-node-modules-named.md +0 -0
  112. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-05-path-table-symlinks.md +0 -0
  113. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-05-path-table-trailing-slash.md +0 -0
  114. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-05-unbalanced-brackets-literal.md +0 -0
  115. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-config-braces.md +0 -0
  116. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-config-directory.md +0 -0
  117. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-config-dotnames.md +0 -0
  118. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-config-gitignore.md +0 -0
  119. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
  120. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-config-links.md +0 -0
  121. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-one-glob-compiler.md +0 -0
  122. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-plugin-no-default-records.md +0 -0
  123. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-watch-broadcast.md +0 -0
  124. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-06-zero-match-config-table-warning.md +0 -0
  125. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-bracket-slash-literal.md +0 -0
  126. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-dotdot-and-double-slashes.md +0 -0
  127. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-dotdot-as-written.md +0 -0
  128. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-glob-walks-node-modules.md +0 -0
  129. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-literal-gitignore.md +0 -0
  130. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-on-file-ndjson.md +0 -0
  131. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-parallel-hooks.md +0 -0
  132. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-persist-cache-outside-root.md +0 -0
  133. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-posix-classes-unicode.md +0 -0
  134. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-07-spread-few-large-files.md +0 -0
  135. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-08-small-walks-stay-on-one-thread.md +0 -0
  136. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-10-08-watch-requires-named-table.md +0 -0
  137. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-11-02-watch-dirs-created-mid-registration.md +0 -0
  138. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/2026-11-02-watch-live-on-return.md +0 -0
  139. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/changelog.d/README.md +0 -0
  140. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/conftest.py +0 -0
  141. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/.claude/CLAUDE.md +0 -0
  142. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/.vitepress/config.ts +0 -0
  143. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/.vitepress/theme/index.ts +0 -0
  144. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
  145. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/AGENTS.md +0 -0
  146. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/context/.gitattributes +0 -0
  147. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/context/recipes.md +0 -0
  148. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/context/troubleshooting.md +0 -0
  149. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/context/usage.md +0 -0
  150. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/explanation.md +0 -0
  151. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/getting-started.md +0 -0
  152. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/agent-skill.md +0 -0
  153. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/columns-from-paths.md +0 -0
  154. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/define-tables.md +0 -0
  155. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/embed.md +0 -0
  156. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/extract-from-contents.md +0 -0
  157. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/load-extension.md +0 -0
  158. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
  159. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/persist.md +0 -0
  160. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/query-json.md +0 -0
  161. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/query-without-config.md +0 -0
  162. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/react-to-changes.md +0 -0
  163. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/search-by-meaning.md +0 -0
  164. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/search-indexes.md +0 -0
  165. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/skip-files.md +0 -0
  166. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/howto/write-a-plugin.md +0 -0
  167. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/index.md +0 -0
  168. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/package.json +0 -0
  169. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/plugins.md +0 -0
  170. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/pnpm-lock.yaml +0 -0
  171. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/pnpm-workspace.yaml +0 -0
  172. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/reference/cli.md +0 -0
  173. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/reference/columns.md +0 -0
  174. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/reference/config.md +0 -0
  175. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/reference/glob.md +0 -0
  176. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/reference/hooks.md +0 -0
  177. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/reference/http-api.md +0 -0
  178. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/reference/path-tables.md +0 -0
  179. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/reference/sdk.md +0 -0
  180. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/speed.json +0 -0
  181. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/docs/speed.md +0 -0
  182. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1334-listing-exemptions.json +0 -0
  183. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1397-watch-broadcast.json +0 -0
  184. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1398-inotify-error.json +0 -0
  185. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1399-server-cors.json +0 -0
  186. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1401-watch-scope.json +0 -0
  187. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1406-watch-no-tables-1008.json +0 -0
  188. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1407-child-place-depth.json +0 -0
  189. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1414-stat-speed.json +0 -0
  190. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1415-server-speed.json +0 -0
  191. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1416-watch-speed-1008.json +0 -0
  192. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1418-node-modules.json +0 -0
  193. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1419-dotdot-slashes.json +0 -0
  194. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1420-bracket-slash.json +0 -0
  195. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1421-posix-unicode.json +0 -0
  196. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1422-literal-gitignore.json +0 -0
  197. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1426-walk-spawn-threshold-1008.json +0 -0
  198. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1428-ndjson-hooks.json +0 -0
  199. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1429-parallel-hooks.json +0 -0
  200. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1430-dotdot-as-written.json +0 -0
  201. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1431-persist-cache-dir.json +0 -0
  202. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1437-test-cache-isolation.json +0 -0
  203. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1440-fix-main-build.json +0 -0
  204. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1448-wildcard-ignored-prefix.json +0 -0
  205. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1451-named-dir-never-hidden.json +0 -0
  206. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1454-split-few-files.json +0 -0
  207. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1457-incremental-refresh-1008.json +0 -0
  208. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1459-rescan-on-overflow-1008.json +0 -0
  209. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1461-chunked-read-1016.json +0 -0
  210. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1461-row-footprint-1008.json +0 -0
  211. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1461-step3-1020.json +0 -0
  212. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1461-wide-read-1015.json +0 -0
  213. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1462-paired-speed-harness-1008.json +0 -0
  214. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1464-fastest-native-1008.json +0 -0
  215. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1469-ci-speed-sanity-1009.json +0 -0
  216. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1470-perf-suite-1009.json +0 -0
  217. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1470-speed-page-1011.json +0 -0
  218. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1471-one-level-restore-1102.json +0 -0
  219. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1474-vtab-speed-1014.json +0 -0
  220. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1475-rowpath-1016.json +0 -0
  221. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1477-onelevel-speed-1015.json +0 -0
  222. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1477-onelevel-speed-1016.json +0 -0
  223. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1478-perdir-walk-1020.json +0 -0
  224. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1480-matcher-speed-1015.json +0 -0
  225. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1481-gitrepo-speed-1015.json +0 -0
  226. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1482-docs-fastest-bar-1102.json +0 -0
  227. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1483-fm-speed-1015.json +0 -0
  228. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1484-jsonl-speed-1015.json +0 -0
  229. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1487-frontend-query-1011.json +0 -0
  230. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1488-frontend-metadata-1011.json +0 -0
  231. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1489-frontend-browse-1013.json +0 -0
  232. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1503-bench-watch-1011.json +0 -0
  233. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1504-bench-names-1011.json +0 -0
  234. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1514-watch-rerun-inline-1015.json +0 -0
  235. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1524-path-eq-1016.json +0 -0
  236. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1526-main-red-1016.json +0 -0
  237. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1532-gitignore-fastest-bar-1016.json +0 -0
  238. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1534-fm-native-1016.json +0 -0
  239. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1534-fm-native-1102.json +0 -0
  240. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1538-onfile-order-1019.json +0 -0
  241. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1540-update-in-place-1019.json +0 -0
  242. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1541-defer-fk-1019.json +0 -0
  243. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1544-perfile-update-1020.json +0 -0
  244. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1552-watch-gap-1102.json +0 -0
  245. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1557-watch-rename-1102.json +0 -0
  246. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1562-hook-savepoint-1102.json +0 -0
  247. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-1562-watch-speed-1102.json +0 -0
  248. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-fix-main-place-depth-20261007.json +0 -0
  249. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-issue-1486-frontend-20261009.json +0 -0
  250. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-speed-gap-childpath-1011.json +0 -0
  251. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-speed-parse-overlap-1011.json +0 -0
  252. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-speed-parse-paths-1009.json +0 -0
  253. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-speed-parse-pragmas-1011.json +0 -0
  254. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-speed-sql-valueref-1013.json +0 -0
  255. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-speed-walk-components-1011.json +0 -0
  256. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-speed-walk-rowpath-1011.json +0 -0
  257. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-speed-walk-rows-1013.json +0 -0
  258. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/bot-speed-walk-sched-1009.json +0 -0
  259. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/cc-keen-knuth-f11gyq.json +0 -0
  260. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1056-py-ofpf9.json +0 -0
  261. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1066-p1-resolve-extension.json +0 -0
  262. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1078-argv-config-paths-core.json +0 -0
  263. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1079-p2-resolve-config-extensions.json +0 -0
  264. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1080-share-vtab-scaffolding.json +0 -0
  265. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1081-indicatif-progress.json +0 -0
  266. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1096-watch-moved-dir.json +0 -0
  267. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1109-watch-moved-out.json +0 -0
  268. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1119-ext-plan.json +0 -0
  269. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1120-py-ext.json +0 -0
  270. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1122-ext-cleanup.json +0 -0
  271. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1130-codec-crates.json +0 -0
  272. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1131-flatten-row-event.json +0 -0
  273. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1139-sse-flatten.json +0 -0
  274. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1140-scan-failure-export.json +0 -0
  275. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1148-clippy-all-targets.json +0 -0
  276. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1164-sigint-fatal.json +0 -0
  277. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1170-projection-order.json +0 -0
  278. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1172-on-file-path.json +0 -0
  279. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1173-py-projection-order.json +0 -0
  280. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1184-win-rel-paths.json +0 -0
  281. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1185-win-abs-table-names.json +0 -0
  282. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1186-win-test-harness.json +0 -0
  283. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1196-join-index.json +0 -0
  284. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1199-glob-prefix.json +0 -0
  285. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1201-single-walk.json +0 -0
  286. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1204-embed-batch.json +0 -0
  287. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1207-win-argv-quote.json +0 -0
  288. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1208-win-nonverbatim-paths.json +0 -0
  289. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1215-on-file-batch.json +0 -0
  290. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1216-on-file-cleanup.json +0 -0
  291. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1223-config-glob-rule.json +0 -0
  292. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1223-dir-one-level.json +0 -0
  293. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1225-plugin-no-default.json +0 -0
  294. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1226-stale-docs.json +0 -0
  295. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1232-anchor-plumbing.json +0 -0
  296. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1232-config-anchor.json +0 -0
  297. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1232-multi-watch.json +0 -0
  298. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1232-zero-match.json +0 -0
  299. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1238-parallel-walk.json +0 -0
  300. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1241-content-prefetch.json +0 -0
  301. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1243-ingest-perf.json +0 -0
  302. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1249-dotfiles.json +0 -0
  303. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1256-symlinks.json +0 -0
  304. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1257-trailing-slash.json +0 -0
  305. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1258-config-braces.json +0 -0
  306. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1258-config-directory.json +0 -0
  307. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1258-config-dotnames.json +0 -0
  308. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1258-config-gitignore.json +0 -0
  309. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1258-config-links.json +0 -0
  310. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1258-one-pattern.json +0 -0
  311. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1262-brace-literal.json +0 -0
  312. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1264-context.json +0 -0
  313. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1267-posix-classes.json +0 -0
  314. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1268-unbalanced-brackets.json +0 -0
  315. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1269-utf8-chars.json +0 -0
  316. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1271-node-modules-named.json +0 -0
  317. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1272-ancestor-gitignore.json +0 -0
  318. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1273-walk-prune.json +0 -0
  319. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1285-ingest-fast.json +0 -0
  320. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1286-nested-repo.json +0 -0
  321. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1305-glob-speed.json +0 -0
  322. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1308-glob-speed.json +0 -0
  323. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1310-glob-speed.json +0 -0
  324. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1311-glob-speed.json +0 -0
  325. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1312-glob-speed.json +0 -0
  326. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1318-lazy-stat.json +0 -0
  327. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1320-walk-speed.json +0 -0
  328. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1322-walk-readdir.json +0 -0
  329. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1325-parallel-walk.json +0 -0
  330. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1326-stream-rows.json +0 -0
  331. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1330-python-dirsql-patch.json +0 -0
  332. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1330-python-extensions-patch.json +0 -0
  333. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1330-scanner-effects.json +0 -0
  334. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1330-scanner-gitignore.json +0 -0
  335. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1330-vtab-prefetch-flag.json +0 -0
  336. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1330-vtab-read.json +0 -0
  337. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-1351-dot-dirs.json +0 -0
  338. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-819-oneshot-timeout.json +0 -0
  339. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-827-unquote-doubled-quotes.json +0 -0
  340. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-epic-953-slice2-reedline.json +0 -0
  341. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-epic-953-slice3-format.json +0 -0
  342. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-epic-953-stacked-prs-x59wm3.json +0 -0
  343. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-github-issue-825-e4mhhp.json +0 -0
  344. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-issue-951-0eease.json +0 -0
  345. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-issue-962-0jjrfv.json +0 -0
  346. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-issue-986-red-test-e7sjrb.json +0 -0
  347. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-tackle-1034-cachesplit.json +0 -0
  348. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-tackle-1042-py12.json +0 -0
  349. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-tackle-956-xzen74.json +0 -0
  350. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6-worker-calls.json +0 -0
  351. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-tackle-957-lrm0z6.json +0 -0
  352. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/e2e-attestations/claude-tackle-975-n8mc2h.json +0 -0
  353. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
  354. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
  355. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
  356. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
  357. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
  358. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
  359. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
  360. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
  361. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-08-04-cli-in-process.md +0 -0
  362. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-08-20-declared-table-name.md +0 -0
  363. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-09-20-sigint-ends-a-run-in-progress.md +0 -0
  364. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-09-24-query-rows-in-projection-order.md +0 -0
  365. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-02-readme-docs-host.md +0 -0
  366. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-03-one-glob-rule-for-config-globs.md +0 -0
  367. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-03-path-table-directory-one-level.md +0 -0
  368. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-04-path-table-dotfiles-hidden.md +0 -0
  369. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-05-brace-groups-follow-bash.md +0 -0
  370. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-05-cli-context.md +0 -0
  371. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-05-gitignore-requires-repo.md +0 -0
  372. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-05-path-table-node-modules-named.md +0 -0
  373. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-05-path-table-symlinks.md +0 -0
  374. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-05-path-table-trailing-slash.md +0 -0
  375. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-05-unbalanced-brackets-literal.md +0 -0
  376. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-config-braces.md +0 -0
  377. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-config-directory.md +0 -0
  378. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-config-dotnames.md +0 -0
  379. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-config-gitignore.md +0 -0
  380. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-config-globs-anchor-at-the-config.md +0 -0
  381. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-config-links.md +0 -0
  382. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-one-glob-compiler.md +0 -0
  383. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-plugin-no-default-records.md +0 -0
  384. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-watch-broadcast.md +0 -0
  385. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-06-zero-match-config-table-warning.md +0 -0
  386. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-bracket-slash-literal.md +0 -0
  387. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-dotdot-and-double-slashes.md +0 -0
  388. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-dotdot-as-written.md +0 -0
  389. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-glob-walks-node-modules.md +0 -0
  390. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-literal-gitignore.md +0 -0
  391. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-on-file-ndjson.md +0 -0
  392. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-parallel-hooks.md +0 -0
  393. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-persist-cache-outside-root.md +0 -0
  394. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-posix-classes-unicode.md +0 -0
  395. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-07-spread-few-large-files.md +0 -0
  396. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-08-small-walks-stay-on-one-thread.md +0 -0
  397. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-10-08-watch-requires-named-table.md +0 -0
  398. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-11-02-watch-dirs-created-mid-registration.md +0 -0
  399. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/2026-11-02-watch-live-on-return.md +0 -0
  400. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/migrations.d/README.md +0 -0
  401. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/src/lib.rs +0 -0
  402. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/testing-conventions.toml +0 -0
  403. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/__init__.py +0 -0
  404. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/conftest.py +0 -0
  405. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/e2e/__init__.py +0 -0
  406. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/e2e/bench_report.py +0 -0
  407. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/e2e/bench_suite.py +0 -0
  408. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
  409. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
  410. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/e2e/speed_of_light.py +0 -0
  411. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/integration/__init__.py +0 -0
  412. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/integration/binding/__init__.py +0 -0
  413. {dirsql-0.4.129 → dirsql-0.4.131}/packages/python/tests/integration/hermetic/__init__.py +0 -0
  414. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/CHANGELOG.md +0 -0
  415. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/MIGRATIONS.md +0 -0
  416. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/README.md +0 -0
  417. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/benches/db_bench.rs +0 -0
  418. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/benches/differ_bench.rs +0 -0
  419. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/benches/matcher_bench.rs +0 -0
  420. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/benches/scanner_bench.rs +0 -0
  421. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/context/.gitattributes +0 -0
  422. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/context/recipes.md +0 -0
  423. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/context/troubleshooting.md +0 -0
  424. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/context/usage.md +0 -0
  425. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/explanation.md +0 -0
  426. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/getting-started.md +0 -0
  427. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/agent-skill.md +0 -0
  428. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/columns-from-paths.md +0 -0
  429. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/define-tables.md +0 -0
  430. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/embed.md +0 -0
  431. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/extract-from-contents.md +0 -0
  432. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/load-extension.md +0 -0
  433. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
  434. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/persist.md +0 -0
  435. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/query-json.md +0 -0
  436. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/query-without-config.md +0 -0
  437. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/react-to-changes.md +0 -0
  438. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/search-by-meaning.md +0 -0
  439. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/search-indexes.md +0 -0
  440. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/skip-files.md +0 -0
  441. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/howto/write-a-plugin.md +0 -0
  442. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/index.md +0 -0
  443. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/plugins.md +0 -0
  444. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/reference/cli.md +0 -0
  445. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/reference/columns.md +0 -0
  446. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/reference/config.md +0 -0
  447. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/reference/glob.md +0 -0
  448. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/reference/hooks.md +0 -0
  449. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/reference/http-api.md +0 -0
  450. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/reference/path-tables.md +0 -0
  451. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/reference/sdk.md +0 -0
  452. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/speed.json +0 -0
  453. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/docs/speed.md +0 -0
  454. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/bin/dirsql.rs +0 -0
  455. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/brace.rs +0 -0
  456. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/context.rs +0 -0
  457. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/execute.rs +0 -0
  458. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/frontend.html +0 -0
  459. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/frontend.js +0 -0
  460. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/init.rs +0 -0
  461. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/mod.rs +0 -0
  462. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/repl.rs +0 -0
  463. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/router.rs +0 -0
  464. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/serialize.rs +0 -0
  465. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/server.rs +0 -0
  466. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/cli/table.rs +0 -0
  467. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/command.rs +0 -0
  468. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/config.rs +0 -0
  469. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/default_config.toml +0 -0
  470. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/differ.rs +0 -0
  471. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/extension_resolution.rs +0 -0
  472. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/foreign_key.rs +0 -0
  473. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/functions.rs +0 -0
  474. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/gitignore_frame.rs +0 -0
  475. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/infer.rs +0 -0
  476. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/launcher.rs +0 -0
  477. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/listing.rs +0 -0
  478. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/matcher.rs +0 -0
  479. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/on_file.rs +0 -0
  480. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/parsed_vtab.rs +0 -0
  481. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/path_table.rs +0 -0
  482. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/per_thread.rs +0 -0
  483. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/persist.rs +0 -0
  484. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/posix_class.rs +0 -0
  485. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/progress.rs +0 -0
  486. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/row_event_flat.rs +0 -0
  487. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/row_stream.rs +0 -0
  488. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/scanner.rs +0 -0
  489. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/sql_literal.rs +0 -0
  490. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/vtab.rs +0 -0
  491. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/vtab_scaffold.rs +0 -0
  492. {dirsql-0.4.129 → dirsql-0.4.131}/packages/rust/src/watcher.rs +0 -0
  493. {dirsql-0.4.129 → dirsql-0.4.131}/pyproject.toml +0 -0
@@ -573,7 +573,7 @@ dependencies = [
573
573
 
574
574
  [[package]]
575
575
  name = "dirsql"
576
- version = "0.4.129"
576
+ version = "0.4.131"
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.129"
628
+ version = "0.4.131"
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.129
3
+ Version: 0.4.131
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.129"
7
+ version = "0.4.131"
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_dotfiles_test.py tests/e2e/glob_speed_gitignore_test.py tests/e2e/glob_speed_matchers_test.py tests/e2e/glob_speed_node_modules_test.py tests/e2e/glob_speed_one_level_test.py tests/e2e/glob_speed_recursive_test.py tests/e2e/glob_speed_symlink_test.py tests/e2e/stat_speed_test.py tests/e2e/frontmatter_parse_speed_test.py tests/e2e/jsonl_parse_speed_test.py tests/e2e/query_contract_test.py tests/e2e/fanout_test.py tests/e2e/repl_interactive_test.py tests/e2e/server_speed_test.py -q",
3
+ "ran_at": 1793763290,
4
+ "exit_code": 0,
5
+ "commit": "80d1da9e6e85a68d69a48840dc58f00a09775b11",
6
+ "branch": "bot/1475-prefix-speed-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/cli_version_test.py tests/e2e/declared_table_name_test.py tests/e2e/extension_package_test.py tests/e2e/fanout_test.py tests/e2e/interpret_removed_test.py tests/e2e/on_file_query_test.py tests/e2e/plugin_discovery_test.py tests/e2e/plugin_extension_discovery_test.py tests/e2e/query_contract_test.py tests/e2e/repl_interactive_test.py tests/e2e/sigint_interrupt_test.py tests/e2e/use_case_dossier_test.py tests/e2e/use_case_join_test.py tests/e2e/use_case_notebook_test.py tests/e2e/use_case_transcripts_test.py -q",
3
+ "ran_at": 1793710164,
4
+ "exit_code": 0,
5
+ "commit": "e68653bf196f55bbf2b6e5adfbe4d98daf65d866",
6
+ "branch": "bot/1560-scan-insert-1102"
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.129"
9
+ version = "0.4.131"
10
10
  edition.workspace = true
11
11
  # Literal `license` (not `license.workspace = true`) because
12
12
  # putitoutthere's preflight check reads `[package].license` directly
@@ -329,7 +329,13 @@ pub fn run_cli(argv: Vec<String>) -> i32 {
329
329
  }
330
330
  };
331
331
 
332
- let runtime = match tokio::runtime::Runtime::new() {
332
+ let runtime = match if serves(&cli) {
333
+ tokio::runtime::Runtime::new()
334
+ } else {
335
+ tokio::runtime::Builder::new_current_thread()
336
+ .enable_all()
337
+ .build()
338
+ } {
333
339
  Ok(runtime) => runtime,
334
340
  Err(err) => {
335
341
  eprintln!("dirsql: failed to start the async runtime: {err}");
@@ -352,6 +358,13 @@ pub fn run_cli(argv: Vec<String>) -> i32 {
352
358
  i32::from(code)
353
359
  }
354
360
 
361
+ /// Whether `cli` keeps serving, as the server and the REPL do, and so wants a
362
+ /// runtime with a worker per core; a one-shot command waits on one thing at a
363
+ /// time, and starting and stopping those workers is a cost it would only pay.
364
+ fn serves(cli: &Cli) -> bool {
365
+ matches!(cli.command, Some(Command::Server(_))) || (cli.command.is_none() && cli.sql.is_none())
366
+ }
367
+
355
368
  /// The default (no-subcommand) behavior. With SQL, run it as a one-shot query,
356
369
  /// exactly as `dirsql query "<sql>"` does. With no SQL, read statements until
357
370
  /// EOF instead: bare `dirsql` is a REPL over the current directory, prompted
@@ -679,6 +692,24 @@ mod tests {
679
692
  assert_eq!(query_body(" "), r#"{"sql":" "}"#);
680
693
  }
681
694
 
695
+ #[test]
696
+ fn the_server_and_the_repl_serve() {
697
+ let serving =
698
+ [&["dirsql", "server"][..], &["dirsql"]].map(|argv| serves(&Cli::parse_from(argv)));
699
+ assert_eq!(serving, [true, true]);
700
+ }
701
+
702
+ #[test]
703
+ fn one_shot_commands_do_not_serve() {
704
+ let serving = [
705
+ &["dirsql", "query", "SELECT 1"][..],
706
+ &["dirsql", "SELECT 1"],
707
+ &["dirsql", "context"],
708
+ ]
709
+ .map(|argv| serves(&Cli::parse_from(argv)));
710
+ assert_eq!(serving, [false, false, false]);
711
+ }
712
+
682
713
  fn query_args(argv: &[&str]) -> QueryArgs {
683
714
  match Cli::parse_from(argv).command {
684
715
  Some(Command::Query(args)) => args,
@@ -457,7 +457,7 @@ pub struct Db {
457
457
  path_table_ignore: Vec<String>,
458
458
  /// Whether a path-table scan respects `.gitignore` files. On by default;
459
459
  /// the CLI's `--no-ignore` turns it off.
460
- path_table_gitignore: bool,
460
+ pub(crate) path_table_gitignore: bool,
461
461
  /// When set (the CLI's `--on-file`), every path-table is minted over the
462
462
  /// parser instead of the stat columns: its rows and schema come from the
463
463
  /// command's output. `None` keeps the stat path-table behavior.
@@ -1345,10 +1345,10 @@ impl DirSQL {
1345
1345
  }
1346
1346
 
1347
1347
  /// Split-phase construction — part 1. Performs all I/O that is safe to run
1348
- /// off the host's main thread: validates DDL, compiles the matcher, walks
1349
- /// the directory, opens the persistent cache (when enabled) and decides
1350
- /// which files need re-parsing. Does **not** read file contents and does
1351
- /// **not** invoke `on_file`.
1348
+ /// off the host's main thread: compiles the matcher, walks the directory,
1349
+ /// opens the database, creates transient tables when possible, and decides
1350
+ /// which files need re-parsing. Does **not** read file contents or invoke
1351
+ /// `on_file`.
1352
1352
  ///
1353
1353
  /// Pair with [`finish_build`](Self::finish_build) to complete construction
1354
1354
  /// on a thread where the `on_file` callback can safely execute (e.g. the
@@ -1359,6 +1359,30 @@ impl DirSQL {
1359
1359
  }
1360
1360
 
1361
1361
  fn prepare_resolved_with(resolved: ResolvedBuild, scan: ScanFn<'_>) -> Result<PreparedBuild> {
1362
+ Self::prepare_resolved_with_db(resolved, scan, Db::new)
1363
+ }
1364
+
1365
+ fn prepare_resolved_with_db<F>(
1366
+ resolved: ResolvedBuild,
1367
+ scan: ScanFn<'_>,
1368
+ new_db: F,
1369
+ ) -> Result<PreparedBuild>
1370
+ where
1371
+ F: FnOnce() -> db::Result<Db> + Send,
1372
+ {
1373
+ Self::prepare_resolved_with_setup(resolved, scan, new_db, run_table_ddl)
1374
+ }
1375
+
1376
+ fn prepare_resolved_with_setup<F, D>(
1377
+ resolved: ResolvedBuild,
1378
+ scan: ScanFn<'_>,
1379
+ new_db: F,
1380
+ ddl: D,
1381
+ ) -> Result<PreparedBuild>
1382
+ where
1383
+ F: FnOnce() -> db::Result<Db> + Send,
1384
+ D: FnOnce(&Db, &[Table]) -> Result<Vec<String>> + Send,
1385
+ {
1362
1386
  let ResolvedBuild {
1363
1387
  root,
1364
1388
  tables,
@@ -1404,23 +1428,62 @@ impl DirSQL {
1404
1428
  } else {
1405
1429
  (HashMap::new(), Vec::new())
1406
1430
  };
1407
- let scanned = if table_names.is_empty() {
1408
- Vec::new()
1431
+ let (scanned, fresh_db) = if table_names.is_empty() {
1432
+ let fresh_db = if persist_ctx.is_none() {
1433
+ let mut db = new_db().map_err(map_db_error)?;
1434
+ configure_db_paths(
1435
+ &mut db,
1436
+ &root,
1437
+ &ignore,
1438
+ hint_legacy_files_table,
1439
+ path_table_parser.as_deref(),
1440
+ no_ignore,
1441
+ );
1442
+ Some((db, true, Vec::new()))
1443
+ } else {
1444
+ None
1445
+ };
1446
+ (Vec::new(), fresh_db)
1409
1447
  } else {
1410
- // The walk reports a running count rather than a fraction: it does
1411
- // not know how many files there are until it has found them all.
1412
- let mut progress = Progress::scanning();
1413
- let (scanned, seen) = scan_groups(&groups, scan, &mut progress, &mut |path, table| {
1414
- if let Some(feed) = feeds.get(table) {
1415
- let _ = feed.send(path.to_path_buf());
1448
+ std::thread::scope(|scope| {
1449
+ let db_task = persist_ctx.is_none().then(|| {
1450
+ scope.spawn(|| {
1451
+ let mut db = new_db().map_err(map_db_error)?;
1452
+ configure_db_paths(
1453
+ &mut db,
1454
+ &root,
1455
+ &ignore,
1456
+ hint_legacy_files_table,
1457
+ path_table_parser.as_deref(),
1458
+ no_ignore,
1459
+ );
1460
+ let ddl_ready = extensions.is_empty() && functions.is_empty();
1461
+ if ddl_ready {
1462
+ let warnings = ddl(&db, &tables)?;
1463
+ return Ok::<_, DirSqlError>((db, true, warnings));
1464
+ }
1465
+ Ok::<_, DirSqlError>((db, false, Vec::new()))
1466
+ })
1467
+ });
1468
+ // The walk reports a running count rather than a fraction: it does
1469
+ // not know how many files there are until it has found them all.
1470
+ let mut progress = Progress::scanning();
1471
+ let (scanned, seen) =
1472
+ scan_groups(&groups, scan, &mut progress, &mut |path, table| {
1473
+ if let Some(feed) = feeds.get(table) {
1474
+ let _ = feed.send(path.to_path_buf());
1475
+ }
1476
+ });
1477
+ drop(feeds);
1478
+ progress.finish(seen);
1479
+ for warning in empty_table_warnings(&tables, &anchors, &scanned) {
1480
+ eprintln!("{warning}");
1416
1481
  }
1417
- });
1418
- drop(feeds);
1419
- progress.finish(seen);
1420
- for warning in empty_table_warnings(&tables, &anchors, &scanned) {
1421
- eprintln!("{warning}");
1422
- }
1423
- scanned
1482
+ let fresh_db = db_task
1483
+ .map(|task| task.join().expect("database creation panicked"))
1484
+ .transpose()?;
1485
+ Ok::<_, DirSqlError>((scanned, fresh_db))
1486
+ })?
1424
1487
  };
1425
1488
 
1426
1489
  // When persist is enabled, files whose stat tuple matches the cache
@@ -1443,6 +1506,7 @@ impl DirSQL {
1443
1506
  anchors,
1444
1507
  ignore,
1445
1508
  scanned_files,
1509
+ fresh_db,
1446
1510
  early,
1447
1511
  hint_legacy_files_table,
1448
1512
  persist: persist_ctx.map(|ctx| PreparedPersist {
@@ -1471,10 +1535,9 @@ impl DirSQL {
1471
1535
  }
1472
1536
 
1473
1537
  /// Split-phase construction — part 2. Consumes the intermediate state from
1474
- /// [`prepare_resolved`](Self::prepare_resolved): creates the SQLite
1475
- /// database (or wires up the persistent on-disk one), runs each table's
1476
- /// DDL, invokes each file's `on_file` callback, and inserts the
1477
- /// resulting rows.
1538
+ /// [`prepare_resolved`](Self::prepare_resolved): configures the prepared
1539
+ /// database, completes any deferred DDL, invokes each file's `on_file`
1540
+ /// callback, and inserts the resulting rows.
1478
1541
  ///
1479
1542
  /// Must be invoked on a thread where the `on_file` closures can safely
1480
1543
  /// run. For the napi-rs binding that is the JS main thread.
@@ -1501,6 +1564,7 @@ impl DirSQL {
1501
1564
  anchors,
1502
1565
  ignore,
1503
1566
  scanned_files,
1567
+ fresh_db,
1504
1568
  early,
1505
1569
  persist,
1506
1570
  poll_interval,
@@ -1509,20 +1573,28 @@ impl DirSQL {
1509
1573
  no_ignore,
1510
1574
  } = prepared;
1511
1575
 
1512
- let (mut db, persist_ready, needs_sweep) = match persist {
1576
+ let (mut db, fresh_ddl, ddl_warnings, persist_ready, needs_sweep) = match persist {
1513
1577
  Some(p) => (
1514
1578
  p.db,
1579
+ false,
1580
+ Vec::new(),
1515
1581
  Some((p.deleted, p.meta, p.meta_current)),
1516
1582
  p.needs_sweep,
1517
1583
  ),
1518
- None => (Db::new()?, None, false),
1584
+ None => {
1585
+ let (db, ddl_ready, warnings) = fresh_db.expect("prepare opened the database");
1586
+ (db, ddl_ready, warnings, None, false)
1587
+ }
1519
1588
  };
1520
- db.set_path_table_root(root.clone());
1521
- db.set_hint_legacy_files_table(hint_legacy_files_table);
1522
- db.add_path_table_ignore(ignore);
1523
- db.set_path_table_gitignore(!no_ignore);
1524
- if let Some(command) = path_table_parser {
1525
- db.set_path_table_parser(command);
1589
+ if persist_ready.is_some() {
1590
+ configure_db_paths(
1591
+ &mut db,
1592
+ &root,
1593
+ &ignore,
1594
+ hint_legacy_files_table,
1595
+ path_table_parser.as_deref(),
1596
+ no_ignore,
1597
+ );
1526
1598
  }
1527
1599
 
1528
1600
  // Load extensions before any CREATE TABLE so a table's DDL and later
@@ -1558,32 +1630,16 @@ impl DirSQL {
1558
1630
  let mut ddl_map: HashMap<String, String> = HashMap::new();
1559
1631
  let declared: Vec<String> = tables.iter().map(|table| table.name.clone()).collect();
1560
1632
 
1633
+ let ddl_warnings = if fresh_ddl {
1634
+ ddl_warnings
1635
+ } else {
1636
+ run_table_ddl(&db, &tables)?
1637
+ };
1638
+ for warning in ddl_warnings {
1639
+ eprintln!("{warning}");
1640
+ }
1561
1641
  for table in tables {
1562
1642
  let table_name = table.name.clone();
1563
- // A real table under this name is the cache already holding it
1564
- // from a prior run: skip the batch, since the schema is preserved
1565
- // verbatim across runs (the glob_config_hash captures the whole
1566
- // `ddl`). Anything else under the name is not a warm cache — run
1567
- // the batch and let SQLite object to the collision itself.
1568
- let warm = catalog_entry(&db, &table_name)?.is_some_and(|entry| entry.kind == "table");
1569
- if !warm {
1570
- let before = db::user_table_names(db.conn()).map_err(DirSqlError::sqlite)?;
1571
- db.create_table(&table_name, &table.ddl).map_err(|source| {
1572
- DirSqlError::TableDdl {
1573
- name: table_name.clone(),
1574
- source,
1575
- }
1576
- })?;
1577
- let created = db::user_table_names(db.conn())
1578
- .map_err(DirSqlError::sqlite)?
1579
- .into_iter()
1580
- .filter(|name| !before.contains(name))
1581
- .collect();
1582
- let entry = catalog_entry(&db, &table_name)?;
1583
- if let Some(warning) = classify_declared_table(&table_name, entry, created)? {
1584
- eprintln!("{warning}");
1585
- }
1586
- }
1587
1643
  on_file_map.insert(table_name.clone(), table.hook);
1588
1644
  strict_map.insert(table_name.clone(), table.strict);
1589
1645
  ddl_map.insert(table_name, table.ddl);
@@ -2196,6 +2252,9 @@ pub struct PreparedBuild {
2196
2252
  /// the same ones declared tables do.
2197
2253
  ignore: Vec<String>,
2198
2254
  scanned_files: Scanned,
2255
+ /// The transient database opened during the scan, whether its tables'
2256
+ /// DDL already ran, and that DDL's warnings. `None` when persisting.
2257
+ fresh_db: Option<(Db, bool, Vec<String>)>,
2199
2258
  /// Per-table hooks already running over the paths the scan found, by table.
2200
2259
  early: Vec<(String, Production)>,
2201
2260
  persist: Option<PreparedPersist>,
@@ -2239,6 +2298,49 @@ struct PersistContext {
2239
2298
 
2240
2299
  type GroupDraft = (PathBuf, Vec<String>, Vec<(String, String)>, Vec<String>);
2241
2300
 
2301
+ fn configure_db_paths(
2302
+ db: &mut Db,
2303
+ root: &Path,
2304
+ ignore: &[String],
2305
+ hint_legacy_files_table: bool,
2306
+ path_table_parser: Option<&str>,
2307
+ no_ignore: bool,
2308
+ ) {
2309
+ db.set_path_table_root(root.to_path_buf());
2310
+ db.set_hint_legacy_files_table(hint_legacy_files_table);
2311
+ db.add_path_table_ignore(ignore.to_vec());
2312
+ db.set_path_table_gitignore(!no_ignore);
2313
+ if let Some(command) = path_table_parser {
2314
+ db.set_path_table_parser(command.to_owned());
2315
+ }
2316
+ }
2317
+
2318
+ fn run_table_ddl(db: &Db, tables: &[Table]) -> Result<Vec<String>> {
2319
+ let mut warnings = Vec::new();
2320
+ for table in tables {
2321
+ let table_name = &table.name;
2322
+ let warm = catalog_entry(db, table_name)?.is_some_and(|entry| entry.kind == "table");
2323
+ if !warm {
2324
+ let before = db::user_table_names(db.conn()).map_err(DirSqlError::sqlite)?;
2325
+ db.create_table(table_name, &table.ddl)
2326
+ .map_err(|source| DirSqlError::TableDdl {
2327
+ name: table_name.clone(),
2328
+ source,
2329
+ })?;
2330
+ let created = db::user_table_names(db.conn())
2331
+ .map_err(DirSqlError::sqlite)?
2332
+ .into_iter()
2333
+ .filter(|name| !before.contains(name))
2334
+ .collect();
2335
+ let entry = catalog_entry(db, table_name)?;
2336
+ if let Some(warning) = classify_declared_table(table_name, entry, created)? {
2337
+ warnings.push(warning);
2338
+ }
2339
+ }
2340
+ }
2341
+ Ok(warnings)
2342
+ }
2343
+
2242
2344
  /// Walk every group's anchor in turn, reporting one running count across all of
2243
2345
  /// them. Returns the matches and the total count.
2244
2346
  fn scan_groups(
@@ -3450,6 +3552,173 @@ mod internal_tests {
3450
3552
  )
3451
3553
  }
3452
3554
 
3555
+ #[test]
3556
+ fn prepare_opens_the_database_while_the_scan_is_active() {
3557
+ use std::sync::mpsc;
3558
+
3559
+ let dir = TempDir::new().unwrap();
3560
+ let (scan_started, wait_for_scan) = mpsc::channel();
3561
+ let (db_opened, wait_for_db) = mpsc::channel();
3562
+ let scan =
3563
+ |_: &Path, _: &TableMatcher, _: &mut dyn FnMut(u64), _: &mut dyn FnMut(&Path, &str)| {
3564
+ scan_started.send(()).unwrap();
3565
+ assert!(
3566
+ wait_for_db.recv_timeout(Duration::from_secs(5)).is_ok(),
3567
+ "database creation must finish before the scan completes"
3568
+ );
3569
+ Vec::new()
3570
+ };
3571
+ let new_db = move || {
3572
+ wait_for_scan.recv_timeout(Duration::from_secs(5)).unwrap();
3573
+ let db = Db::new()?;
3574
+ db_opened.send(()).unwrap();
3575
+ Ok(db)
3576
+ };
3577
+
3578
+ let prepared = DirSQL::prepare_resolved_with_db(
3579
+ resolved_over(dir.path(), vec![txt_table()], false),
3580
+ &scan,
3581
+ new_db,
3582
+ )
3583
+ .unwrap();
3584
+ assert!(prepared.scanned_files.into_files().is_empty());
3585
+ }
3586
+
3587
+ #[test]
3588
+ fn prepare_creates_the_table_while_the_scan_is_active() {
3589
+ use std::sync::mpsc;
3590
+
3591
+ let dir = TempDir::new().unwrap();
3592
+ let (scan_started, wait_for_scan) = mpsc::channel();
3593
+ let (ddl_done, wait_for_ddl) = mpsc::channel();
3594
+ let scan =
3595
+ |_: &Path, _: &TableMatcher, _: &mut dyn FnMut(u64), _: &mut dyn FnMut(&Path, &str)| {
3596
+ scan_started.send(()).unwrap();
3597
+ assert!(
3598
+ wait_for_ddl.recv_timeout(Duration::from_secs(5)).is_ok(),
3599
+ "table DDL must finish before the scan completes"
3600
+ );
3601
+ Vec::new()
3602
+ };
3603
+ let ddl = move |db: &Db, tables: &[Table]| {
3604
+ wait_for_scan.recv_timeout(Duration::from_secs(5)).unwrap();
3605
+ let warnings = run_table_ddl(db, tables)?;
3606
+ assert!(catalog_entry(db, "items")?.is_some());
3607
+ ddl_done.send(()).unwrap();
3608
+ Ok(warnings)
3609
+ };
3610
+
3611
+ let prepared = DirSQL::prepare_resolved_with_setup(
3612
+ resolved_over(dir.path(), vec![txt_table()], false),
3613
+ &scan,
3614
+ Db::new,
3615
+ ddl,
3616
+ )
3617
+ .unwrap();
3618
+ assert!(prepared.scanned_files.into_files().is_empty());
3619
+ }
3620
+
3621
+ #[test]
3622
+ fn prepare_defers_ddl_until_after_extensions_load() {
3623
+ use std::sync::atomic::{AtomicBool, Ordering};
3624
+
3625
+ let dir = TempDir::new().unwrap();
3626
+ let mut resolved = resolved_over(dir.path(), vec![txt_table()], false);
3627
+ resolved.extensions.push(Extension {
3628
+ path: dir.path().join("missing-extension.so"),
3629
+ entrypoint: None,
3630
+ });
3631
+ let ddl_called = Arc::new(AtomicBool::new(false));
3632
+ let called = Arc::clone(&ddl_called);
3633
+ let prepared = DirSQL::prepare_resolved_with_setup(
3634
+ resolved,
3635
+ &|_, _, _, _| Vec::new(),
3636
+ Db::new,
3637
+ move |_, _| {
3638
+ called.store(true, Ordering::SeqCst);
3639
+ Ok(Vec::new())
3640
+ },
3641
+ )
3642
+ .unwrap();
3643
+
3644
+ assert!(!ddl_called.load(Ordering::SeqCst));
3645
+ assert!(!prepared.fresh_db.as_ref().unwrap().1);
3646
+ assert!(matches!(
3647
+ DirSQL::finish_build(prepared),
3648
+ Err(DirSqlError::Extension { .. })
3649
+ ));
3650
+ }
3651
+
3652
+ #[test]
3653
+ fn configure_db_paths_honors_gitignore_unless_told_not_to() {
3654
+ for no_ignore in [false, true] {
3655
+ let mut db = Db::new().unwrap();
3656
+ configure_db_paths(&mut db, Path::new("/r"), &[], false, None, no_ignore);
3657
+ assert_eq!(db.path_table_gitignore, !no_ignore);
3658
+ }
3659
+ }
3660
+
3661
+ #[test]
3662
+ fn run_table_ddl_creates_a_missing_table_and_keeps_a_present_one() {
3663
+ let db = Db::new().unwrap();
3664
+ let tables = [txt_table()];
3665
+ assert!(run_table_ddl(&db, &tables).unwrap().is_empty());
3666
+ assert!(catalog_entry(&db, "items").unwrap().is_some());
3667
+ assert!(run_table_ddl(&db, &tables).unwrap().is_empty());
3668
+ }
3669
+
3670
+ #[test]
3671
+ fn run_table_ddl_names_only_the_tables_its_batch_created() {
3672
+ let db = Db::new().unwrap();
3673
+ db.conn()
3674
+ .execute_batch("CREATE TABLE earlier (y TEXT)")
3675
+ .unwrap();
3676
+ let tables = [Table::new(
3677
+ "items",
3678
+ "CREATE TABLE made (x TEXT)",
3679
+ "*.txt",
3680
+ |_| Vec::new(),
3681
+ )];
3682
+ let err = run_table_ddl(&db, &tables).unwrap_err();
3683
+ assert!(
3684
+ matches!(&err, DirSqlError::TableNotCreated { created, .. } if created == &["made"]),
3685
+ "{err:?}"
3686
+ );
3687
+ }
3688
+
3689
+ #[test]
3690
+ fn prepare_defers_ddl_until_after_functions_register() {
3691
+ use std::sync::atomic::{AtomicBool, Ordering};
3692
+
3693
+ let dir = TempDir::new().unwrap();
3694
+ let mut resolved = resolved_over(dir.path(), vec![txt_table()], false);
3695
+ resolved.functions.push(ResolvedFunction {
3696
+ name: "custom_value".into(),
3697
+ args: vec![0],
3698
+ command: "true".into(),
3699
+ deterministic: true,
3700
+ timeout: Duration::from_secs(1),
3701
+ batch: None,
3702
+ cwd: dir.path().to_path_buf(),
3703
+ });
3704
+ let ddl_called = Arc::new(AtomicBool::new(false));
3705
+ let called = Arc::clone(&ddl_called);
3706
+ let prepared = DirSQL::prepare_resolved_with_setup(
3707
+ resolved,
3708
+ &|_, _, _, _| Vec::new(),
3709
+ Db::new,
3710
+ move |_, _| {
3711
+ called.store(true, Ordering::SeqCst);
3712
+ Ok(Vec::new())
3713
+ },
3714
+ )
3715
+ .unwrap();
3716
+
3717
+ assert!(!ddl_called.load(Ordering::SeqCst));
3718
+ assert!(!prepared.fresh_db.as_ref().unwrap().1);
3719
+ assert!(DirSQL::finish_build(prepared).is_ok());
3720
+ }
3721
+
3453
3722
  /// Configless startup declares zero tables, so nothing the walk could
3454
3723
  /// visit can match: the walk must not run at all.
3455
3724
  #[test]
@@ -3621,6 +3890,7 @@ mod internal_tests {
3621
3890
  stat: None,
3622
3891
  trusted: false,
3623
3892
  }]),
3893
+ fresh_db: Some((Db::new().unwrap(), false, Vec::new())),
3624
3894
  early: Vec::new(),
3625
3895
  poll_interval: DEFAULT_POLL_INTERVAL,
3626
3896
  persist: None,
@@ -5855,6 +6125,9 @@ mod internal_tests {
5855
6125
  })
5856
6126
  .collect(),
5857
6127
  );
6128
+ let fresh_db = persist
6129
+ .is_none()
6130
+ .then(|| (Db::new().unwrap(), false, Vec::new()));
5858
6131
  PreparedBuild {
5859
6132
  ignore: Vec::new(),
5860
6133
  root: root.to_path_buf(),
@@ -5864,6 +6137,7 @@ mod internal_tests {
5864
6137
  groups: Vec::new(),
5865
6138
  anchors: TableAnchors::at_root(root),
5866
6139
  scanned_files,
6140
+ fresh_db,
5867
6141
  early: Vec::new(),
5868
6142
  poll_interval: DEFAULT_POLL_INTERVAL,
5869
6143
  persist,
@@ -130,6 +130,8 @@ struct Shared<'e, D, L> {
130
130
  open: Mutex<Open<D, L>>,
131
131
  found_dir: Condvar,
132
132
  found: AtomicUsize,
133
+ /// Threads started on the walk, the calling thread among them.
134
+ hired: AtomicUsize,
133
135
  explore: &'e (dyn Fn(D) -> Vec<Step<D, L>> + Sync),
134
136
  }
135
137
 
@@ -147,6 +149,7 @@ pub(crate) fn walk_in_order<D: Send, L: Send>(
147
149
  }),
148
150
  found_dir: Condvar::new(),
149
151
  found: AtomicUsize::new(1),
152
+ hired: AtomicUsize::new(1),
150
153
  explore,
151
154
  };
152
155
  thread::scope(|scope| {
@@ -159,9 +162,7 @@ pub(crate) fn walk_in_order<D: Send, L: Send>(
159
162
  if !spawned && shared.found.load(Ordering::Relaxed) >= PARALLEL_DIRS {
160
163
  spawned = true;
161
164
  let workers = thread::available_parallelism().map_or(1, usize::from);
162
- for _ in 1..workers {
163
- scope.spawn(|| shared.work());
164
- }
165
+ hire(scope, &shared, workers);
165
166
  }
166
167
  stack.push(shared.obtain(&slot).into_iter());
167
168
  }
@@ -179,6 +180,25 @@ fn lock<T>(mutex: &Mutex<T>) -> MutexGuard<'_, T> {
179
180
  mutex.lock().expect("exploring a directory does not panic")
180
181
  }
181
182
 
183
+ /// Start workers until `workers` threads are on the walk, as a tree: each
184
+ /// worker starts up to two more before it explores, since spawning a thread
185
+ /// takes tens of microseconds and the walk hands out nothing while it spawns.
186
+ /// The count only rises, so however the tree branches it ends.
187
+ fn hire<'scope, D: Send, L: Send>(
188
+ scope: &'scope thread::Scope<'scope, '_>,
189
+ shared: &'scope Shared<'_, D, L>,
190
+ workers: usize,
191
+ ) {
192
+ for _ in 0..2 {
193
+ if shared.hired.fetch_add(1, Ordering::Relaxed) < workers {
194
+ scope.spawn(move || {
195
+ hire(scope, shared, workers);
196
+ shared.work();
197
+ });
198
+ }
199
+ }
200
+ }
201
+
182
202
  impl<D, L> Shared<'_, D, L> {
183
203
  fn open_lock(&self) -> MutexGuard<'_, Open<D, L>> {
184
204
  lock(&self.open)
@@ -392,6 +412,7 @@ mod tests {
392
412
  }),
393
413
  found_dir: Condvar::new(),
394
414
  found: AtomicUsize::new(0),
415
+ hired: AtomicUsize::new(1),
395
416
  explore: &explore,
396
417
  };
397
418
  assert!(