@outfitter/tooling 0.2.1 → 0.2.3

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 (53) hide show
  1. package/.markdownlint-cli2.jsonc +55 -55
  2. package/README.md +30 -3
  3. package/biome.json +79 -72
  4. package/dist/cli/check-boundary-invocations.d.ts +34 -0
  5. package/dist/cli/check-boundary-invocations.js +14 -0
  6. package/dist/cli/check-bunup-registry.d.ts +36 -0
  7. package/dist/cli/check-bunup-registry.js +12 -0
  8. package/dist/cli/check-changeset.d.ts +64 -0
  9. package/dist/cli/check-changeset.js +14 -0
  10. package/dist/cli/check-clean-tree.d.ts +36 -0
  11. package/dist/cli/check-clean-tree.js +14 -0
  12. package/dist/cli/check-exports.d.ts +2 -0
  13. package/dist/cli/check-exports.js +12 -0
  14. package/dist/cli/check-readme-imports.d.ts +60 -0
  15. package/dist/cli/check-readme-imports.js +194 -0
  16. package/dist/cli/check.js +2 -1
  17. package/dist/cli/fix.js +2 -1
  18. package/dist/cli/index.js +1106 -17
  19. package/dist/cli/init.js +2 -1
  20. package/dist/cli/pre-push.d.ts +34 -1
  21. package/dist/cli/pre-push.js +15 -2
  22. package/dist/cli/upgrade-bun.js +2 -1
  23. package/dist/index.d.ts +110 -35
  24. package/dist/index.js +23 -8
  25. package/dist/registry/build.d.ts +6 -0
  26. package/dist/registry/build.js +32 -13
  27. package/dist/registry/index.js +1 -0
  28. package/dist/registry/schema.js +1 -0
  29. package/dist/shared/@outfitter/{tooling-xx1146e3.js → tooling-0x5q15ec.js} +2 -1
  30. package/dist/shared/@outfitter/tooling-1y8w5ahg.js +70 -0
  31. package/dist/shared/@outfitter/tooling-3w8vr2w3.js +94 -0
  32. package/dist/shared/@outfitter/tooling-8sd32ts6.js +277 -0
  33. package/dist/shared/@outfitter/{tooling-s4eqq91d.js → tooling-9errkcvk.js} +2 -1
  34. package/dist/shared/@outfitter/tooling-9vs606gq.d.ts +3 -0
  35. package/dist/shared/@outfitter/{tooling-75j500dv.js → tooling-9yzd08v1.js} +10 -6
  36. package/dist/shared/@outfitter/tooling-ctmgnap5.js +19 -0
  37. package/dist/shared/@outfitter/tooling-dvwh9qve.js +4 -0
  38. package/dist/shared/@outfitter/{tooling-xaxdr9da.js → tooling-mxwc1n8w.js} +13 -3
  39. package/dist/shared/@outfitter/tooling-q0d60xb3.d.ts +58 -0
  40. package/dist/shared/@outfitter/tooling-r9976n43.js +100 -0
  41. package/dist/shared/@outfitter/tooling-t17gnh9b.js +78 -0
  42. package/dist/shared/@outfitter/tooling-tf22zt9p.js +226 -0
  43. package/dist/shared/chunk-3s189drz.js +4 -0
  44. package/dist/shared/chunk-6a7tjcgm.js +193 -0
  45. package/dist/shared/chunk-8aenrm6f.js +18 -0
  46. package/dist/version.d.ts +2 -0
  47. package/dist/version.js +8 -0
  48. package/lefthook.yml +5 -7
  49. package/package.json +122 -121
  50. package/registry/registry.json +78 -76
  51. package/tsconfig.preset.bun.json +5 -5
  52. package/tsconfig.preset.json +33 -33
  53. package/dist/shared/@outfitter/tooling-qm7jeg0d.js +0 -99
