@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.
Files changed (170) hide show
  1. package/README.md +16 -8
  2. package/bin/m3l-groundwork.mjs +36 -2
  3. package/dist/assets.d.ts +10 -0
  4. package/dist/assets.js +14 -0
  5. package/dist/baseline-stage.d.ts +173 -0
  6. package/dist/baseline-stage.js +215 -0
  7. package/dist/caps.d.ts +4 -1
  8. package/dist/caps.js +17 -3
  9. package/dist/conflicts.d.ts +23 -2
  10. package/dist/conflicts.js +89 -11
  11. package/dist/customize-paths.d.ts +92 -0
  12. package/dist/customize-paths.js +115 -0
  13. package/dist/emit.d.ts +50 -1
  14. package/dist/emit.js +121 -13
  15. package/dist/fatal.d.ts +70 -0
  16. package/dist/fatal.js +132 -0
  17. package/dist/format-error.d.ts +113 -0
  18. package/dist/format-error.js +553 -0
  19. package/dist/fs-guard.d.ts +142 -0
  20. package/dist/fs-guard.js +222 -0
  21. package/dist/git.js +10 -1
  22. package/dist/harness/conformance.js +2 -0
  23. package/dist/harness/frontmatter.js +2 -13
  24. package/dist/harness/grade.js +37 -8
  25. package/dist/harness/rules.d.ts +20 -3
  26. package/dist/harness/rules.js +108 -6
  27. package/dist/harness/types.d.ts +13 -0
  28. package/dist/harness/types.js +3 -0
  29. package/dist/inventory.d.ts +77 -3
  30. package/dist/inventory.js +103 -12
  31. package/dist/jsonc.d.ts +49 -2
  32. package/dist/jsonc.js +140 -7
  33. package/dist/main.d.ts +62 -3
  34. package/dist/main.js +538 -67
  35. package/dist/merge-json.d.ts +47 -4
  36. package/dist/merge-json.js +120 -8
  37. package/dist/mode.js +12 -2
  38. package/dist/pack-stage.d.ts +210 -0
  39. package/dist/pack-stage.js +287 -0
  40. package/dist/packs.d.ts +19 -13
  41. package/dist/packs.js +231 -28
  42. package/dist/palette.d.ts +23 -0
  43. package/dist/palette.js +22 -0
  44. package/dist/plugin.d.ts +122 -6
  45. package/dist/plugin.js +687 -47
  46. package/dist/report.d.ts +21 -2
  47. package/dist/report.js +93 -5
  48. package/dist/staging.d.ts +176 -0
  49. package/dist/staging.js +375 -0
  50. package/dist/survey/fs-walk.d.ts +34 -2
  51. package/dist/survey/fs-walk.js +70 -5
  52. package/dist/survey/internal/blocked-path.d.ts +27 -0
  53. package/dist/survey/internal/blocked-path.js +129 -0
  54. package/dist/survey/internal/package-json.d.ts +13 -0
  55. package/dist/survey/internal/package-json.js +37 -0
  56. package/dist/survey/internal/read-guard.d.ts +178 -0
  57. package/dist/survey/internal/read-guard.js +276 -0
  58. package/dist/survey/survey-docs.d.ts +17 -2
  59. package/dist/survey/survey-docs.js +61 -21
  60. package/dist/survey/survey-harness.d.ts +20 -2
  61. package/dist/survey/survey-harness.js +87 -46
  62. package/dist/survey/survey-shape.d.ts +17 -2
  63. package/dist/survey/survey-shape.js +60 -46
  64. package/dist/survey/survey-toolchain.d.ts +16 -1
  65. package/dist/survey/survey-toolchain.js +69 -66
  66. package/dist/survey/survey.js +6 -4
  67. package/dist/survey/types.d.ts +79 -0
  68. package/dist/survey/types.js +2 -6
  69. package/dist/term.d.ts +80 -0
  70. package/dist/term.js +145 -0
  71. package/dist/tokens.js +2 -0
  72. package/dist/toolchain/conformance.js +2 -0
  73. package/dist/toolchain/grade.js +26 -8
  74. package/dist/toolchain/rules.d.ts +13 -4
  75. package/dist/toolchain/rules.js +16 -0
  76. package/dist/toolchain/tsconfig-chain.d.ts +2 -0
  77. package/dist/toolchain/tsconfig-chain.js +32 -8
  78. package/dist/toolchain/types.d.ts +16 -4
  79. package/dist/toolchain/types.js +3 -0
  80. package/package.json +4 -3
  81. package/plugin/skills/customize/SKILL.md +292 -18
  82. package/plugin/src/domain-map.ts +39 -14
  83. package/plugin/src/index.ts +5 -1
  84. package/plugin/src/kind-facet-map.ts +25 -8
  85. package/plugin/src/pack-map.ts +147 -25
  86. package/plugin/src/plugin-map.ts +236 -0
  87. package/templates/core/.claude/agents/Explore.md +0 -1
  88. package/templates/core/.claude/agents/code-implementer.md +4 -4
  89. package/templates/core/.claude/agents/code-reviewer.md +4 -4
  90. package/templates/core/.claude/agents/silent-failure-hunter.md +2 -2
  91. package/templates/core/.claude/agents/test-author.md +7 -5
  92. package/templates/core/.claude/hooks/guard-branch-isolation.mjs +56 -10
  93. package/templates/core/.claude/hooks/guard-double-background.mjs +13 -8
  94. package/templates/core/.claude/hooks/guard-git-push-signed.mjs +12 -9
  95. package/templates/core/.claude/hooks/guard-hub-src-writes.mjs +1890 -38
  96. package/templates/core/.claude/hooks/guard-js-extension.mjs +2 -1
  97. package/templates/core/.claude/hooks/guard-no-commonjs.mjs +7 -5
  98. package/templates/core/.claude/hooks/guard-secret-writes.mjs +7 -5
  99. package/templates/core/.claude/hooks/inject-decision-gate.mjs +12 -9
  100. package/templates/core/.claude/hooks/post-edit-verify.mjs +276 -98
  101. package/templates/core/.claude/rules/agent-dispatch.md +7 -0
  102. package/templates/core/.claude/rules/tests.md +2 -2
  103. package/templates/core/.claude/settings.json +5 -0
  104. package/templates/core/.claude/skills/finishing-work/SKILL.md +58 -10
  105. package/templates/core/.claude/skills/harness-guidance/SKILL.md +16 -7
  106. package/templates/core/.claude/skills/starting-work/SKILL.md +5 -0
  107. package/templates/core/.claude/skills/triaging-ci/SKILL.md +9 -8
  108. package/templates/core/.claude/skills/typescript-guidance/SKILL.md +137 -20
  109. package/templates/core/.claude/skills/typescript-guidance/references/area-catalog.md +135 -0
  110. package/templates/core/.claude/skills/typescript-guidance/references/tooling-sources.md +113 -0
  111. package/templates/core/.claude/skills/writing-commits/SKILL.md +2 -2
  112. package/templates/core/.github/dependabot.yml +18 -0
  113. package/templates/core/.github/workflows/ci.yml +15 -15
  114. package/templates/core/.github/workflows/dependency-review.yml +2 -2
  115. package/templates/core/.github/workflows/security-audit.yml +10 -4
  116. package/templates/core/.prettierignore +4 -0
  117. package/templates/core/CLAUDE.md +53 -3
  118. package/templates/core/README.md +30 -10
  119. package/templates/core/_gitignore +17 -0
  120. package/templates/core/bin/check-exports.mjs +11 -5
  121. package/templates/core/bin/lib/agent-roster.mjs +1 -1
  122. package/templates/core/bin/lib/frontmatter.mjs +4 -2
  123. package/templates/core/bin/lib/harness-rules.mjs +169 -20
  124. package/templates/core/bin/lib/protected-paths.mjs +93 -5
  125. package/templates/core/bin/lib/toolchain-rules.mjs +187 -26
  126. package/templates/core/bin/lib/verify-steps.mjs +29 -11
  127. package/templates/core/bin/verify.mjs +12 -0
  128. package/templates/core/eslint.config.js +5 -0
  129. package/templates/core/package.json +7 -7
  130. package/templates/core/vitest.config.ts +8 -1
  131. package/templates/packs/README.md +35 -24
  132. package/templates/packs/github/files/.claude/skills/reviewing-dependabot-prs/SKILL.md +133 -0
  133. package/templates/packs/github/files/.claude/skills/triaging-scan-alerts/SKILL.md +88 -0
  134. package/templates/packs/github/files/.claude/skills/watching-pr-checks/SKILL.md +94 -0
  135. package/templates/packs/github/files/.github/workflows/claude-pr-review.yml +267 -0
  136. package/templates/packs/github/files/.github/workflows/claude.yml +106 -0
  137. package/templates/packs/github/pack.json +19 -0
  138. package/templates/packs/harness-extras/files/.claude/hooks/guard-readonly-bash.mjs +1122 -65
  139. package/templates/packs/harness-extras/files/.claude/hooks/reinject-compact-handoff.mjs +147 -13
  140. package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/statusline.mjs +6 -2
  141. package/templates/packs/harness-extras/files/.claude/hooks/write-compact-handoff.mjs +227 -44
  142. package/templates/packs/harness-extras/pack.json +18 -13
  143. package/templates/packs/publishing/files/.changeset/README.md +25 -0
  144. package/templates/packs/publishing/files/.changeset/config.json +7 -0
  145. package/templates/packs/publishing/files/.github/release-tools/package.json +9 -0
  146. package/templates/packs/publishing/files/.github/workflows/release.yml +293 -0
  147. package/templates/packs/publishing/files/REUSE.toml +28 -0
  148. package/templates/packs/publishing/files/bin/check-dts-deps.mjs +234 -0
  149. package/templates/packs/publishing/files/bin/check-license-headers.mjs +217 -0
  150. package/templates/packs/publishing/files/bin/check-publish-version.mjs +149 -0
  151. package/templates/packs/publishing/files/bin/lib/npm-publish-args.mjs +86 -0
  152. package/templates/packs/publishing/files/bin/pnpm-publish-shim.mjs +86 -0
  153. package/templates/packs/publishing/pack.json +35 -0
  154. package/templates/packs/{harness-extras → quality}/files/bin/check-file-budget.mjs +6 -4
  155. package/templates/packs/quality/pack.json +29 -0
  156. package/templates/packs/supply-chain/files/.github/workflows/gitleaks.yml +52 -0
  157. package/templates/packs/supply-chain/files/.github/workflows/scorecard.yml +48 -0
  158. package/templates/packs/supply-chain/files/.gitleaks.toml +2 -0
  159. package/templates/packs/supply-chain/pack.json +19 -0
  160. package/templates/packs/worktrees/files/.claude/hooks/ensure-worktree-deps.mjs +283 -0
  161. package/templates/packs/worktrees/files/.claude/hooks/guard-worktree-only.mjs +245 -0
  162. package/templates/packs/worktrees/files/.claude/hooks/repair-core-bare.mjs +335 -0
  163. package/templates/packs/worktrees/files/.claude/skills/working-in-worktrees/SKILL.md +139 -0
  164. package/templates/packs/worktrees/files/.worktreeinclude +11 -0
  165. package/templates/packs/worktrees/pack.json +64 -0
  166. package/templates/packs/statusline/pack.json +0 -31
  167. /package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/statusline-layout.mjs +0 -0
  168. /package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/subagent-statusline.mjs +0 -0
  169. /package/templates/packs/{harness-extras → quality}/files/.claude/agents/type-design-analyzer.md +0 -0
  170. /package/templates/packs/{harness-extras → quality}/files/bin/file-budget-baseline.json +0 -0
@@ -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
- * Nothing here throws: a file that cannot be read or parsed is recorded on
11
- * the chain, and the chain is marked incomplete.
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
- function isFile(path) {
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
- return statSync(path).isFile();
35
+ stats = statSync(path);
20
36
  }
21
- catch {
22
- return false;
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(isFile),
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(isFile);
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 defects
4
- * `tsc` and ESLint do not catch and fail a gate; `rubric` findings are the
5
- * floor official TypeScript / typescript-eslint guidance sets and only ever
6
- * warn.
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>;
@@ -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": "0.1.0-next.1",
4
- "description": "Deterministic Phase A bootstrapper: writes the m3l-groundwork baseline (toolchain + Claude Code harness) into a new directory, or surveys an existing project read-only. No prompts, no network beyond the package install.",
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",