@monte3l/groundwork 0.1.0-next.1 → 1.0.0-rc.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.
- package/README.md +16 -8
- package/bin/m3l-groundwork.mjs +36 -2
- package/dist/assets.d.ts +10 -0
- package/dist/assets.js +14 -0
- package/dist/baseline-stage.d.ts +173 -0
- package/dist/baseline-stage.js +215 -0
- package/dist/caps.d.ts +4 -1
- package/dist/caps.js +17 -3
- package/dist/conflicts.d.ts +23 -2
- package/dist/conflicts.js +89 -11
- package/dist/customize-paths.d.ts +92 -0
- package/dist/customize-paths.js +115 -0
- package/dist/emit.d.ts +50 -1
- package/dist/emit.js +121 -13
- package/dist/fatal.d.ts +70 -0
- package/dist/fatal.js +132 -0
- package/dist/format-error.d.ts +113 -0
- package/dist/format-error.js +553 -0
- package/dist/fs-guard.d.ts +142 -0
- package/dist/fs-guard.js +222 -0
- package/dist/git.js +10 -1
- package/dist/harness/conformance.js +2 -0
- package/dist/harness/frontmatter.js +2 -13
- package/dist/harness/grade.js +37 -8
- package/dist/harness/rules.d.ts +20 -3
- package/dist/harness/rules.js +108 -6
- package/dist/harness/types.d.ts +13 -0
- package/dist/harness/types.js +3 -0
- package/dist/inventory.d.ts +77 -3
- package/dist/inventory.js +103 -12
- package/dist/jsonc.d.ts +49 -2
- package/dist/jsonc.js +140 -7
- package/dist/main.d.ts +62 -3
- package/dist/main.js +538 -67
- package/dist/merge-json.d.ts +47 -4
- package/dist/merge-json.js +120 -8
- package/dist/mode.js +12 -2
- package/dist/pack-stage.d.ts +210 -0
- package/dist/pack-stage.js +287 -0
- package/dist/packs.d.ts +19 -13
- package/dist/packs.js +231 -28
- package/dist/palette.d.ts +23 -0
- package/dist/palette.js +22 -0
- package/dist/plugin.d.ts +122 -6
- package/dist/plugin.js +687 -47
- package/dist/report.d.ts +21 -2
- package/dist/report.js +93 -5
- package/dist/staging.d.ts +176 -0
- package/dist/staging.js +375 -0
- package/dist/survey/fs-walk.d.ts +34 -2
- package/dist/survey/fs-walk.js +70 -5
- package/dist/survey/internal/blocked-path.d.ts +27 -0
- package/dist/survey/internal/blocked-path.js +129 -0
- package/dist/survey/internal/package-json.d.ts +13 -0
- package/dist/survey/internal/package-json.js +37 -0
- package/dist/survey/internal/read-guard.d.ts +178 -0
- package/dist/survey/internal/read-guard.js +276 -0
- package/dist/survey/survey-docs.d.ts +17 -2
- package/dist/survey/survey-docs.js +61 -21
- package/dist/survey/survey-harness.d.ts +20 -2
- package/dist/survey/survey-harness.js +87 -46
- package/dist/survey/survey-shape.d.ts +17 -2
- package/dist/survey/survey-shape.js +60 -46
- package/dist/survey/survey-toolchain.d.ts +16 -1
- package/dist/survey/survey-toolchain.js +69 -66
- package/dist/survey/survey.js +6 -4
- package/dist/survey/types.d.ts +79 -0
- package/dist/survey/types.js +2 -6
- package/dist/term.d.ts +80 -0
- package/dist/term.js +145 -0
- package/dist/tokens.js +2 -0
- package/dist/toolchain/conformance.js +2 -0
- package/dist/toolchain/grade.js +26 -8
- package/dist/toolchain/rules.d.ts +13 -4
- package/dist/toolchain/rules.js +16 -0
- package/dist/toolchain/tsconfig-chain.d.ts +2 -0
- package/dist/toolchain/tsconfig-chain.js +32 -8
- package/dist/toolchain/types.d.ts +16 -4
- package/dist/toolchain/types.js +3 -0
- package/package.json +4 -3
- package/plugin/skills/customize/SKILL.md +292 -18
- package/plugin/src/domain-map.ts +39 -14
- package/plugin/src/index.ts +5 -1
- package/plugin/src/kind-facet-map.ts +25 -8
- package/plugin/src/pack-map.ts +147 -25
- package/plugin/src/plugin-map.ts +236 -0
- package/templates/core/.claude/agents/Explore.md +0 -1
- package/templates/core/.claude/agents/code-implementer.md +4 -4
- package/templates/core/.claude/agents/code-reviewer.md +4 -4
- package/templates/core/.claude/agents/silent-failure-hunter.md +2 -2
- package/templates/core/.claude/agents/test-author.md +7 -5
- package/templates/core/.claude/hooks/guard-branch-isolation.mjs +56 -10
- package/templates/core/.claude/hooks/guard-double-background.mjs +13 -8
- package/templates/core/.claude/hooks/guard-git-push-signed.mjs +12 -9
- package/templates/core/.claude/hooks/guard-hub-src-writes.mjs +1890 -38
- package/templates/core/.claude/hooks/guard-js-extension.mjs +2 -1
- package/templates/core/.claude/hooks/guard-no-commonjs.mjs +7 -5
- package/templates/core/.claude/hooks/guard-secret-writes.mjs +7 -5
- package/templates/core/.claude/hooks/inject-decision-gate.mjs +12 -9
- package/templates/core/.claude/hooks/post-edit-verify.mjs +276 -98
- package/templates/core/.claude/rules/agent-dispatch.md +7 -0
- package/templates/core/.claude/rules/tests.md +2 -2
- package/templates/core/.claude/settings.json +5 -0
- package/templates/core/.claude/skills/finishing-work/SKILL.md +58 -10
- package/templates/core/.claude/skills/harness-guidance/SKILL.md +16 -7
- package/templates/core/.claude/skills/starting-work/SKILL.md +5 -0
- package/templates/core/.claude/skills/triaging-ci/SKILL.md +9 -8
- package/templates/core/.claude/skills/typescript-guidance/SKILL.md +137 -20
- package/templates/core/.claude/skills/typescript-guidance/references/area-catalog.md +135 -0
- package/templates/core/.claude/skills/typescript-guidance/references/tooling-sources.md +113 -0
- package/templates/core/.claude/skills/writing-commits/SKILL.md +2 -2
- package/templates/core/.github/dependabot.yml +18 -0
- package/templates/core/.github/workflows/ci.yml +15 -15
- package/templates/core/.github/workflows/dependency-review.yml +2 -2
- package/templates/core/.github/workflows/security-audit.yml +10 -4
- package/templates/core/.prettierignore +4 -0
- package/templates/core/CLAUDE.md +53 -3
- package/templates/core/README.md +30 -10
- package/templates/core/_gitignore +17 -0
- package/templates/core/bin/check-exports.mjs +11 -5
- package/templates/core/bin/lib/agent-roster.mjs +1 -1
- package/templates/core/bin/lib/frontmatter.mjs +4 -2
- package/templates/core/bin/lib/harness-rules.mjs +169 -20
- package/templates/core/bin/lib/protected-paths.mjs +93 -5
- package/templates/core/bin/lib/toolchain-rules.mjs +187 -26
- package/templates/core/bin/lib/verify-steps.mjs +29 -11
- package/templates/core/bin/verify.mjs +12 -0
- package/templates/core/eslint.config.js +5 -0
- package/templates/core/package.json +7 -7
- package/templates/core/vitest.config.ts +8 -1
- package/templates/packs/README.md +35 -24
- package/templates/packs/github/files/.claude/skills/reviewing-dependabot-prs/SKILL.md +133 -0
- package/templates/packs/github/files/.claude/skills/triaging-scan-alerts/SKILL.md +88 -0
- package/templates/packs/github/files/.claude/skills/watching-pr-checks/SKILL.md +94 -0
- package/templates/packs/github/files/.github/workflows/claude-pr-review.yml +267 -0
- package/templates/packs/github/files/.github/workflows/claude.yml +106 -0
- package/templates/packs/github/pack.json +19 -0
- package/templates/packs/harness-extras/files/.claude/hooks/guard-readonly-bash.mjs +1122 -65
- package/templates/packs/harness-extras/files/.claude/hooks/reinject-compact-handoff.mjs +147 -13
- package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/statusline.mjs +6 -2
- package/templates/packs/harness-extras/files/.claude/hooks/write-compact-handoff.mjs +227 -44
- package/templates/packs/harness-extras/pack.json +18 -13
- package/templates/packs/publishing/files/.changeset/README.md +25 -0
- package/templates/packs/publishing/files/.changeset/config.json +7 -0
- package/templates/packs/publishing/files/.github/release-tools/package.json +9 -0
- package/templates/packs/publishing/files/.github/workflows/release.yml +293 -0
- package/templates/packs/publishing/files/REUSE.toml +28 -0
- package/templates/packs/publishing/files/bin/check-dts-deps.mjs +234 -0
- package/templates/packs/publishing/files/bin/check-license-headers.mjs +217 -0
- package/templates/packs/publishing/files/bin/check-publish-version.mjs +149 -0
- package/templates/packs/publishing/files/bin/lib/npm-publish-args.mjs +86 -0
- package/templates/packs/publishing/files/bin/pnpm-publish-shim.mjs +86 -0
- package/templates/packs/publishing/pack.json +35 -0
- package/templates/packs/{harness-extras → quality}/files/bin/check-file-budget.mjs +6 -4
- package/templates/packs/quality/pack.json +29 -0
- package/templates/packs/supply-chain/files/.github/workflows/gitleaks.yml +52 -0
- package/templates/packs/supply-chain/files/.github/workflows/scorecard.yml +48 -0
- package/templates/packs/supply-chain/files/.gitleaks.toml +2 -0
- package/templates/packs/supply-chain/pack.json +19 -0
- package/templates/packs/worktrees/files/.claude/hooks/ensure-worktree-deps.mjs +283 -0
- package/templates/packs/worktrees/files/.claude/hooks/guard-worktree-only.mjs +245 -0
- package/templates/packs/worktrees/files/.claude/hooks/repair-core-bare.mjs +335 -0
- package/templates/packs/worktrees/files/.claude/skills/working-in-worktrees/SKILL.md +139 -0
- package/templates/packs/worktrees/files/.worktreeinclude +11 -0
- package/templates/packs/worktrees/pack.json +64 -0
- package/templates/packs/statusline/pack.json +0 -31
- /package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/statusline-layout.mjs +0 -0
- /package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/subagent-statusline.mjs +0 -0
- /package/templates/packs/{harness-extras → quality}/files/.claude/agents/type-design-analyzer.md +0 -0
- /package/templates/packs/{harness-extras → quality}/files/bin/file-budget-baseline.json +0 -0
package/dist/toolchain/rules.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright the m3l-groundwork contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
1
3
|
const NONE = { checked: 0, failures: [] };
|
|
2
4
|
const lower = (value) => typeof value === "string" ? value.toLowerCase() : undefined;
|
|
3
5
|
/**
|
|
@@ -185,6 +187,7 @@ function scriptTsconfig(script) {
|
|
|
185
187
|
const match = /\btsc\b[^&|;\n]*?\s(?:-b|--build|-p|--project)\s+(?:--\S+\s+)*([^\s&|;]+\.json)/.exec(script);
|
|
186
188
|
return match?.[1]?.replace(/^\.\//, "");
|
|
187
189
|
}
|
|
190
|
+
/** Confirms every CI/lefthook lane invokes verify.mjs by static group name, not by step id or a dynamic matrix -- otherwise a new gate can silently go unenforced in one surface while it passes in another. */
|
|
188
191
|
const gateLaneParity = {
|
|
189
192
|
id: "gate-lane-parity",
|
|
190
193
|
level: "structural",
|
|
@@ -241,6 +244,7 @@ function enginesBounds(range) {
|
|
|
241
244
|
};
|
|
242
245
|
}
|
|
243
246
|
// --- structural rules ------------------------------------------------------
|
|
247
|
+
/** A tsconfig that fails to parse breaks every rule that reads its chain -- reporting the parse error itself, first, keeps a later rule's silence from being mistaken for a clean file. */
|
|
244
248
|
const tsconfigParses = {
|
|
245
249
|
id: "tsconfig-parses",
|
|
246
250
|
level: "structural",
|
|
@@ -255,6 +259,7 @@ const tsconfigParses = {
|
|
|
255
259
|
})),
|
|
256
260
|
}),
|
|
257
261
|
};
|
|
262
|
+
/** An `extends` specifier that resolves to no file silently drops every option the base file would have set -- tsc itself gives no error until something downstream trips on the missing option. */
|
|
258
263
|
const tsconfigExtendsResolves = {
|
|
259
264
|
id: "tsconfig-extends-resolves",
|
|
260
265
|
level: "structural",
|
|
@@ -274,6 +279,7 @@ const tsconfigExtendsResolves = {
|
|
|
274
279
|
};
|
|
275
280
|
},
|
|
276
281
|
};
|
|
282
|
+
/** The tsconfig `build` compiles must actually set an outDir (or `build` emits .js next to sources) and must not set noEmit -- and if a separate tooling tsconfig sits beside it, that one must set noEmit, or typecheck starts emitting too. */
|
|
277
283
|
const tsconfigEmitCoherence = {
|
|
278
284
|
id: "tsconfig-emit-coherence",
|
|
279
285
|
level: "structural",
|
|
@@ -310,6 +316,7 @@ const tsconfigEmitCoherence = {
|
|
|
310
316
|
return { checked, failures };
|
|
311
317
|
},
|
|
312
318
|
};
|
|
319
|
+
/** A verify step naming a package.json script, a file, or a group that doesn't exist is a wiring defect no offline check other than this one would catch before someone actually runs it. */
|
|
313
320
|
const gateWiring = {
|
|
314
321
|
id: "gate-wiring",
|
|
315
322
|
level: "structural",
|
|
@@ -375,6 +382,7 @@ const gateWiring = {
|
|
|
375
382
|
return { checked, failures };
|
|
376
383
|
},
|
|
377
384
|
};
|
|
385
|
+
/** `.node-version` outside the range package.json's `engines.node` declares means the pinned dev/CI Node isn't even a Node version the project claims to support. */
|
|
378
386
|
const nodePinCoherence = {
|
|
379
387
|
id: "node-pin-coherence",
|
|
380
388
|
level: "structural",
|
|
@@ -408,6 +416,7 @@ const nodePinCoherence = {
|
|
|
408
416
|
},
|
|
409
417
|
};
|
|
410
418
|
// --- rubric rules ----------------------------------------------------------
|
|
419
|
+
/** The strict-family flags are the floor current TypeScript guidance recommends; tsc raises no warning for a flag simply left off, so this is the only check that notices. */
|
|
411
420
|
const strictFlags = {
|
|
412
421
|
id: "strict-flags",
|
|
413
422
|
level: "rubric",
|
|
@@ -434,6 +443,7 @@ const strictFlags = {
|
|
|
434
443
|
return { checked: STRICT_FLAGS.length + 1, failures };
|
|
435
444
|
},
|
|
436
445
|
};
|
|
446
|
+
/** Warns ahead of a TypeScript major that removes an option outright -- by the time tsc itself rejects it, the fix is no longer a choice, it's an emergency. */
|
|
437
447
|
const tsconfigOptionLifecycle = {
|
|
438
448
|
id: "tsconfig-option-lifecycle",
|
|
439
449
|
level: "rubric",
|
|
@@ -470,6 +480,7 @@ const tsconfigOptionLifecycle = {
|
|
|
470
480
|
return { checked: files.length, failures };
|
|
471
481
|
},
|
|
472
482
|
};
|
|
483
|
+
/** An outdated `module`/`moduleResolution`/`target` still compiles fine today, but forgoes current Node/bundler resolution semantics and syntax the project doesn't need to lower. */
|
|
473
484
|
const moduleTargetModern = {
|
|
474
485
|
id: "module-target-modern",
|
|
475
486
|
level: "rubric",
|
|
@@ -514,6 +525,7 @@ const moduleTargetModern = {
|
|
|
514
525
|
return { checked, failures };
|
|
515
526
|
},
|
|
516
527
|
};
|
|
528
|
+
/** ESLint 10 reads only eslint.config.* -- a lingering legacy eslintrc file means either an old ESLint is still in play, or a current one is silently linting nothing. */
|
|
517
529
|
const eslintFlatConfig = {
|
|
518
530
|
id: "eslint-flat-config",
|
|
519
531
|
level: "rubric",
|
|
@@ -533,6 +545,7 @@ const eslintFlatConfig = {
|
|
|
533
545
|
};
|
|
534
546
|
},
|
|
535
547
|
};
|
|
548
|
+
/** Without a type-checked preset and `projectService`, typescript-eslint runs syntax-only rules and silently skips every rule that needs real type information. */
|
|
536
549
|
const eslintTypedLinting = {
|
|
537
550
|
id: "eslint-typed-linting",
|
|
538
551
|
level: "rubric",
|
|
@@ -573,6 +586,7 @@ const eslintTypedLinting = {
|
|
|
573
586
|
return { checked: 2, failures };
|
|
574
587
|
},
|
|
575
588
|
};
|
|
589
|
+
/** `bin/**` and `.claude/hooks/**` are code this project actually runs, not incidental scripts -- if ESLint has no config block for them, or actively ignores src, they ship unlinted. */
|
|
576
590
|
const eslintCoversEmittedCode = {
|
|
577
591
|
id: "eslint-covers-emitted-code",
|
|
578
592
|
level: "rubric",
|
|
@@ -611,6 +625,7 @@ const eslintCoversEmittedCode = {
|
|
|
611
625
|
return { checked, failures };
|
|
612
626
|
},
|
|
613
627
|
};
|
|
628
|
+
/** A coverage threshold without `perFile: true` lets one well-tested file's coverage average out another file with none -- the gate passes while a whole file goes untested. */
|
|
614
629
|
const coverageGate = {
|
|
615
630
|
id: "coverage-gate",
|
|
616
631
|
level: "rubric",
|
|
@@ -635,6 +650,7 @@ const coverageGate = {
|
|
|
635
650
|
return { checked: 2, failures };
|
|
636
651
|
},
|
|
637
652
|
};
|
|
653
|
+
/** An unpinned toolchain package, a missing `packageManager`, or an `@types/node` major that doesn't match the pinned Node version each make installs non-reproducible across machines and CI runs. */
|
|
638
654
|
const toolchainPinShape = {
|
|
639
655
|
id: "toolchain-pin-shape",
|
|
640
656
|
level: "rubric",
|
|
@@ -5,6 +5,8 @@ interface ChainFile {
|
|
|
5
5
|
rel: string;
|
|
6
6
|
/** Why the file could not be used, or `undefined` when it parsed. */
|
|
7
7
|
error: string | undefined;
|
|
8
|
+
/** True when `error` is a read failure (missing, unreadable, unresolvable, not a regular file) rather than a parse failure. */
|
|
9
|
+
readFailed: boolean;
|
|
8
10
|
/** This file's own `compilerOptions`, unmerged. */
|
|
9
11
|
options: Record<string, unknown>;
|
|
10
12
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright the m3l-groundwork contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
1
3
|
/**
|
|
2
4
|
* Follows one tsconfig's `extends` chain and folds `compilerOptions` the way
|
|
3
5
|
* TypeScript does: array entries (TS 5.0+) left to right, the file's own
|
|
@@ -7,20 +9,41 @@
|
|
|
7
9
|
* Handles a relative target (`x`, `x.json`, `x/tsconfig.json`) and a bare
|
|
8
10
|
* package specifier looked up under every ancestor `node_modules`. A package
|
|
9
11
|
* `exports` map is out of scope -- such a specifier simply stays unresolved.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
+
* A file that is missing, unreadable (`EACCES`/`EPERM`, including under a
|
|
13
|
+
* directory this process cannot search), unresolvable (`ELOOP`) or
|
|
14
|
+
* unparseable is recorded on the chain, and the chain is marked incomplete;
|
|
15
|
+
* an unreachable `extends` target is followed and recorded as unreadable,
|
|
16
|
+
* never as missing. Any other failure (`EIO`, `EMFILE`, ...) on the
|
|
17
|
+
* existence check or the read throws an error naming the path, with the
|
|
18
|
+
* original as `cause`.
|
|
12
19
|
*/
|
|
13
20
|
import { statSync } from "node:fs";
|
|
14
21
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
15
22
|
import { readJsoncFile } from "../jsonc.js";
|
|
23
|
+
import { SurveyReadError, isAbsentError, unresolvableCode, } from "../survey/internal/read-guard.js";
|
|
16
24
|
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Whether `path` is a candidate `extends` target: a regular file, or
|
|
27
|
+
* something this process cannot reach (`EACCES`/`EPERM`/`ELOOP`). The latter
|
|
28
|
+
* is taken as the target so `readJsoncFile` records it as unreadable with
|
|
29
|
+
* its errno -- never reported "does not exist" for a file that may well be
|
|
30
|
+
* there. `ENOENT`/`ENOTDIR` is not a candidate; any other errno throws.
|
|
31
|
+
*/
|
|
32
|
+
function isCandidateFile(path) {
|
|
33
|
+
let stats;
|
|
18
34
|
try {
|
|
19
|
-
|
|
35
|
+
stats = statSync(path);
|
|
20
36
|
}
|
|
21
|
-
catch {
|
|
22
|
-
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (isAbsentError(error))
|
|
39
|
+
return false;
|
|
40
|
+
if (unresolvableCode(error) !== undefined)
|
|
41
|
+
return true;
|
|
42
|
+
throw new SurveyReadError(`could not check whether ${path} exists`, {
|
|
43
|
+
cause: error,
|
|
44
|
+
});
|
|
23
45
|
}
|
|
46
|
+
return stats.isFile();
|
|
24
47
|
}
|
|
25
48
|
/** The `extends` value as a list: a string, or TypeScript 5.0+'s array form. */
|
|
26
49
|
function extendsList(value) {
|
|
@@ -41,14 +64,14 @@ function resolveExtends(specifier, fromAbs) {
|
|
|
41
64
|
const base = resolve(dirname(fromAbs), specifier);
|
|
42
65
|
return {
|
|
43
66
|
kind: "relative",
|
|
44
|
-
abs: candidates(base).find(
|
|
67
|
+
abs: candidates(base).find(isCandidateFile),
|
|
45
68
|
attempted: base.endsWith(".json") ? base : `${base}.json`,
|
|
46
69
|
};
|
|
47
70
|
}
|
|
48
71
|
let dir = dirname(fromAbs);
|
|
49
72
|
for (;;) {
|
|
50
73
|
const base = join(dir, "node_modules", specifier);
|
|
51
|
-
const abs = candidates(base).find(
|
|
74
|
+
const abs = candidates(base).find(isCandidateFile);
|
|
52
75
|
if (abs !== undefined)
|
|
53
76
|
return { kind: "package", abs, attempted: base };
|
|
54
77
|
const parent = dirname(dir);
|
|
@@ -81,6 +104,7 @@ export function loadTsconfigChain(root, entry) {
|
|
|
81
104
|
: read.ok
|
|
82
105
|
? "top level is not an object"
|
|
83
106
|
: read.error,
|
|
107
|
+
readFailed: !read.ok && read.stage === "read",
|
|
84
108
|
options: own,
|
|
85
109
|
});
|
|
86
110
|
}
|
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shapes shared by the toolchain grader. Same two-level model as the harness
|
|
3
|
-
* grader (`../harness/types.ts`): `structural` findings are wiring
|
|
4
|
-
* `tsc` and ESLint do not catch and fail a gate
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* grader (`../harness/types.ts`): `structural` findings are pass/fail wiring
|
|
4
|
+
* defects `tsc` and ESLint do not catch, and fail a gate. `rubric` findings
|
|
5
|
+
* are quality judgements scored against a checklist rather than pass/fail
|
|
6
|
+
* wiring checks; that checklist encodes the floor -- the minimum baseline of
|
|
7
|
+
* practice current official TypeScript / typescript-eslint guidance
|
|
8
|
+
* recommends -- and a rubric finding only ever warns.
|
|
7
9
|
*/
|
|
8
10
|
import type { CheckTally, RuleLevel } from "../harness/types.js";
|
|
11
|
+
/** The toolchain area a rule or finding belongs to (tsconfig, modules, eslint, testing, gates, deps). */
|
|
9
12
|
export type ToolchainCategory = "tsconfig" | "modules" | "eslint" | "testing" | "gates" | "deps";
|
|
13
|
+
/** Every {@link ToolchainCategory}, as an ordered list -- so rubric tallies are iterated in a fixed order. */
|
|
10
14
|
export declare const TOOLCHAIN_CATEGORIES: readonly ToolchainCategory[];
|
|
15
|
+
/** One rule's result against one subject. */
|
|
11
16
|
export interface ToolchainFinding {
|
|
17
|
+
/** The id of the rule this finding came from. */
|
|
12
18
|
ruleId: string;
|
|
19
|
+
/** Whether this finding fails the gate (`structural`) or only warns (`rubric`). */
|
|
13
20
|
level: RuleLevel;
|
|
21
|
+
/** Which toolchain area this finding is about. */
|
|
14
22
|
category: ToolchainCategory;
|
|
15
23
|
/** The file, package, or verify step the finding is about. */
|
|
16
24
|
subject: string;
|
|
25
|
+
/** Human-readable description of what the rule found. */
|
|
17
26
|
message: string;
|
|
18
27
|
}
|
|
28
|
+
/** The full result of grading one project's toolchain. */
|
|
19
29
|
export interface ToolchainGrade {
|
|
30
|
+
/** Every finding from every rule, in rule order. */
|
|
20
31
|
findings: ToolchainFinding[];
|
|
32
|
+
/** The tally of structural checks: how many were checked and how many failed. */
|
|
21
33
|
structural: CheckTally;
|
|
22
34
|
/** Rubric tallies per category -- the absolute-quality measurement. */
|
|
23
35
|
rubric: Record<ToolchainCategory, CheckTally>;
|
package/dist/toolchain/types.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright the m3l-groundwork contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/** Every {@link ToolchainCategory}, as an ordered list -- so rubric tallies are iterated in a fixed order. */
|
|
1
4
|
export const TOOLCHAIN_CATEGORIES = [
|
|
2
5
|
"tsconfig",
|
|
3
6
|
"modules",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monte3l/groundwork",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0-rc.3",
|
|
4
|
+
"description": "CLI that writes a TypeScript toolchain and Claude Code setup into an empty directory, or -- against an existing project -- read-only surveys it and reports the differences. No prompts, and no network access beyond the package install.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
7
7
|
"claude-code",
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"!dist/.tsbuildinfo",
|
|
37
37
|
"bin",
|
|
38
38
|
"templates",
|
|
39
|
-
"plugin"
|
|
39
|
+
"plugin",
|
|
40
|
+
"LICENSE"
|
|
40
41
|
],
|
|
41
42
|
"publishConfig": {
|
|
42
43
|
"access": "public",
|