@@ -1,66 +1,66 @@
1
1
  {
2
- // Outfitter markdownlint preset
3
- // https://github.com/DavidAnson/markdownlint
2
+ // Outfitter markdownlint preset
3
+ // https://github.com/DavidAnson/markdownlint
4
4
 
5
- "config": {
6
- // Headings
7
- "MD003": { "style": "atx" }, // ATX-style headings (# Heading)
8
- "MD022": { "lines_above": 1, "lines_below": 1 }, // Blank lines around headings
9
- "MD024": { "siblings_only": true }, // Allow duplicate headings in different sections
10
- "MD041": false, // First line doesn't need to be h1 (frontmatter, etc.)
5
+ "config": {
6
+ // Headings
7
+ "MD003": { "style": "atx" }, // ATX-style headings (# Heading)
8
+ "MD022": { "lines_above": 1, "lines_below": 1 }, // Blank lines around headings
9
+ "MD024": { "siblings_only": true }, // Allow duplicate headings in different sections
10
+ "MD041": false, // First line doesn't need to be h1 (frontmatter, etc.)
11
11
 
12
- // Line length - disabled for prose flexibility
13
- "MD013": false,
12
+ // Line length - disabled for prose flexibility
13
+ "MD013": false,
14
14
 
15
- // Lists
16
- "MD004": { "style": "dash" }, // Unordered list style: dash (-)
17
- "MD007": { "indent": 2 }, // List indentation: 2 spaces
18
- "MD032": true, // Blank lines around lists
15
+ // Lists
16
+ "MD004": { "style": "dash" }, // Unordered list style: dash (-)
17
+ "MD007": { "indent": 2 }, // List indentation: 2 spaces
18
+ "MD032": true, // Blank lines around lists
19
19
 
20
- // Code blocks
21
- "MD040": true, // Fenced code blocks should have a language
22
- "MD046": { "style": "fenced" }, // Code block style: fenced (```)
23
- "MD048": { "style": "backtick" }, // Code fence style: backticks
20
+ // Code blocks
21
+ "MD040": true, // Fenced code blocks should have a language
22
+ "MD046": { "style": "fenced" }, // Code block style: fenced (```)
23
+ "MD048": { "style": "backtick" }, // Code fence style: backticks
24
24
 
25
- // Links
26
- "MD034": true, // No bare URLs (use <url> or [text](url))
25
+ // Links
26
+ "MD034": true, // No bare URLs (use <url> or [text](url))
27
27
 
28
- // Whitespace
29
- "MD009": { "br_spaces": 2 }, // Allow 2 trailing spaces for <br>
30
- "MD010": { "spaces_per_tab": 2 }, // Tabs to spaces
31
- "MD012": { "maximum": 1 }, // Max 1 consecutive blank line
32
- "MD047": true, // Files should end with newline
28
+ // Whitespace
29
+ "MD009": { "br_spaces": 2 }, // Allow 2 trailing spaces for <br>
30
+ "MD010": { "spaces_per_tab": 2 }, // Tabs to spaces
31
+ "MD012": { "maximum": 1 }, // Max 1 consecutive blank line
32
+ "MD047": true, // Files should end with newline
33
33
 
34
- // HTML - allow for GitHub-specific elements
35
- "MD033": {
36
- "allowed_elements": [
37
- "details",
38
- "summary",
39
- "kbd",
40
- "br",
41
- "sup",
42
- "sub",
43
- "img",
44
- "picture",
45
- "source",
46
- "a"
47
- ]
48
- },
34
+ // HTML - allow for GitHub-specific elements
35
+ "MD033": {
36
+ "allowed_elements": [
37
+ "details",
38
+ "summary",
39
+ "kbd",
40
+ "br",
41
+ "sup",
42
+ "sub",
43
+ "img",
44
+ "picture",
45
+ "source",
46
+ "a"
47
+ ]
48
+ },
49
49
 
50
- // Emphasis
51
- "MD049": { "style": "asterisk" }, // Emphasis style: *italic*
52
- "MD050": { "style": "asterisk" } // Strong style: **bold**
53
- },
50
+ // Emphasis
51
+ "MD049": { "style": "asterisk" }, // Emphasis style: *italic*
52
+ "MD050": { "style": "asterisk" } // Strong style: **bold**
53
+ },
54
54
 
55
- // Ignore patterns
56
- "ignores": [
57
- "node_modules/**",
58
- "**/node_modules/**",
59
- "dist/**",
60
- "**/dist/**",
61
- ".turbo/**",
62
- "**/.turbo/**",
63
- "CHANGELOG.md",
64
- "**/CHANGELOG.md"
65
- ]
55
+ // Ignore patterns
56
+ "ignores": [
57
+ "node_modules/**",
58
+ "**/node_modules/**",
59
+ "dist/**",
60
+ "**/dist/**",
61
+ ".turbo/**",
62
+ "**/.turbo/**",
63
+ "CHANGELOG.md",
64
+ "**/CHANGELOG.md"
65
+ ]
66
66
  }
