@vibe-agent-toolkit/utils 0.2.0-rc.3 → 0.2.0-rc.4

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 (74) hide show
  1. package/README.md +21 -13
  2. package/dist/crawl-timing.d.ts +43 -66
  3. package/dist/crawl-timing.d.ts.map +1 -1
  4. package/dist/crawl-timing.js +35 -79
  5. package/dist/crawl-timing.js.map +1 -1
  6. package/dist/crawl.d.ts +2 -4
  7. package/dist/crawl.d.ts.map +1 -1
  8. package/dist/crawl.js +2 -4
  9. package/dist/crawl.js.map +1 -1
  10. package/dist/git.d.ts +11 -4
  11. package/dist/git.d.ts.map +1 -1
  12. package/dist/git.js +11 -4
  13. package/dist/git.js.map +1 -1
  14. package/dist/index.d.ts +19 -20
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +19 -41
  17. package/dist/index.js.map +1 -1
  18. package/dist/project.d.ts +7 -5
  19. package/dist/project.d.ts.map +1 -1
  20. package/dist/project.js +7 -5
  21. package/dist/project.js.map +1 -1
  22. package/dist/testing.d.ts +73 -3
  23. package/dist/testing.d.ts.map +1 -1
  24. package/dist/testing.js +93 -3
  25. package/dist/testing.js.map +1 -1
  26. package/dist/timing-dump.d.ts +22 -5
  27. package/dist/timing-dump.d.ts.map +1 -1
  28. package/dist/timing-dump.js +89 -23
  29. package/dist/timing-dump.js.map +1 -1
  30. package/eslint/index.cjs +9 -0
  31. package/eslint/index.d.cts +14 -7
  32. package/eslint/rules/no-process-exit-in-phase.cjs +117 -0
  33. package/package.json +5 -7
  34. package/dist/link-auth/build-headers.d.ts +0 -34
  35. package/dist/link-auth/build-headers.d.ts.map +0 -1
  36. package/dist/link-auth/build-headers.js +0 -58
  37. package/dist/link-auth/build-headers.js.map +0 -1
  38. package/dist/link-auth/expand-macro.d.ts +0 -38
  39. package/dist/link-auth/expand-macro.d.ts.map +0 -1
  40. package/dist/link-auth/expand-macro.js +0 -139
  41. package/dist/link-auth/expand-macro.js.map +0 -1
  42. package/dist/link-auth/macros.yaml +0 -50
  43. package/dist/link-auth/resolve-token.d.ts +0 -83
  44. package/dist/link-auth/resolve-token.d.ts.map +0 -1
  45. package/dist/link-auth/resolve-token.js +0 -115
  46. package/dist/link-auth/resolve-token.js.map +0 -1
  47. package/dist/link-auth/resolve.d.ts +0 -102
  48. package/dist/link-auth/resolve.d.ts.map +0 -1
  49. package/dist/link-auth/resolve.js +0 -66
  50. package/dist/link-auth/resolve.js.map +0 -1
  51. package/dist/link-auth/rewrite.d.ts +0 -52
  52. package/dist/link-auth/rewrite.d.ts.map +0 -1
  53. package/dist/link-auth/rewrite.js +0 -102
  54. package/dist/link-auth/rewrite.js.map +0 -1
  55. package/dist/link-auth/select-provider.d.ts +0 -30
  56. package/dist/link-auth/select-provider.d.ts.map +0 -1
  57. package/dist/link-auth/select-provider.js +0 -55
  58. package/dist/link-auth/select-provider.js.map +0 -1
  59. package/dist/link-auth/template.d.ts +0 -40
  60. package/dist/link-auth/template.d.ts.map +0 -1
  61. package/dist/link-auth/template.js +0 -89
  62. package/dist/link-auth/template.js.map +0 -1
  63. package/dist/link-auth/transforms.d.ts +0 -46
  64. package/dist/link-auth/transforms.d.ts.map +0 -1
  65. package/dist/link-auth/transforms.js +0 -52
  66. package/dist/link-auth/transforms.js.map +0 -1
  67. package/dist/template-entry.d.ts +0 -10
  68. package/dist/template-entry.d.ts.map +0 -1
  69. package/dist/template-entry.js +0 -10
  70. package/dist/template-entry.js.map +0 -1
  71. package/dist/template.d.ts +0 -7
  72. package/dist/template.d.ts.map +0 -1
  73. package/dist/template.js +0 -18
  74. package/dist/template.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -3,40 +3,39 @@
3
3
  * Core shared utilities with no dependencies on other packages
4
4
  *
5
5
  * Utilities are added as needed by other packages, not speculatively.
