@antelopejs/tooling-configs 0.0.9 → 0.2.1

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.
package/README.md CHANGED
@@ -6,23 +6,30 @@
6
6
  <a href="https://discord.gg/sjK28QHrA7"><img src="https://img.shields.io/badge/Discord-18181B?logo=discord&style=for-the-badge&color=000000" alt="Discord"></a>
7
7
  </div>
8
8
 
9
- Shared lint, format and dead-code presets for AntelopeJS repositories, plus a check for the version ranges of interface dependencies.
9
+ The AntelopeJS guardrail pack: shared lint, format and dead-code presets, the commands that install and enforce them in a repository, and a check for the version ranges of interface dependencies.
10
10
 
11
11
  - [oxlint](https://oxc.rs) and [oxfmt](https://oxc.rs) replace Biome: lint, format and Tailwind class sorting, `.vue` included.
12
12
  - ESLint stays for the Nuxt front ends, from a shared config, until oxlint lints `.vue` files.
13
13
  - [Knip](https://knip.dev) learns the entry points of an AntelopeJS module.
14
14
  - Every preset is a function: options adjust it without copying it.
15
+ - `antelopejs-sync` writes the configs, hooks, scripts and agent instructions into a repository, and `antelopejs-sync --check` fails CI when they drift.
16
+ - Every lint rule is an error or off. Existing debt is recorded per repository and may only shrink.
15
17
 
16
18
  ## What's in the box
17
19
 
18
- | Export | Import | What it gives |
19
- | ----------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------- |
20
- | `./oxc/lint` | `import { antelopePreset } from "@antelopejs/tooling-configs/oxc/lint"` | The oxlint preset |
21
- | `./oxc/fmt` | `import { antelopeFmtPreset } from "@antelopejs/tooling-configs/oxc/fmt"` | The oxfmt preset (house style) |
22
- | `./eslint` | `import { antelopeNuxtConfig } from "@antelopejs/tooling-configs/eslint"` | ESLint for Nuxt layers |
23
- | `./knip` | `import { antelopeKnipConfig } from "@antelopejs/tooling-configs/knip"` | Knip for AntelopeJS modules |
24
- | `./oxc/anti-slop` | Loaded by the oxlint preset as a JS plugin | The vendored [anti-slop](https://github.com/dmmulroy/anti-slop) rules |
25
- | bin | `antelopejs-check-interface-ranges` | Fails on interface ranges that break module startup |
20
+ | Export | Import | What it gives |
21
+ | ------------------ | ------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
22
+ | `./oxc/lint` | `import { antelopePreset } from "@antelopejs/tooling-configs/oxc/lint"` | The oxlint preset |
23
+ | `./oxc/fmt` | `import { antelopeFmtPreset } from "@antelopejs/tooling-configs/oxc/fmt"` | The oxfmt preset (house style) |
24
+ | `./eslint` | `import { antelopeNuxtConfig } from "@antelopejs/tooling-configs/eslint"` | ESLint for Nuxt layers |
25
+ | `./knip` | `import { antelopeKnipConfig } from "@antelopejs/tooling-configs/knip"` | Knip for AntelopeJS modules |
26
+ | `./oxc/anti-slop` | Loaded by the oxlint preset as a JS plugin | The vendored [anti-slop](https://github.com/dmmulroy/anti-slop) rules |
27
+ | `./oxc/guardrails` | Loaded by the oxlint preset as a JS plugin | The `antelopejs` comment and test-quality rules |
28
+ | bin | `antelopejs-sync` | Writes the guardrail pack into a repository; `--check` reports drift |
29
+ | bin | `antelopejs-checks` | Runs every check and prints only the failures |
30
+ | bin | `antelopejs-ratchet` | Fails when recorded debt grows; `--update` lowers the record |
31
+ | bin | `antelopejs-check-size` | Fails on authored files over 20,000 bytes and on blanket disable directives |
32
+ | bin | `antelopejs-check-interface-ranges` | Fails on interface ranges that break module startup |
26
33
 
27
34
  ## Install
28
35
 
@@ -74,12 +81,25 @@ export default defineConfig({
74
81
  | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
75
82
  | oxc | the `correctness` category, with the `eslint`, `typescript`, `node`, `oxc`, `import` and `promise` plugins; `no-unused-vars` (`_` prefix allowed), `eqeqeq` (`== null` allowed), `radix`, `prefer-regex-literals` | error |
76
83
  | Imports | `import/no-cycle`, `import/no-self-import`, `import/no-duplicates` | error |
77
- | Type-aware | `typescript/no-floating-promises` as an error, eight more type-aware rules as warnings | on |
78
- | Complexity | `max-params` 5, `max-lines-per-function` 120, `max-lines` 500, `max-depth` 4, `complexity` 20 | warn |
79
- | Anti-slop | 7 of the 15 vendored rules; the 8 others are listed in `ANTI_SLOP_RULES_OFF_BY_DEFAULT` | warn |
84
+ | Type-aware | `typescript/no-floating-promises` and eight more type-aware rules | error |
85
+ | Complexity | `max-params` 5, `max-lines-per-function` 120, `max-lines` 500, `max-depth` 4, `complexity` 20 | error |
86
+ | Anti-slop | all 15 vendored rules | error |
87
+ | Guardrails | `antelopejs/no-comments`; in test files `antelopejs/no-fs-read-in-tests`, `antelopejs/no-constant-value-assertion`, `antelopejs/no-typeof-function-only-test` and `antelopejs/require-assertion` | error |
80
88
  | Import sorting | `perfectionist/sort-imports`, autofixed by `oxlint --fix` | off |
81
89
 
82
- `correctness` is raised to error on purpose: oxlint reports it as warnings, and warnings never fail the command. Complexity and anti-slop start as warnings so a repository can work through its backlog before raising them to `"error"`.
90
+ No rule warns. oxlint reports `correctness` as warnings by default, and warnings never fail the command, so the preset raises it to error. A repository with existing findings records them in `guardrails.ratchet.json` instead of lowering a severity (see [Guardrail pack](#guardrail-pack)).
91
+
92
+ The guardrail rules:
93
+
94
+ | Rule | Fails on |
95
+ | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
96
+ | `antelopejs/no-comments` | `//` and `/* */` comments. Allowed: TSDoc `/** */`, `SAFETY: <reason>` (one block, or a run of `//` lines), `/*!` license headers, `@ts-expect-error <reason>`, oxlint/eslint directives that name their rules, `/// <reference />`, `#__PURE__`/`@__PURE__`, `@vite-ignore` and webpack magic comments, `prettier-ignore`/`oxfmt-ignore` |
97
+ | `antelopejs/no-fs-read-in-tests` | `readFileSync` or `readdirSync` from `fs` in a test file. Files under `fixtures/`, `helpers/` and `locales/` may read |
98
+ | `antelopejs/require-assertion` | a test with no assertion. Counts: calls named `expect*` or `assert*`, `sinon.assert.*`, supertest `.expect(...)`, and should-style `x.should…` or `should(x)` |
99
+ | `antelopejs/no-constant-value-assertion` | `expect(X).toBe(literal)` where the root of `X` is an UPPER_SNAKE constant (`MAX_ITEMS`, `NAMES.if`, not `process.env.NODE_ENV`); also `.toEqual`, `.to.equal`, `.to.eq`, `.eql` and synonyms |
100
+ | `antelopejs/no-typeof-function-only-test` | a test whose only assertions are `toBeTypeOf("function")`, `to.be.a("function")` or equivalents |
101
+
102
+ Test files are `*.test.*`, `*.spec.*`, and files under `test/`, `tests/` and `__tests__/`, whatever the framework. The preset keeps four framework-neutral Jest-plugin rules: `no-disabled-tests`, `no-focused-tests`, `valid-describe-callback` and `valid-title`.
83
103
 
84
104
  Import sorting is off because it moves value imports across side-effect imports, and in an AntelopeJS module `import "./components"` is what registers the decorated classes. Turn it on only where import order does not matter.
85
105
 
@@ -87,9 +107,10 @@ Import sorting is off because it moves value imports across side-effect imports,
87
107
 
88
108
  ```ts
89
109
  antelopePreset({
90
- antiSlop: "error", // "warn" (default) | "error" | false
91
- importCycles: "warn", // "error" (default) | "warn" | false
92
- complexity: { maxParams: 8 }, // override thresholds or severity, or false
110
+ antiSlop: false, // true (default)
111
+ guardrails: false, // true (default)
112
+ importCycles: false, // true (default)
113
+ complexity: { maxParams: 8 }, // override thresholds, or false
93
114
  importSorting: true, // false (default); needs eslint-plugin-perfectionist
94
115
  typeAware: false, // true (default); false when the repository has no oxlint-tsgolint
95
116
  });
@@ -113,6 +134,50 @@ export default defineConfig({
113
134
  });
114
135
  ```
115
136
 
137
+ ## Guardrail pack
138
+
139
+ Run `antelopejs-sync` at the repository root, then install dependencies. It is idempotent: a second run changes nothing.
140
+
141
+ ```bash
142
+ pnpm add -D @antelopejs/tooling-configs oxlint@1.81.0 oxlint-tsgolint oxfmt
143
+ pnpm exec antelopejs-sync
144
+ pnpm install
145
+ ```
146
+
147
+ | File | What `sync` does |
148
+ | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
149
+ | `oxlint.config.ts`, `oxfmt.config.ts`, `knip.config.ts` | Writes a config that extends the preset, unless the file already imports it |
150
+ | `lefthook.yml` | Pre-commit on staged files: oxfmt, oxlint, size. Pre-push: typecheck |
151
+ | `package.json` | `prepare` installs lefthook. Sets `checks`, `size`, `ratchet`, `ratchet:update`, `sync`, `sync:check`; adds missing `typecheck`, `lint`, `format`, `format:check`, `knip`; adds `lefthook` and `knip` |
152
+ | `.nvmrc` | `24` |
153
+ | `.agents/setup` | Orb setup: switches to the `.nvmrc` Node, activates `packageManager` through corepack, installs with the frozen lockfile |
154
+ | `AGENTS.md` | Writes the managed block between `<!-- antelopejs-guardrails:start -->` and `:end -->`; text outside the markers stays |
155
+ | `CLAUDE.md` | `@AGENTS.md` |
156
+ | `guardrails.ratchet.json` | Records the current findings, once, when the file is missing |
157
+
158
+ `--profile template` writes only the three preset configs and a user-facing `AGENTS.md` block, for template repositories. `antelopejs-sync --check` writes nothing and exits 1 on any drift; `pnpm run checks` runs it.
159
+
160
+ `pnpm run checks` runs `typecheck`, `lint`, `format:check`, `knip`, `test`, `size`, `ratchet` and `sync:check`, and prints only the output of the steps that failed.
161
+
162
+ ### Ratchet
163
+
164
+ `guardrails.ratchet.json` holds the debt a repository had when it adopted the pack:
165
+
166
+ ```json
167
+ {
168
+ "rules": { "antelopejs/no-comments": 22, "eslint/max-depth": 1 },
169
+ "oversizeFiles": { "src/legacy.ts": 31250 }
170
+ }
171
+ ```
172
+
173
+ - A rule listed under `rules` is off for `oxlint`, so editors, hooks and `lint` stay green. `antelopejs-ratchet` counts it with every rule on, and fails when a count rises. It prints the findings in the files the change touched.
174
+ - A file listed under `oversizeFiles` may exceed 20,000 bytes and `max-lines`, up to its recorded size. Any other file over either limit fails.
175
+ - `antelopejs-ratchet --update` lowers each number to the current count and removes what reached zero. It never raises a number or adds an entry. Commit the lowered file.
176
+
177
+ ### Size
178
+
179
+ `antelopejs-check-size` fails on an authored file over 20,000 bytes, tests included. Generated code, fixtures, lockfiles, `CHANGELOG.md`, Markdown and binary assets are excluded. Pass paths to check only those files, as the pre-commit hook does. It also fails on an `oxlint-disable` or `eslint-disable` directive (line, next-line or file form) that names no rule: oxlint applies such a directive before any rule runs, so `no-comments` cannot report it.
180
+
116
181
  ## oxfmt
117
182
 
118
183
  ```ts
@@ -159,7 +224,7 @@ import { antelopeNuxtConfig } from "@antelopejs/tooling-configs/eslint";
159
224
  export default antelopeNuxtConfig({ dirs: ["./playground"] });
160
225
  ```
161
226
 
162
- `@nuxt/eslint-config` supplies the Vue and TypeScript rules. The preset only records where AntelopeJS layers differ: single-word page components, `any` and `{}` allowed, `_`-prefixed unused bindings, and import order left alone. It sets no formatting rule, since oxfmt formats `.vue`. Pass `rules` to layer your own on top, and declare `@nuxt/eslint-config` in the front end's `package.json`.
227
+ `@nuxt/eslint-config` supplies the Vue and TypeScript rules. The preset only records where AntelopeJS layers differ: single-word page components, `any` and `{}` allowed, `_`-prefixed unused bindings, and import order left alone. It sets no formatting rule, since oxfmt formats `.vue`. Every rule the resolved config sets to warn becomes an error, so no rule warns there either. Pass `rules` to layer your own on top, and declare `@nuxt/eslint-config` in the front end's `package.json`.
163
228
 
164
229
  ## Knip
165
230
 
@@ -214,7 +279,7 @@ checks that remain the author's responsibility.
214
279
 
215
280
  ## Contributing
216
281
 
217
- See [CONTRIBUTING.md](./CONTRIBUTING.md). `pnpm install`, then `pnpm checks` runs the typecheck, lint, format check and tests.
282
+ See [CONTRIBUTING.md](./CONTRIBUTING.md). `pnpm install`, then `pnpm checks` runs the typecheck, lint, format check, tests, size check and ratchet.
218
283
 
219
284
  ## License
220
285
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { execFileSync } from "node:child_process";
3
2
  import { readFileSync } from "node:fs";
4
3
  import { join, relative } from "node:path";
4
+ import { execFileSync } from "node:child_process";
5
5
  //#region src/interface-ranges.ts
6
6
  /**
7
7
  * At startup `@antelopejs/core` keeps one copy of each interface package, the
@@ -18,11 +18,13 @@ import { join, relative } from "node:path";
18
18
  * is 0.x.
19
19
  */
20
20
  const INTERFACE_PACKAGE_PREFIX = "@antelopejs/interface-";
21
+ /** A module's own interface linked from the workspace is the copy it builds against, not a release it resolves. */
21
22
  const LOCAL_SPEC_PREFIXES = [
22
23
  "workspace:",
23
24
  "file:",
24
25
  "link:"
25
26
  ];
27
+ /** The fields `@antelopejs/core` checks at startup. */
26
28
  const CHECKED_FIELDS = ["dependencies", "optionalDependencies"];
27
29
  const BOUNDED_RANGE = /^>=(\d+)\.(\d+)\.(\d+) <(\d+)\.(\d+)\.(\d+)$/;
28
30
  const SINGLE_VERSION = /^[\^~=]?v?(\d+)\.(\d+)\.(\d+)$/;
@@ -66,6 +68,7 @@ function readFloor(spec) {
66
68
  function compareVersions(a, b) {
67
69
  return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
68
70
  }
71
+ /** A range is accepted when it is bounded for its role and admits the interface this package builds against. */
69
72
  function isAcceptedRange(spec, role, local) {
70
73
  const bounded = BOUNDED_RANGE.exec(spec);
71
74
  if (!bounded) return false;
@@ -109,6 +112,12 @@ function describeViolation(violation) {
109
112
  }
110
113
  //#endregion
111
114
  //#region src/bin/check-interface-ranges.ts
115
+ /**
116
+ * Every manifest in the repository by default, whatever directory the lint
117
+ * runs from: playgrounds and front-end layers are loaded by the runtime too, a
118
+ * playground is where a stale interface range first broke a startup, and an
119
+ * implemented interface usually sits in a sibling package.
120
+ */
112
121
  function trackedManifests() {
113
122
  const git = (args) => execFileSync("git", args, { encoding: "utf8" }).trim();
114
123
  const root = git(["rev-parse", "--show-toplevel"]);
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ import { a as repositoryRoot, i as repositoryPath, o as runCli, t as authoredSizes } from "../files-Bocv-qA8.mjs";
3
+ import { t as checkSize } from "../size-DJ7YSry_.mjs";
4
+ import { existsSync, readFileSync } from "node:fs";
5
+ import { join, resolve } from "node:path";
6
+ import { spawnSync } from "node:child_process";
7
+ import { parseArgs } from "node:util";
8
+ //#region src/guardrails/directives.ts
9
+ const CODE_FILE = /\.(?:[cm]?[jt]sx?|vue)$/u;
10
+ const BLANKET_DISABLE = /(?:\/\*|\/\/)\s*((?:eslint|oxlint)-disable(?:-line|-next-line)?)\s*(?:--[^\n]*?)?(?:\*\/|$)/gmu;
11
+ function fileText(root, file, staged) {
12
+ if (!staged) {
13
+ const path = join(root, file);
14
+ return existsSync(path) ? readFileSync(path, "utf8") : "";
15
+ }
16
+ const result = spawnSync("git", ["show", `:${file}`], {
17
+ cwd: root,
18
+ encoding: "utf8",
19
+ maxBuffer: 67108864
20
+ });
21
+ if (result.error) throw result.error;
22
+ return result.status === 0 ? result.stdout : "";
23
+ }
24
+ /** Reports disable directives without a rule list: oxlint honours them before any rule runs, so they also silence no-comments. */
25
+ function checkBlanketDisables(root, files, staged = false) {
26
+ const failures = [];
27
+ for (const file of authoredSizes(root, files, staged).keys()) {
28
+ if (!CODE_FILE.test(file)) continue;
29
+ const text = fileText(root, file, staged);
30
+ for (const match of text.matchAll(BLANKET_DISABLE)) {
31
+ const line = text.slice(0, match.index).split("\n").length;
32
+ failures.push(`${file}:${line}: \`${match[1]}\` without a rule list disables every rule, the comment ban included. Name the rule(s) and give a reason, for example: oxlint-disable-next-line no-debugger -- debugging this operation.`);
33
+ }
34
+ }
35
+ return failures;
36
+ }
37
+ //#endregion
38
+ //#region src/bin/check-size.ts
39
+ runCli(() => {
40
+ const root = repositoryRoot();
41
+ const { values, positionals } = parseArgs({
42
+ options: { staged: { type: "boolean" } },
43
+ allowPositionals: true
44
+ });
45
+ const files = positionals.length ? positionals.map((file) => repositoryPath(root, resolve(file))) : void 0;
46
+ const failures = [...checkSize(root, files, values.staged), ...checkBlanketDisables(root, files, values.staged)];
47
+ for (const failure of failures) process.stderr.write(`${failure}\n`);
48
+ return failures.length ? 1 : 0;
49
+ });
50
+ //#endregion
51
+ export {};
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ import { a as repositoryRoot, o as runCli } from "../files-Bocv-qA8.mjs";
3
+ import { i as parseManifest, r as packageManager } from "../package-B1aipTbn.mjs";
4
+ import { readFileSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { spawnSync } from "node:child_process";
7
+ //#region src/guardrails/checks.ts
8
+ const CHECK_STEPS = [
9
+ "typecheck",
10
+ "lint",
11
+ "format:check",
12
+ "knip",
13
+ "test",
14
+ "size",
15
+ "ratchet",
16
+ "sync:check"
17
+ ];
18
+ function runChecks(root) {
19
+ const manifest = parseManifest(readFileSync(join(root, "package.json"), "utf8"));
20
+ const manager = packageManager(manifest);
21
+ const failures = [];
22
+ for (const step of CHECK_STEPS) {
23
+ if (!manifest.scripts?.[step]) {
24
+ failures.push(`[${step}] Missing package.json script "${step}". Run antelopejs-sync.\n`);
25
+ continue;
26
+ }
27
+ const result = spawnSync(manager, ["run", step], {
28
+ cwd: root,
29
+ encoding: "utf8",
30
+ env: {
31
+ ...process.env,
32
+ CI: "1"
33
+ },
34
+ maxBuffer: 67108864
35
+ });
36
+ if (result.status !== 0) failures.push(`[${step}]\n${result.stdout ?? ""}${result.stderr ?? ""}${result.error ? `${result.error.message}\n` : ""}${result.signal ? `Terminated by ${result.signal}\n` : ""}`);
37
+ }
38
+ return {
39
+ failed: failures.length,
40
+ output: `${failures.join("\n")}Checks: ${CHECK_STEPS.length - failures.length} passed, ${failures.length} failed.\n`
41
+ };
42
+ }
43
+ //#endregion
44
+ //#region src/bin/checks.ts
45
+ runCli(() => {
46
+ const result = runChecks(repositoryRoot());
47
+ process.stdout.write(result.output);
48
+ return result.failed ? 1 : 0;
49
+ });
50
+ //#endregion
51
+ export {};
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ import { o as readCeilings } from "../ceilings--pJmhSde.mjs";
3
+ import { a as repositoryRoot, i as repositoryPath, o as runCli } from "../files-Bocv-qA8.mjs";
4
+ import { n as ratchet, r as lintDiagnostics } from "../ratchet-B2-4XxAl.mjs";
5
+ import { resolve } from "node:path";
6
+ import { execFileSync } from "node:child_process";
7
+ import { parseArgs } from "node:util";
8
+ //#region src/guardrails/staged-ratchet.ts
9
+ function stagedRatchet(root, files) {
10
+ const targets = files ?? execFileSync("git", [
11
+ "diff",
12
+ "--cached",
13
+ "--name-only",
14
+ "--diff-filter=ACMR",
15
+ "-z"
16
+ ], {
17
+ cwd: root,
18
+ encoding: "utf8"
19
+ }).split("\0").filter(Boolean);
20
+ if (!targets.length) return [];
21
+ const additions = /* @__PURE__ */ new Map();
22
+ for (const file of targets) {
23
+ const diff = execFileSync("git", [
24
+ "diff",
25
+ "--cached",
26
+ "--no-ext-diff",
27
+ "--no-color",
28
+ "--unified=0",
29
+ "--",
30
+ file
31
+ ], {
32
+ cwd: root,
33
+ encoding: "utf8"
34
+ });
35
+ additions.set(file, Array.from(diff.matchAll(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm), ([, line, count]) => ({
36
+ start: Number(line),
37
+ end: Number(line) + Number(count ?? 1) - 1
38
+ })));
39
+ }
40
+ const ceilings = readCeilings(root);
41
+ return lintDiagnostics(root, void 0, targets).filter(({ rule, file, line }) => Object.hasOwn(ceilings.rules, rule) && line !== void 0 && additions.get(file)?.some(({ start, end }) => line >= start && line <= end)).map((diagnostic) => `${diagnostic.location}: ${diagnostic.message} [${diagnostic.rule}]\n Fix: ${diagnostic.help ?? "Resolve this finding on the added line; the ceiling covers only legacy findings on untouched lines."}`);
42
+ }
43
+ //#endregion
44
+ //#region src/bin/ratchet.ts
45
+ runCli(() => {
46
+ const { values, positionals } = parseArgs({
47
+ options: {
48
+ update: { type: "boolean" },
49
+ staged: { type: "boolean" }
50
+ },
51
+ allowPositionals: true
52
+ });
53
+ const root = repositoryRoot();
54
+ if (values.update && values.staged) throw new Error("--staged cannot be combined with --update.");
55
+ if (positionals.length && !values.staged) throw new Error("File arguments require --staged.");
56
+ const result = values.staged ? {
57
+ failures: stagedRatchet(root, positionals.length ? positionals.map((file) => repositoryPath(root, resolve(file))) : void 0),
58
+ lowered: []
59
+ } : ratchet(root, values.update);
60
+ for (const message of result.lowered) process.stdout.write(`Lowered ${message}\n`);
61
+ for (const message of result.failures) process.stderr.write(`${message}\n`);
62
+ if (!result.failures.length) process.stdout.write("Ratchet: within ceilings.\n");
63
+ return result.failures.length ? 1 : 0;
64
+ });
65
+ //#endregion
66
+ export {};
@@ -0,0 +1 @@
1
+ export {}