package/README.md CHANGED
@@ -68,21 +68,36 @@ bunx @outfitter/tooling upgrade-bun 1.4.0 --no-install
68
68
 
69
69
  ### `tooling pre-push`
70
70
 
71
- TDD-aware pre-push test hook. Detects RED phase branches and skips tests by design.
71
+ TDD-aware pre-push strict verification hook. Detects RED phase branches and skips verification by design.
72
72
 
73
73
  RED phase branches follow these patterns:
74
74
  - `*-tests` (e.g., `feature/auth-tests`)
75
75
  - `*/tests` (e.g., `feature/auth/tests`)
76
76
  - `*_tests` (e.g., `feature/auth_tests`)
77
77
 
78
+ Verification order:
79
+ 1. Run `verify:ci` if present.
80
+ 2. Otherwise run strict fallback: `typecheck`, `check|lint`, `build`, `test`.
81
+
78
82
  ```bash
79
83
  # Normal usage (in lefthook.yml)
80
84
  bunx @outfitter/tooling pre-push
81
85
 
82
- # Force skip tests
86
+ # Force skip verification
83
87
  bunx @outfitter/tooling pre-push --force
84
88
  ```
85
89
 
90
+ ### `tooling check-boundary-invocations`
91
+
92
+ Validate that root/app scripts do not execute `packages/*/src/*` directly.
93
+
94
+ ```bash
95
+ bunx @outfitter/tooling check-boundary-invocations
96
+ ```
97
+
98
+ When this fails, replace direct source execution with canonical command surfaces
99
+ (`outfitter repo ...` in monorepo scripts, or package bins for standalone use).
100
+
86
101
  ## Configuration Presets
87
102
 
88
103
  ### Biome
@@ -124,7 +139,7 @@ extends:
124
139
 
125
140
  Default hooks:
126
141
  - **pre-commit**: Runs ultracite on staged files, typechecks
127
- - **pre-push**: Runs build, then TDD-aware tests via `tooling pre-push`
142
+ - **pre-push**: Runs TDD-aware strict verification via `tooling pre-push`
128
143
 
129
144
  ### markdownlint
130
145
 
@@ -147,6 +162,18 @@ Available blocks:
147
162
  - `bootstrap` — Project bootstrap script
148
163
  - `scaffolding` — Full starter kit (combines all above)
149
164
 
165
+ ## Monorepo Command Mapping
166
+
167
+ Within this monorepo, maintenance checks are routed via `outfitter repo`:
168
+
169
+ ```bash
170
+ bun run apps/outfitter/src/cli.ts repo check exports --cwd .
171
+ bun run apps/outfitter/src/cli.ts repo check readme --cwd .
172
+ bun run apps/outfitter/src/cli.ts repo check registry --cwd .
173
+ bun run apps/outfitter/src/cli.ts repo check tree --cwd .
174
+ bun run apps/outfitter/src/cli.ts repo check boundary-invocations --cwd .
175
+ ```
176
+
150
177
  ## Exports
151
178
 
152
179
  | Export | Description |