6
+ *
7
+ * **A module that brings a third-party dependency belongs on a subpath, not
8
+ * here.** This entry has ~245 in-repo importers plus published adopters, and
9
+ * every one of them pays for the whole graph reachable from it — a bundler that
10
+ * cannot tree-shake a dependency (a CJS package, or one reached through
11
+ * `new URL(..., import.meta.url)`) inlines it into every consumer that touched
12
+ * a path helper. The domains that carry weight each have their own entry:
13
+ * `./crawl`, `./git`, `./process`, `./skill-test`, `./template`, `./yaml`.
14
+ * `./skill-test` is there for a *transitive* reason rather than a direct one —
15
+ * it declares no dependency itself, but spawning a headless agent goes through
16
+ * `./process`, which reaches `which` and (because `safeExecSync` refuses `git`
17
+ * and delegates) `@vibe-validate/git`. Reachability is the criterion, not the
18
+ * import a module happens to write.
19
+ *
20
+ * The rule is enforced, not merely stated: `test/subpath-purity.test.ts` asserts
21
+ * this entry's reachable third-party set by equality, so a dependency arriving
22
+ * here — directly or transitively, through any module below — turns that row red
23
+ * and has to be an argued edit rather than an unnoticed one.
6
24
  */
7
- export * from './safe-exec.js';
8
- export * from './windows-shell.js';
9
- export * from './spawn-hardened.js';
10
25
  export * from './path-utils.js';
11
26
  export * from './text-content.js';
12
27
  export * from './text-file.js';
13
- export * from './stdio-blocking.js';
14
28
  export * from './asset-reference.js';
15
29
  export { classifyFilenameCaseFrom, copyDirectory, fillRealpaths, fillSiblingNames, FsLookupCache, isFilesystemAccessError, realpathFrom, } from './fs-utils.js';
16
30
  export type { FilenameCaseVerdict, FilenameMatch, PathProbe, PathProbeStats, RealpathTable, SiblingNamesTable, } from './fs-utils.js';
17
- export * from './file-crawler.js';
18
- export * from './gitignore-checker.js';
19
- export * from './git-run.js';
20
- export * from './git-url.js';
21
- export * from './git-utils.js';
22
- export * from './git-snapshot.js';
23
31
  export * from './project-utils.js';
24
- export * from './git-tracker.js';
25
32
  export * from './test-helpers.js';
26
33
  export * from './zod-introspection.js';
27
- export * from './template.js';
28
34
  export * from './skill-targets.js';
29
- export { type LinkAuthConfig, type Provider, type ProviderAuth, type ProviderCheck, resolveAuthenticatedUrl, type ResolveOutcome, } from './link-auth/resolve.js';
30
- export type { ProviderMatch } from './link-auth/select-provider.js';
31
- export type { RewriteRule } from './link-auth/rewrite.js';
32
- export { defaultRunCommand, type TokenSource } from './link-auth/resolve-token.js';
33
- export { expandMacro, UnknownMacroError } from './link-auth/expand-macro.js';
34
- export * from './skill-test/index.js';
35
35
  export * from './glob/glob-pattern.js';
36
36
  export * from './fs/file-hash.js';
37
- export * from './yaml/surgical-yaml.js';
38
37
  export { parseWholeNumberAtLeast } from './numeric-args.js';
39
38
  export { compareCodeUnits } from './compare-code-units.js';
40
- export { CRAWL_BLOB_POPULATE_ID, CRAWL_CLOSURE_CONTRIBUTE_ID, CRAWL_CLOSURE_RESOLVE_ID, CRAWL_PASS_INSIDE, CRAWL_REGISTRY_ADD_RESOURCE_ID, CRAWL_REGISTRY_ENUMERATE_ID, CRAWL_REGISTRY_ID_PREFIX, CRAWL_REGISTRY_RESOLVE_LINKS_ID, CRAWL_SEAM_DUMP_VERSION, CRAWL_SHARED_GIT_TRACKER_ID, CRAWL_STORE_READ_ID, CRAWL_STORE_WRITE_ID, CRAWL_STRATA, CRAWL_WALKER_GITIGNORE_ID, CRAWL_WALKER_ID, crawlTimingStart, recordContributorInvocation, recordCrawlPass, recordRegistryPass, recordSharedPass, withContributorStratum, withOuterBracket, type CrawlDriverStratum, type CrawlStratum, type CrawlTimingDump, type CrawlTimingEntry, type CrawlTimingProcess, __readCrawlTimingSnapshot, __setCrawlTimingForTest, __writeCrawlTimingDumpForTest, } from './crawl-timing.js';
39
+ export { CRAWL_BLOB_POPULATE_ID, CRAWL_CLOSURE_CONTRIBUTE_ID, CRAWL_CLOSURE_RESOLVE_ID, CRAWL_PASS_INSIDE, CRAWL_REGISTRY_ADMIT_ID, CRAWL_REGISTRY_ENUMERATE_ID, CRAWL_REGISTRY_ID_PREFIX, CRAWL_REGISTRY_RESOLVE_LINKS_ID, CRAWL_SHARED_GIT_TRACKER_ID, CRAWL_STORE_READ_ID, CRAWL_STORE_WRITE_ID, CRAWL_STRATA, CRAWL_WALKER_GITIGNORE_ID, CRAWL_WALKER_ID, crawlTimingStart, recordContributorInvocation, recordCrawlPass, recordRegistryPass, recordSharedPass, withContributorStratum, withOuterBracket, type CrawlDriverStratum, type CrawlStratum, type CrawlTimingDump, type CrawlTimingEntry, type CrawlTimingProcess, __readCrawlTimingSnapshot, __setCrawlTimingForTest, __writeCrawlTimingDumpForTest, } from './crawl-timing.js';
41
40
  export { ensureTimingDirectory, normalizeTimingDirectory, readTimingProcess, type TimingProcess, writeTimingDump, } from './timing-dump.js';
42
41
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,iBAAiB,CAAC;AAShC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,qBAAqB,CAAC;AAGpC,cAAc,sBAAsB,CAAC;AAqCrC,OAAO,EACL,wBAAwB,EACxB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,cAAc,EACd,aAAa,EACb,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAGvB,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAKvC,cAAc,cAAc,CAAC;AAG7B,cAAc,cAAc,CAAC;AAG7B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,mBAAmB,CAAC;AAIlC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,eAAe,CAAC;AAG9B,cAAc,oBAAoB,CAAC;AAInC,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAG7E,cAAc,uBAAuB,CAAC;AAGtC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,yBAAyB,CAAC;AAExC,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAgB3D,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,wBAAwB,EACxB,iBAAiB,EACjB,8BAA8B,EAC9B,2BAA2B,EAC3B,wBAAwB,EACxB,+BAA+B,EAK/B,uBAAuB,EACvB,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,2BAA2B,EAC3B,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,KAAK,aAAa,EAClB,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,cAAc,iBAAiB,CAAC;AAShC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,sBAAsB,CAAC;AAqCrC,OAAO,EACL,wBAAwB,EACxB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,cAAc,EACd,aAAa,EACb,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAIvB,cAAc,oBAAoB,CAAC;AAGnC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAgB3D,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EACvB,2BAA2B,EAC3B,wBAAwB,EACxB,+BAA+B,EAC/B,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,2BAA2B,EAC3B,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,KAAK,aAAa,EAClB,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -3,13 +3,25 @@
3
3
  * Core shared utilities with no dependencies on other packages
4
4
  *
5
5
  * Utilities are added as needed by other packages, not speculatively.
6
+ *
7
+ * **A module that brings a third-party dependency belongs on a subpath, not
8
+ * here.** This entry has ~245 in-repo importers plus published adopters, and
9
+ * every one of them pays for the whole graph reachable from it — a bundler that
10
+ * cannot tree-shake a dependency (a CJS package, or one reached through
11
+ * `new URL(..., import.meta.url)`) inlines it into every consumer that touched
12
+ * a path helper. The domains that carry weight each have their own entry:
13
+ * `./crawl`, `./git`, `./process`, `./skill-test`, `./template`, `./yaml`.
14
+ * `./skill-test` is there for a *transitive* reason rather than a direct one —
15
+ * it declares no dependency itself, but spawning a headless agent goes through
16
+ * `./process`, which reaches `which` and (because `safeExecSync` refuses `git`
17
+ * and delegates) `@vibe-validate/git`. Reachability is the criterion, not the
18
+ * import a module happens to write.
19
+ *
20
+ * The rule is enforced, not merely stated: `test/subpath-purity.test.ts` asserts
21
+ * this entry's reachable third-party set by equality, so a dependency arriving
22
+ * here — directly or transitively, through any module below — turns that row red
23
+ * and has to be an argued edit rather than an unnoticed one.
6
24
  */
7
- // Safe command execution (cross-platform, no shell injection)
8
- export * from './safe-exec.js';
9
- // Windows shell-invocation helpers (.cmd/.bat/.ps1 handling), shared by every spawn wrapper
10
- export * from './windows-shell.js';
11
- // Hardened async spawn (streaming stdio + correct Windows .cmd/.bat launching)
12
- export * from './spawn-hardened.js';
13
25
  // Cross-platform path utilities
14
26
  export * from './path-utils.js';
15
27
  // THE content-decoding seam: bytes to text, in one place. `decodeTextContent` is
@@ -21,8 +33,6 @@ export * from './path-utils.js';
21
33
  // of the repo is a migration ledger in `eslint.config.js`, not a covered claim.
22
34
  export * from './text-content.js';
23
35
  export * from './text-file.js';
24
- // Blocking stdio for published bins (process.exit must not truncate output)
25
- export * from './stdio-blocking.js';
26
36
  // Asset reference resolution (paths + npm bare specifiers)
27
37
  export * from './asset-reference.js';
28
38
  // Filesystem utilities.
@@ -61,46 +71,19 @@ export * from './asset-reference.js';
61
71
  // symptom is a type that cannot be imported, which surfaces the first time
62
72
  // someone tries — not a silent break in existing code.
63
73
  export { classifyFilenameCaseFrom, copyDirectory, fillRealpaths, fillSiblingNames, FsLookupCache, isFilesystemAccessError, realpathFrom, } from './fs-utils.js';
64
- // Directory crawling with glob patterns
65
- export * from './file-crawler.js';
66
- // Git ignore checking
67
- export * from './gitignore-checker.js';
68
- // The one way to run git: scrubbed by default, `ambient: true` to opt out.
69
- // safeExecSync/safeExecResult refuse `git` and point here. The scrub itself,
70
- // and dirty-corrected tree snapshots, come from `@vibe-validate/git`.
71
- export * from './git-run.js';
72
- // Git URL parsing (parse/detect git URLs, GitHub shorthand, SSH forms)
73
- export * from './git-url.js';
74
- // Git utilities (using git commands directly)
75
- export * from './git-utils.js';
76
- // Dirty-corrected tree snapshots: paths, on-disk blob OIDs and modes in one call
77
- export * from './git-snapshot.js';
78
74
  // Project root discovery (canonical: config → git → null).