package/biome.json CHANGED
@@ -1,74 +1,81 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3
- "root": false,
4
- "javascript": {
5
- "globals": ["Bun"]
6
- },
7
- "linter": {
8
- "rules": {
9
- "complexity": {
10
- "useLiteralKeys": "off",
11
- "noVoid": "off",
12
- "noExcessiveCognitiveComplexity": "off"
13
- },
14
- "performance": {
15
- "useTopLevelRegex": "off"
16
- },
17
- "style": {
18
- "useBlockStatements": "off"
19
- },
20
- "suspicious": {
21
- "noConsole": "error"
22
- }
23
- }
24
- },
25
- "vcs": {
26
- "enabled": true,
27
- "clientKind": "git",
28
- "useIgnoreFile": true
29
- },
30
- "files": {
31
- "ignoreUnknown": true,
32
- "includes": ["!**/node_modules", "!**/dist", "!**/.turbo", "!**/*.gen.ts"]
33
- },
34
- "overrides": [
35
- {
36
- "includes": ["packages/*/src/index.ts", "apps/*/src/index.ts", "**/index.ts"],
37
- "linter": {
38
- "rules": {
39
- "performance": {
40
- "noBarrelFile": "off"
41
- }
42
- }
43
- }
44
- },
45
- {
46
- "includes": ["**/*.test.ts", "**/__tests__/**/*"],
47
- "linter": {
48
- "rules": {
49
- "suspicious": {
50
- "useAwait": "off",
51
- "noConsole": "off"
52
- },
53
- "performance": {
54
- "noDelete": "off"
55
- }
56
- }
57
- }
58
- },
59
- {
60
- "includes": [
61
- "apps/**/*.ts",
62
- "scripts/**/*.ts",
63
- "**/scripts/**/*.ts"
64
- ],
65
- "linter": {
66
- "rules": {
67
- "suspicious": {
68
- "noConsole": "off"
69
- }
70
- }
71
- }
72
- }
73
- ]
2
+ "$schema": "https://biomejs.dev/schemas/2.3.12/schema.json",
3
+ "root": false,
4
+ "javascript": {
5
+ "globals": ["Bun"]
6
+ },
7
+ "linter": {
8
+ "rules": {
9
+ "complexity": {
10
+ "useLiteralKeys": "off",
11
+ "noVoid": "off",
12
+ "noExcessiveCognitiveComplexity": "off"
13
+ },
14
+ "performance": {
15
+ "useTopLevelRegex": "off"
16
+ },
17
+ "style": {
18
+ "useBlockStatements": "off"
19
+ },
20
+ "suspicious": {
21
+ "noConsole": "error"
22
+ }
23
+ }
24
+ },
25
+ "vcs": {
26
+ "enabled": true,
27
+ "clientKind": "git",
28
+ "useIgnoreFile": true
29
+ },
30
+ "files": {
31
+ "ignoreUnknown": true,
32
+ "includes": [
33
+ "**",
34
+ "!**/node_modules",
35
+ "!**/dist",
36
+ "!**/.turbo",
37
+ "!**/*.gen.ts",
38
+ "!registry/registry.json"
39
+ ]
40
+ },
41
+ "overrides": [
42
+ {
43
+ "includes": [
44
+ "packages/*/src/index.ts",
45
+ "apps/*/src/index.ts",
46
+ "**/index.ts"
47
+ ],
48
+ "linter": {
49
+ "rules": {
50
+ "performance": {
51
+ "noBarrelFile": "off"
52
+ }
53
+ }
54
+ }
55
+ },
56
+ {
57
+ "includes": ["**/*.test.ts", "**/__tests__/**/*"],
58
+ "linter": {
59
+ "rules": {
60
+ "suspicious": {
61
+ "useAwait": "off",
62
+ "noConsole": "off"
63
+ },
64
+ "performance": {
65
+ "noDelete": "off"
66
+ }
67
+ }
68
+ }
69
+ },
70
+ {
71
+ "includes": ["apps/**/*.ts", "scripts/**/*.ts", "**/scripts/**/*.ts"],
72
+ "linter": {
73
+ "rules": {
74
+ "suspicious": {
75
+ "noConsole": "off"
76
+ }
77
+ }
78
+ }
79
+ }
80
+ ]
74
81
  }