79
75
  // CLI-boundary use only — see docs/concepts/roots-and-config.md.
80
76
  export * from './project-utils.js';
81
- // Git tracking cache (for efficient git-ignore checking)
82
- export * from './git-tracker.js';
83
77
  // Test helpers for isolated test output directories
84
78
  export * from './test-helpers.js';
85
79
  // Zod type introspection (version-agnostic)
86
80
  export * from './zod-introspection.js';
87
- // Handlebars template rendering (cached, no HTML escaping)
88
- export * from './template.js';
89
81
  // Skill target resolution (cross-platform flat skill install paths)
90
82
  export * from './skill-targets.js';
91
- // linkAuth pure engine — public API only (issue #113).
92
- // Internal helpers (rewrite, build-headers, etc.) stay module-private.
93
- export { resolveAuthenticatedUrl, } from './link-auth/resolve.js';
94
- export { defaultRunCommand } from './link-auth/resolve-token.js';
95
- export { expandMacro, UnknownMacroError } from './link-auth/expand-macro.js';
96
- // Skill testing utilities (environment management for headless agent runs)
97
- export * from './skill-test/index.js';
98
83
  // Glob pattern helpers (isGlob, staticGlobBase, globMagicRemainder)
99
84
  export * from './glob/glob-pattern.js';
100
85
  // Filesystem hashing (sha256 of raw file bytes)
101
86
  export * from './fs/file-hash.js';
102
- // Byte-surgical YAML value updater (replace/insert without reflowing the doc)
103
- export * from './yaml/surgical-yaml.js';
104
87
  export { parseWholeNumberAtLeast } from './numeric-args.js';
105
88
  // Machine-independent string ordering for hashed/serialized output — never `localeCompare`.
106
89
  export { compareCodeUnits } from './compare-code-units.js';
@@ -118,12 +101,7 @@ export { compareCodeUnits } from './compare-code-units.js';
118
101
  // `keyOf`, `recordInheritedPass`) are not surface, and `timing-dump.ts` is
119
102
  // plumbing shared with `resources`' package-internal `parse-timing.ts` — a star
120
103
  // re-export would publish both the moment either grew a symbol.
121
- export { CRAWL_BLOB_POPULATE_ID, CRAWL_CLOSURE_CONTRIBUTE_ID, CRAWL_CLOSURE_RESOLVE_ID, CRAWL_PASS_INSIDE, CRAWL_REGISTRY_ADD_RESOURCE_ID, CRAWL_REGISTRY_ENUMERATE_ID, CRAWL_REGISTRY_ID_PREFIX, CRAWL_REGISTRY_RESOLVE_LINKS_ID,
122
- // Exported so the READER can pin itself against the WRITER. `@vibe-agent-toolkit/lab`
123
- // hard-refuses a dump whose version it does not recognise, and the two constants
124
- // used to be unrelated literals in two packages — drift was silent, and its symptom
125
- // is every dump being refused rather than a subtly wrong number.
126
- CRAWL_SEAM_DUMP_VERSION, CRAWL_SHARED_GIT_TRACKER_ID, CRAWL_STORE_READ_ID, CRAWL_STORE_WRITE_ID, CRAWL_STRATA, CRAWL_WALKER_GITIGNORE_ID, CRAWL_WALKER_ID, crawlTimingStart, recordContributorInvocation, recordCrawlPass, recordRegistryPass, recordSharedPass, withContributorStratum, withOuterBracket, __readCrawlTimingSnapshot, __setCrawlTimingForTest, __writeCrawlTimingDumpForTest, } from './crawl-timing.js';
104
+ export { CRAWL_BLOB_POPULATE_ID, CRAWL_CLOSURE_CONTRIBUTE_ID, CRAWL_CLOSURE_RESOLVE_ID, CRAWL_PASS_INSIDE, CRAWL_REGISTRY_ADMIT_ID, CRAWL_REGISTRY_ENUMERATE_ID, CRAWL_REGISTRY_ID_PREFIX, CRAWL_REGISTRY_RESOLVE_LINKS_ID, CRAWL_SHARED_GIT_TRACKER_ID, CRAWL_STORE_READ_ID, CRAWL_STORE_WRITE_ID, CRAWL_STRATA, CRAWL_WALKER_GITIGNORE_ID, CRAWL_WALKER_ID, crawlTimingStart, recordContributorInvocation, recordCrawlPass, recordRegistryPass, recordSharedPass, withContributorStratum, withOuterBracket, __readCrawlTimingSnapshot, __setCrawlTimingForTest, __writeCrawlTimingDumpForTest, } from './crawl-timing.js';
127
105
  // The on-disk plumbing both timing seams share. Exported because
128
106
  // `resources`' `parse-timing.ts` is the other consumer and now sits a package
129
107
  // away; nothing else should reach for it.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,iFAAiF;AACjF,2EAA2E;AAC3E,iFAAiF;AACjF,gEAAgE;AAChE,6EAA6E;AAC7E,iFAAiF;AACjF,gFAAgF;AAChF,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAE/B,2DAA2D;AAC3D,cAAc,sBAAsB,CAAC;AAErC,wBAAwB;AACxB,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,8EAA8E;AAC9E,iFAAiF;AACjF,+EAA+E;AAC/E,oEAAoE;AACpE,EAAE;AACF,6EAA6E;AAC7E,EAAE;AACF,8EAA8E;AAC9E,iFAAiF;AACjF,iFAAiF;AACjF,wEAAwE;AACxE,gFAAgF;AAChF,kFAAkF;AAClF,yDAAyD;AACzD,EAAE;AACF,iFAAiF;AACjF,kFAAkF;AAClF,yBAAyB;AACzB,EAAE;AACF,kFAAkF;AAClF,gFAAgF;AAChF,iFAAiF;AACjF,+EAA+E;AAC/E,+EAA+E;AAC/E,8BAA8B;AAC9B,EAAE;AACF,gFAAgF;AAChF,kEAAkE;AAClE,8EAA8E;AAC9E,2EAA2E;AAC3E,uDAAuD;AACvD,OAAO,EACL,wBAAwB,EACxB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,YAAY,GACb,MAAM,eAAe,CAAC;AAUvB,2DAA2D;AAC3D,iEAAiE;AACjE,cAAc,oBAAoB,CAAC;AAEnC,oDAAoD;AACpD,cAAc,mBAAmB,CAAC;AAElC,4CAA4C;AAC5C,cAAc,wBAAwB,CAAC;AAEvC,oEAAoE;AACpE,cAAc,oBAAoB,CAAC;AAEnC,oEAAoE;AACpE,cAAc,wBAAwB,CAAC;AAEvC,gDAAgD;AAChD,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,4FAA4F;AAC5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,+EAA+E;AAC/E,mCAAmC;AACnC,EAAE;AACF,6EAA6E;AAC7E,gFAAgF;AAChF,0EAA0E;AAC1E,2EAA2E;AAC3E,yEAAyE;AACzE,8EAA8E;AAC9E,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,gFAAgF;AAChF,gEAAgE;AAChE,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EACvB,2BAA2B,EAC3B,wBAAwB,EACxB,+BAA+B,EAC/B,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,2BAA2B,EAC3B,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAMhB,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAE3B,iEAAiE;AACjE,8EAA8E;AAC9E,0CAA0C;AAC1C,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EAEjB,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
package/dist/project.d.ts CHANGED
@@ -14,11 +14,13 @@
14
14
  * they largely are not, for the reasons documented on the guard test in
15
15
  * `test/package-exports.test.ts`. But the question that decides whether an entry
16
16
  * should exist is "how heavy is the only remaining door?" With `./project` gone,
17
- * the sole route to these functions was the `.` barrel, which reaches
18
- * `handlebars`, `yaml`, `picomatch`, `ignore` and `which`. A consumer that avoids
19
- * the barrel on graph-weight grounds — which is the entire premise of this
20
- * package's subpath layout — could no longer reach a capability whose own code
21
- * imports nothing but `node:fs` and `node:path`.
17
+ * the sole route to these functions was the `.` barrel, which at the time reached
18
+ * five third-party packages. A consumer that avoids the barrel on graph-weight
19
+ * grounds — which is the entire premise of this package's subpath layout — could
20
+ * no longer reach a capability whose own code imports nothing but `node:fs` and
21
+ * `node:path`. The barrel is dependency-free today, which generalizes the
22
+ * argument rather than retiring it: every domain that carries weight is its own
23
+ * entry, and reaching a pure one must not cost a neighbour's graph.
22
24
  *
23
25
  * The functions remain VAT-shaped and are documented as such in README.md: they
24
26
  * look for `vibe-agent-toolkit.config.yaml`, then `.git/`. If your notion of a
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,sBAAsB,GACvB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,sBAAsB,GACvB,MAAM,oBAAoB,CAAC"}
package/dist/project.js CHANGED
@@ -14,11 +14,13 @@
14
14
  * they largely are not, for the reasons documented on the guard test in
15
15
  * `test/package-exports.test.ts`. But the question that decides whether an entry
16
16
  * should exist is "how heavy is the only remaining door?" With `./project` gone,
17
- * the sole route to these functions was the `.` barrel, which reaches
18
- * `handlebars`, `yaml`, `picomatch`, `ignore` and `which`. A consumer that avoids
19
- * the barrel on graph-weight grounds — which is the entire premise of this
20
- * package's subpath layout — could no longer reach a capability whose own code
21
- * imports nothing but `node:fs` and `node:path`.
17
+ * the sole route to these functions was the `.` barrel, which at the time reached
18
+ * five third-party packages. A consumer that avoids the barrel on graph-weight
19
+ * grounds — which is the entire premise of this package's subpath layout — could
20
+ * no longer reach a capability whose own code imports nothing but `node:fs` and
21
+ * `node:path`. The barrel is dependency-free today, which generalizes the
22
+ * argument rather than retiring it: every domain that carries weight is its own
23
+ * entry, and reaching a pure one must not cost a neighbour's graph.
22
24
  *
23
25
  * The functions remain VAT-shaped and are documented as such in README.md: they