@@ -0,0 +1,34 @@
1
+ interface ScriptLocation {
2
+ readonly file: string;
3
+ readonly scriptName: string;
4
+ readonly command: string;
5
+ }
6
+ interface BoundaryViolation extends ScriptLocation {
7
+ readonly rule: "root-runs-package-src" | "cd-package-then-runs-src";
8
+ }
9
+ interface ReadScriptEntriesOptions {
10
+ readonly appManifestRelativePaths?: readonly string[];
11
+ readonly readPackageJson?: (filePath: string) => Promise<{
12
+ scripts?: Record<string, string>;
13
+ }>;
14
+ }
15
+ /**
16
+ * Detect whether a single script command violates boundary invocation rules.
17
+ */
18
+ declare function detectBoundaryViolation(location: ScriptLocation): BoundaryViolation | null;
19
+ /**
20
+ * Find all boundary violations across package/app script maps.
21
+ */
22
+ declare function findBoundaryViolations(entries: readonly {
23
+ file: string;
24
+ scripts: Readonly<Record<string, string>>;
25
+ }[]): BoundaryViolation[];
26
+ declare function readScriptEntries(cwd: string, options?: ReadScriptEntriesOptions): Promise<{
27
+ file: string;
28
+ scripts: Record<string, string>;
29
+ }[]>;
30
+ /**
31
+ * Run boundary invocation checks against root/apps package scripts.
32
+ */
33
+ declare function runCheckBoundaryInvocations(): Promise<void>;
34
+ export { runCheckBoundaryInvocations, readScriptEntries, findBoundaryViolations, detectBoundaryViolation, ScriptLocation, BoundaryViolation };
@@ -0,0 +1,14 @@
1
+ // @bun
2
+ import {
3
+ detectBoundaryViolation,
4
+ findBoundaryViolations,
5
+ readScriptEntries,
6
+ runCheckBoundaryInvocations
7
+ } from "../shared/@outfitter/tooling-r9976n43.js";
8
+ import"../shared/@outfitter/tooling-dvwh9qve.js";
9
+ export {
10
+ runCheckBoundaryInvocations,
11
+ readScriptEntries,
12
+ findBoundaryViolations,
13
+ detectBoundaryViolation
14
+ };
@@ -0,0 +1,36 @@
1
+ /** Result of checking bunup workspace registration */
2
+ interface RegistryCheckResult {
3
+ readonly ok: boolean;
4
+ readonly missing: string[];
5
+ }
6
+ /**
7
+ * Extract the package name from a build script containing `bunup --filter`.
8
+ *
9
+ * @example
10
+ * extractBunupFilterName("bunup --filter @outfitter/logging")
11
+ * // => "@outfitter/logging"
12
+ *
13
+ * extractBunupFilterName("cd ../.. && bunup --filter @outfitter/types")
14
+ * // => "@outfitter/types"
15
+ *
16
+ * extractBunupFilterName("tsc --noEmit")
17
+ * // => null
18
+ */
19
+ declare function extractBunupFilterName(script: string): string | null;
20
+ /**
21
+ * Find packages that have `bunup --filter` build scripts but are not
22
+ * registered in the bunup workspace config.
23
+ *
24
+ * @param packagesWithFilter - Package names that have `bunup --filter` in their build script
25
+ * @param registeredNames - Package names registered in bunup.config.ts
26
+ * @returns Result with sorted list of missing packages
27
+ */
28
+ declare function findUnregisteredPackages(packagesWithFilter: string[], registeredNames: string[]): RegistryCheckResult;
29
+ /**
30
+ * Run bunup registry check across all workspace packages.
31
+ *
32
+ * Scans packages/&#42;/package.json for build scripts containing `bunup --filter`,
33
+ * then verifies each is registered in bunup.config.ts.
34
+ */
35
+ declare function runCheckBunupRegistry(): Promise<void>;
36
+ export { runCheckBunupRegistry, findUnregisteredPackages, extractBunupFilterName, RegistryCheckResult };
@@ -0,0 +1,12 @@
1
+ // @bun
2
+ import {
3
+ extractBunupFilterName,
4
+ findUnregisteredPackages,
5
+ runCheckBunupRegistry
6
+ } from "../shared/@outfitter/tooling-t17gnh9b.js";
7
+ import"../shared/@outfitter/tooling-dvwh9qve.js";
8
+ export {
9
+ runCheckBunupRegistry,
10
+ findUnregisteredPackages,
11
+ extractBunupFilterName
12
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Check-changeset command — validates PRs touching package source include a changeset.
3
+ *
4
+ * Pure core functions for detecting changed packages and verifying changeset
5
+ * presence. The CLI runner in {@link runCheckChangeset} handles git discovery
6
+ * and output.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ /** Result of checking whether changesets are required */
11
+ interface ChangesetCheckResult {
12
+ readonly ok: boolean;
13
+ readonly missingFor: string[];
14
+ }
15
+ /**
16
+ * Extract unique package names from changed file paths.
17
+ *
18
+ * Only considers files matching the pattern "packages/NAME/src/..." and
19
+ * ignores apps/, root files, and package-level config.
20
+ *
21
+ * @param files - List of changed file paths relative to repo root
22
+ * @returns Sorted array of unique package names
23
+ */
24
+ declare function getChangedPackagePaths(files: string[]): string[];
25
+ /**
26
+ * Extract changeset filenames from changed file paths.
27
+ *
28
+ * Only considers files matching `.changeset/*.md`, excluding README.md.
29
+ * This checks the git diff rather than disk, ensuring only changesets added
30
+ * in the current PR are counted.
31
+ *
32
+ * @param files - List of changed file paths relative to repo root
33
+ * @returns Array of changeset filenames (e.g. `["happy-turtle.md"]`)
34
+ */
35
+ declare function getChangedChangesetFiles(files: string[]): string[];
36
+ /**
37
+ * Determine whether a changeset is required and present.
38
+ *
39
+ * Returns `ok: true` when either no packages were changed or at least one
40
+ * changeset file exists. Returns `ok: false` with the list of changed
41
+ * packages when changesets are missing.
42
+ *
43
+ * @param changedPackages - Package names with source changes
44
+ * @param changesetFiles - Changeset filenames found in `.changeset/`
45
+ */
46
+ declare function checkChangesetRequired(changedPackages: string[], changesetFiles: string[]): ChangesetCheckResult;
47
+ interface CheckChangesetOptions {
48
+ readonly skip?: boolean;
49
+ }
50
+ /**
51
+ * Run check-changeset to verify PRs include changeset files.
52
+ *
53
+ * Uses `git diff --name-only origin/main...HEAD` to detect changed files,
54
+ * then checks for changeset presence when package source files are modified.
55
+ *
56
+ * Skips silently when:
57
+ * - `NO_CHANGESET=1` env var is set
58
+ * - `--skip` flag is passed
59
+ * - `GITHUB_EVENT_NAME=push` (post-merge on main)
60
+ * - No packages have source changes
61
+ * - Git diff fails (local dev without origin)
62
+ */
63
+ declare function runCheckChangeset(options?: CheckChangesetOptions): Promise<void>;
64
+ export { runCheckChangeset, getChangedPackagePaths, getChangedChangesetFiles, checkChangesetRequired, CheckChangesetOptions, ChangesetCheckResult };
@@ -0,0 +1,14 @@
1
+ // @bun
2
+ import {
3
+ checkChangesetRequired,
4
+ getChangedChangesetFiles,
5
+ getChangedPackagePaths,
6
+ runCheckChangeset
7
+ } from "../shared/@outfitter/tooling-3w8vr2w3.js";
8
+ import"../shared/@outfitter/tooling-dvwh9qve.js";
9
+ export {
10
+ runCheckChangeset,
11
+ getChangedPackagePaths,
12
+ getChangedChangesetFiles,
13
+ checkChangesetRequired
14
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Check-clean-tree command — asserts the working tree has no modified or untracked files.
3
+ *
4
+ * Pure core functions for parsing git output and determining tree cleanliness.
5
+ * The CLI runner in {@link runCheckCleanTree} handles git invocation and output.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ /** Status of the working tree after verification steps */
10
+ interface TreeStatus {
11
+ readonly clean: boolean;
12
+ readonly modified: string[];
13
+ readonly untracked: string[];
14
+ }
15
+ /**
16
+ * Parse `git diff --name-only` output into a list of modified file paths.
17
+ */
18
+ declare function parseGitDiff(diffOutput: string): string[];
19
+ /**
20
+ * Parse `git ls-files --others --exclude-standard` output into a list of untracked file paths.
21
+ */
22
+ declare function parseUntrackedFiles(lsOutput: string): string[];
23
+ /**
24
+ * Determine if the tree status represents a clean working tree.
25
+ */
26
+ declare function isCleanTree(status: TreeStatus): boolean;
27
+ interface CheckCleanTreeOptions {
28
+ readonly paths?: string[];
29
+ }
30
+ /**
31
+ * Run clean-tree check against the current working directory.
32
+ *
33
+ * Exits 0 if clean, 1 if dirty files are found.
34
+ */
35
+ declare function runCheckCleanTree(options?: CheckCleanTreeOptions): Promise<void>;
36
+ export { runCheckCleanTree, parseUntrackedFiles, parseGitDiff, isCleanTree, TreeStatus, CheckCleanTreeOptions };
@@ -0,0 +1,14 @@
1
+ // @bun
2
+ import {
3
+ isCleanTree,
4
+ parseGitDiff,
5
+ parseUntrackedFiles,
6
+ runCheckCleanTree
7
+ } from "../shared/@outfitter/tooling-1y8w5ahg.js";
8
+ import"../shared/@outfitter/tooling-dvwh9qve.js";
9
+ export {
10
+ runCheckCleanTree,
11
+ parseUntrackedFiles,
12
+ parseGitDiff,
13
+ isCleanTree
14
+ };
@@ -0,0 +1,2 @@
1
+ import { CheckExportsOptions, CheckResult, CompareInput, ExportDrift, ExportMap, PackageResult, compareExports, entryToSubpath, runCheckExports } from "../shared/@outfitter/tooling-q0d60xb3";
2
+ export { runCheckExports, entryToSubpath, compareExports, PackageResult, ExportMap, ExportDrift, CompareInput, CheckResult, CheckExportsOptions };
@@ -0,0 +1,12 @@
1
+ // @bun
2
+ import {
3
+ compareExports,
4
+ entryToSubpath,
5
+ runCheckExports
6
+ } from "../shared/@outfitter/tooling-tf22zt9p.js";
7
+ import"../shared/@outfitter/tooling-dvwh9qve.js";
8
+ export {
9
+ runCheckExports,
10
+ entryToSubpath,
11
+ compareExports
12
+ };
@@ -0,0 +1,60 @@
1
+ import { ExportMap } from "../shared/@outfitter/tooling-q0d60xb3";
2
+ /** An import example extracted from a markdown code block */
3
+ interface ImportExample {
4
+ /** Package name, e.g. "@outfitter/cli" */
5
+ readonly packageName: string;
6
+ /** Export subpath, e.g. "./output" or "." */
7
+ readonly subpath: string;
8
+ /** Full import specifier, e.g. "@outfitter/cli/output" */
9
+ readonly fullSpecifier: string;
10
+ /** File where the import was found */
11
+ readonly file: string;
12
+ /** 1-based line number */
13
+ readonly line: number;
14
+ }
15
+ /** Result of checking imports in a single file */
16
+ interface ImportCheckResult {
17
+ readonly file: string;
18
+ readonly valid: ImportExample[];
19
+ readonly invalid: ImportExample[];
20
+ }
21
+ /**
22
+ * Parse a full import specifier into package name and subpath.
23
+ *
24
+ * Only recognizes `@outfitter/*` scoped packages.
25
+ *
26
+ * @example
27
+ * parseSpecifier("@outfitter/cli/output")
28
+ * // { packageName: "@outfitter/cli", subpath: "./output" }
29
+ *
30
+ * parseSpecifier("@outfitter/contracts")
31
+ * // { packageName: "@outfitter/contracts", subpath: "." }
32
+ */
33
+ declare function parseSpecifier(specifier: string): {
34
+ packageName: string;
35
+ subpath: string;
36
+ } | null;
37
+ /**
38
+ * Extract import specifiers from markdown content.
39
+ *
40
+ * Only extracts imports from fenced code blocks (typescript, ts,
41
+ * javascript, js). Skips blocks preceded by a non-contractual HTML comment.
42
+ * Deduplicates by full specifier within a single file.
43
+ */
44
+ declare function extractImports(content: string, file: string): ImportExample[];
45
+ /**
46
+ * Check whether a subpath exists in a package.json map.
47
+ */
48
+ declare function isExportedSubpath(subpath: string, exports: ExportMap): boolean;
49
+ interface CheckReadmeImportsOptions {
50
+ readonly json?: boolean;
51
+ }
52
+ /**
53
+ * Run check-readme-imports across all workspace packages.
54
+ *
55
+ * Finds README.md files in `packages/` and `docs/packages/`, extracts
56
+ * import examples, and validates each subpath against the corresponding
57
+ * package.json exports.
58
+ */
59
+ declare function runCheckReadmeImports(options?: CheckReadmeImportsOptions): Promise<void>;
60
+ export { runCheckReadmeImports, parseSpecifier, isExportedSubpath, extractImports, ImportExample, ImportCheckResult, ExportMap, CheckReadmeImportsOptions };