24
26
  * look for `vibe-agent-toolkit.config.yaml`, then `.git/`. If your notion of a
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,sBAAsB,GACvB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,sBAAsB,GACvB,MAAM,oBAAoB,CAAC"}
package/dist/testing.d.ts CHANGED
@@ -1,8 +1,78 @@
1
1
  /**
2
- * @vibe-agent-toolkit/utils/testing
2
+ * Fixture primitives shared by suites in more than one package.
3
3
  *
4
- * Isolated temp-directory helpers for test suites. Node-only. Intended for
5
- * a consumer's test code not for their shipped runtime.
4
+ * Deliberately framework-free: nothing here imports `vitest`, so this module
5
+ * stays a plain function library rather than something that registers hooks as a
6
+ * side effect of being imported. Each suite owns its own `beforeEach`/
7
+ * `afterEach` and calls these from inside them — two lines, which is below
8
+ * anything worth sharing, while the part that is genuinely identical (mkdtemp,
9
+ * write the literal, remove the tree) lives here once.
10
+ *
11
+ * It earned a home in `utils` the ordinary way: two packages needed it, not one
12
+ * package speculating that a second might.
13
+ *
14
+ * ⛔ **Do not import `vitest` here to share the hook wrapper itself.**
15
+ * `subpath-purity.test.ts` pins this entry at an EMPTY third-party set, and that
16
+ * pin is load-bearing: `./testing` is a published subpath, so a test framework
17
+ * reached from it becomes a runtime requirement for every adopter who imports
18
+ * it. {@link replantableCorpus} exists precisely so the per-test wrapper each
19
+ * suite still writes is three lines rather than twelve.
6
20
  */
7
21
  export * from './test-helpers.js';
22
+ /** A planted fixture tree and the means to remove it. */
23
+ export interface TempCorpus {
24
+ /** Absolute path to the tree's root. */
25
+ root: string;
26
+ /** Remove the tree. Safe to call when it is already gone. */
27
+ cleanup: () => void;
28
+ }
29
+ /**
30
+ * Write a literal corpus into a fresh temp directory.
31
+ *
32
+ * 🪤 Fixture files must NOT be byte-identical to each other when the suite is
33
+ * about content-addressed behaviour: VAT's blobs are keyed on their bytes plus
34
+ * the parser kind, so two files with the same content collapse into ONE blob and
35
+ * assertions then describe whichever path sorted first. Give each fixture a
36
+ * distinguishing marker line.
37
+ *
38
+ * ⚠️ The root is minted per call, so a suite that plants per test must call this
39
+ * per test — a root captured once and reused across tests survives its own
40
+ * `cleanup`.
41
+ *
42
+ * @param prefix - `mkdtemp` prefix, so a leaked directory names its own suite
43
+ * @param corpus - Fixture name to file content; written verbatim as UTF-8.
44
+ * Names may include forward-slash subpaths only if their parents already exist
45
+ * @returns The tree's root and its teardown
46
+ */
47
+ export declare function createTempCorpus(prefix: string, corpus: Readonly<Record<string, string>>): TempCorpus;
48
+ /** A corpus that can be planted and cleared repeatedly — one tree per test. */
49
+ export interface ReplantableCorpus {
50
+ /** Plant a fresh tree. Drive from the suite's `beforeEach`. */
51
+ plant: () => void;
52
+ /** Remove the current tree, if any. Drive from the suite's `afterEach`. */
53
+ clear: () => void;
54
+ /** The root minted by the most recent {@link plant}. */
55
+ root: () => string;
56
+ }
57
+ /**
58
+ * Hold a per-test corpus root, so a suite's hook wrapper is three lines.
59
+ *
60
+ * ⚠️ **The root comes back through a GETTER, never as a value.** A per-test
61
+ * fixture is reminted for every test, so a root captured at registration time is
62
+ * `undefined` in the first test and stale in every one after it. That mistake is
63
+ * the reason this holder exists rather than each suite keeping its own `let`.
64
+ *
65
+ * ⭐ Framework-free on purpose: it takes no hooks and registers none, so the
66
+ * suite still owns its own `beforeEach`/`afterEach` and this module keeps the
67
+ * empty third-party set its purity pin asserts. See the module docstring.
68
+ *
69
+ * 🪤 `root()` before the first `plant()` THROWS by name. The shape it replaced
70
+ * read an uninitialised `let` and raised `Cannot read properties of undefined`
71
+ * from inside the fixture, which names neither the suite nor the missing hook.
72
+ *
73
+ * @param prefix - `mkdtemp` prefix, so a leaked directory names its own suite
74
+ * @param corpus - Fixture name to file content, as {@link createTempCorpus} takes it
75
+ * @returns Plant/clear/root, to be driven from the caller's own hooks
76
+ */
77
+ export declare function replantableCorpus(prefix: string, corpus: Readonly<Record<string, string>>): ReplantableCorpus;
8
78
  //# sourceMappingURL=testing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAUH,cAAc,mBAAmB,CAAC;AAElC,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACvC,UAAU,CAOZ;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,2EAA2E;IAC3E,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,wDAAwD;IACxD,IAAI,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACvC,iBAAiB,CAyBnB"}
package/dist/testing.js CHANGED
@@ -1,8 +1,98 @@
1
1
  /**
2
- * @vibe-agent-toolkit/utils/testing
2
+ * Fixture primitives shared by suites in more than one package.
3
3
  *
4
- * Isolated temp-directory helpers for test suites. Node-only. Intended for
5
- * a consumer's test code not for their shipped runtime.
4
+ * Deliberately framework-free: nothing here imports `vitest`, so this module
5
+ * stays a plain function library rather than something that registers hooks as a
6
+ * side effect of being imported. Each suite owns its own `beforeEach`/
7
+ * `afterEach` and calls these from inside them — two lines, which is below
8
+ * anything worth sharing, while the part that is genuinely identical (mkdtemp,
9
+ * write the literal, remove the tree) lives here once.
10
+ *
11
+ * It earned a home in `utils` the ordinary way: two packages needed it, not one
12
+ * package speculating that a second might.
13
+ *
14
+ * ⛔ **Do not import `vitest` here to share the hook wrapper itself.**
15
+ * `subpath-purity.test.ts` pins this entry at an EMPTY third-party set, and that
16
+ * pin is load-bearing: `./testing` is a published subpath, so a test framework
17
+ * reached from it becomes a runtime requirement for every adopter who imports
18
+ * it. {@link replantableCorpus} exists precisely so the per-test wrapper each
19
+ * suite still writes is three lines rather than twelve.
6
20
  */
21
+ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
22
+ import { normalizedTmpdir, safePath } from './path-utils.js';
23
+ // The rest of the testing surface. ⚠️ This re-export is the ENTIRETY of what
24
+ // `./testing` used to be, and dropping it silently removed `detachGitEnv`,
25
+ // `setupSyncTempDirSuite` and every sibling from a published subpath. A module
26
+ // that is both a definition site and a barrel loses the barrel first.
7
27
  export * from './test-helpers.js';
28
+ /**
29
+ * Write a literal corpus into a fresh temp directory.
30
+ *
31
+ * 🪤 Fixture files must NOT be byte-identical to each other when the suite is
32
+ * about content-addressed behaviour: VAT's blobs are keyed on their bytes plus
33
+ * the parser kind, so two files with the same content collapse into ONE blob and
34
+ * assertions then describe whichever path sorted first. Give each fixture a
35
+ * distinguishing marker line.
36
+ *
37
+ * ⚠️ The root is minted per call, so a suite that plants per test must call this
38
+ * per test — a root captured once and reused across tests survives its own
39
+ * `cleanup`.
40
+ *
41
+ * @param prefix - `mkdtemp` prefix, so a leaked directory names its own suite
42
+ * @param corpus - Fixture name to file content; written verbatim as UTF-8.
43
+ * Names may include forward-slash subpaths only if their parents already exist
44
+ * @returns The tree's root and its teardown
45
+ */
46
+ export function createTempCorpus(prefix, corpus) {
47
+ const root = mkdtempSync(safePath.join(normalizedTmpdir(), prefix));
48
+ for (const [name, content] of Object.entries(corpus)) {
49
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- a fixture name from the caller's own literal corpus, under this call's fresh mkdtemp root
50
+ writeFileSync(safePath.join(root, name), content, 'utf8');
51
+ }
52
+ return { root, cleanup: () => rmSync(root, { recursive: true, force: true }) };
53
+ }
54
+ /**
55
+ * Hold a per-test corpus root, so a suite's hook wrapper is three lines.
56
+ *
57
+ * ⚠️ **The root comes back through a GETTER, never as a value.** A per-test
58
+ * fixture is reminted for every test, so a root captured at registration time is
59
+ * `undefined` in the first test and stale in every one after it. That mistake is
60
+ * the reason this holder exists rather than each suite keeping its own `let`.
61
+ *
62
+ * ⭐ Framework-free on purpose: it takes no hooks and registers none, so the
63
+ * suite still owns its own `beforeEach`/`afterEach` and this module keeps the
64
+ * empty third-party set its purity pin asserts. See the module docstring.
65
+ *
66
+ * 🪤 `root()` before the first `plant()` THROWS by name. The shape it replaced
67
+ * read an uninitialised `let` and raised `Cannot read properties of undefined`
68
+ * from inside the fixture, which names neither the suite nor the missing hook.
69
+ *
70
+ * @param prefix - `mkdtemp` prefix, so a leaked directory names its own suite
71
+ * @param corpus - Fixture name to file content, as {@link createTempCorpus} takes it
72
+ * @returns Plant/clear/root, to be driven from the caller's own hooks
73
+ */
74
+ export function replantableCorpus(prefix, corpus) {
75
+ let planted;
76
+ return {
77
+ plant: () => {
78
+ // 🪤 Removes any tree still standing FIRST. Nested `describe` blocks each
79
+ // get their own `beforeEach` and vitest runs outer-then-inner before a
80
+ // single `afterEach`, so a double plant is ordinary rather than exotic.
81
+ // Overwriting the handle without this would leak the first tree for the
82
+ // process's lifetime, silently and only on the suites that nest.
83
+ planted?.cleanup();
84
+ planted = createTempCorpus(prefix, corpus);
85
+ },
86
+ clear: () => {
87
+ planted?.cleanup();
88
+ planted = undefined;
89
+ },
90
+ root: () => {
91
+ if (planted === undefined) {
92
+ throw new Error(`replantableCorpus('${prefix}'): root() before plant() — the suite is missing its beforeEach`);
93
+ }
94
+ return planted.root;
95
+ },
96
+ };
97
+ }
8
98
  //# sourceMappingURL=testing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7D,6EAA6E;AAC7E,2EAA2E;AAC3E,+EAA+E;AAC/E,sEAAsE;AACtE,cAAc,mBAAmB,CAAC;AAUlC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAc,EACd,MAAwC;IAExC,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IACpE,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACrD,gKAAgK;QAChK,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACjF,CAAC;AAYD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,MAAwC;IAExC,IAAI,OAA+B,CAAC;IACpC,OAAO;QACL,KAAK,EAAE,GAAG,EAAE;YACV,0EAA0E;YAC1E,uEAAuE;YACvE,wEAAwE;YACxE,wEAAwE;YACxE,iEAAiE;YACjE,OAAO,EAAE,OAAO,EAAE,CAAC;YACnB,OAAO,GAAG,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;QACD,KAAK,EAAE,GAAG,EAAE;YACV,OAAO,EAAE,OAAO,EAAE,CAAC;YACnB,OAAO,GAAG,SAAS,CAAC;QACtB,CAAC;QACD,IAAI,EAAE,GAAG,EAAE;YACT,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CACb,sBAAsB,MAAM,iEAAiE,CAC9F,CAAC;YACJ,CAAC;YACD,OAAO,OAAO,CAAC,IAAI,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -18,9 +18,14 @@
18
18
  * 2. A dump failure is written to **stderr and never thrown**. These run from
19
19
  * an `exit` listener, where a throw changes the process's exit behaviour, and
20
20
  * they must never touch stdout, which carries vat's report.
21
- * 3. A pid can file more than one dump. `vat validate` spawns the vat binary
22
- * once per phase and pids are reused, so `<stem>-<pid>.json` genuinely
23
- * collides; the name gains a counter rather than overwriting.
21
+ * 3. A pid can file more than one dump, and the name is CLAIMED rather than
22
+ * checked. `vat validate` spawns the vat binary once per phase and pids are
23
+ * reused, so `<stem>-<pid>.json` genuinely collides; worse, worker threads
24
+ * SHARE their parent's pid, so a thread pool's whole cohort competes for one
25
+ * `<stem>-<pid>` sequence at the same instant. The name gains a counter
26
+ * rather than overwriting, and the counter is settled by
27
+ * {@link EXCLUSIVE_CREATE} so the OS — not a check-then-write gap — decides
28
+ * who won it.
24
29
  * 4. The process's own wall and CPU time is read ONCE, at dump time. It is a
25
30
  * lifetime figure for the process and never a duration of the measured work;
26
31
  * its value is the RATIO, which tells a reader whether the wall-timed
@@ -59,6 +64,16 @@ export interface TimingProcess {
59
64
  /** System CPU consumed by the process, across all its threads. */
60
65
  cpuSystemMs: number;
61
66
  }
67
+ /**
68
+ * Ceiling on the pid-collision search. A directory holding this many dumps for
69
+ * one pid is a runaway, not a collision, and giving up on a reported line is a
70
+ * better outcome than spinning.
71
+ *
72
+ * Exhausting it does NOT fall back to overwriting the last slot. That was the
73
+ * old behaviour, and it destroyed a dump for the same reason the check-then-
74
+ * write gap did — silently, and precisely when the directory was busiest.
75
+ */
76
+ export declare const MAX_DUMP_COLLISIONS = 1000;
62
77
  /**
63
78
  * Reduce a raw env value to a directory or `null`.
64
79
  *
@@ -107,13 +122,15 @@ export declare function readTimingProcess(): TimingProcess;
107
122
  * Write one seam's dump, if the seam is on.
108
123
  *
109
124
  * The body is built lazily, inside this call, so a disabled seam never pays to
110
- * snapshot accumulators nobody will read.
125
+ * snapshot accumulators nobody will read — and a `build` that throws is reported
126
+ * like any other failure, because this runs from an `exit` listener where a
127
+ * throw would change the process's exit behaviour.
111
128
  *
112
129
  * @param noun - What the seam is called, for any failure line
113
130
  * @param directory - Where to write, or `null` when the seam is off
114
131
  * @param basename - Basename stem for the file
115
132
  * @param build - Produces the dump body
116
- * @returns The path written, or `null` when the seam is off or the write failed
133
+ * @returns The path written, or `null` when the seam is off or nothing was written
117
134
  */
118
135
  export declare function writeTimingDump(noun: string, directory: string | null, basename: string, build: () => unknown): string | null;
119
136
  //# sourceMappingURL=timing-dump.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timing-dump.d.ts","sourceRoot":"","sources":["../src/timing-dump.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAOH;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;CACrB;AAeD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAE/E;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAG1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAM3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,CAOjD;AAuBD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,OAAO,GACnB,MAAM,GAAG,IAAI,CAYf"}
1
+ {"version":3,"file":"timing-dump.d.ts","sourceRoot":"","sources":["../src/timing-dump.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAOH;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;CACrB;AAQD;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,OAAO,CAAC;AA6BxC;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAE/E;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAG1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAM3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,CAOjD;AA0DD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,OAAO,GACnB,MAAM,GAAG,IAAI,CAoBf"}