@monte3l/groundwork 1.0.0-rc.2 → 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 +13 -5
  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
@@ -0,0 +1,23 @@
1
+ /**
2
+ * GENERATED FILE -- do not hand-edit. Run `node bin/build-design-tokens.mjs`
3
+ * to regenerate from design/source/dtcg (the vendored m3l-design tokens).
4
+ * `--check` (used by `pnpm verify`) fails instead of writing on drift.
5
+ * Source of truth: design/source/dtcg (DTCG 2025.10). See design/README.md.
6
+ */
7
+ /** One role's resolved terminal color, per theme -- see term.ts's `paint()`. */
8
+ export interface PaletteRoleColors {
9
+ readonly success: string;
10
+ readonly info: string;
11
+ readonly warning: string;
12
+ readonly danger: string;
13
+ readonly accent: string;
14
+ readonly secondary: string;
15
+ }
16
+ /** {@link PaletteRoleColors} for each theme -- see term.ts's `resolveThemeId()`. */
17
+ export interface Palette {
18
+ readonly light: PaletteRoleColors;
19
+ readonly dark: PaletteRoleColors;
20
+ }
21
+ /** The resolved terminal palette, light and dark -- see term.ts's `paint()`. */
22
+ export declare const PALETTE: Palette;
23
+ //# sourceMappingURL=palette.d.ts.map
@@ -0,0 +1,22 @@
1
+ // SPDX-FileCopyrightText: Copyright the m3l-groundwork contributors
2
+ // SPDX-License-Identifier: MIT
3
+ /** The resolved terminal palette, light and dark -- see term.ts's `paint()`. */
4
+ export const PALETTE = {
5
+ light: {
6
+ success: "#086d31",
7
+ info: "#065da0",
8
+ warning: "#7d4f0a",
9
+ danger: "#963730",
10
+ accent: "#692746",
11
+ secondary: "#554d50",
12
+ },
13
+ dark: {
14
+ success: "#89d298",
15
+ info: "#8ac3fe",
16
+ warning: "#ebb16c",
17
+ danger: "#fda297",
18
+ accent: "#d1789e",
19
+ secondary: "#cdc5c8",
20
+ },
21
+ };
22
+ //# sourceMappingURL=palette.js.map
package/dist/plugin.d.ts CHANGED
@@ -1,22 +1,138 @@
1
+ /**
2
+ * What an install wrote.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { installCustomizeSkill } from "./plugin.js";
7
+ *
8
+ * const { filesWritten } = installCustomizeSkill("/work/app");
9
+ * filesWritten.at(-1); // ".claude/skills/customize/SKILL.md"
10
+ * ```
11
+ */
1
12
  export interface InstallPluginResult {
13
+ /** Paths relative to the project root, in write order (`SKILL.md` last); empty when the destination already held this exact payload. */
2
14
  filesWritten: string[];
3
15
  }
4
16
  /**
5
17
  * Installs the skill into `<targetDir>/.claude/skills/customize/`. Used by
6
- * fresh-bootstrap mode, where the directory is always new.
18
+ * fresh-bootstrap mode, where the directory is normally new (`--force` may
19
+ * point it at a non-empty one or an earlier install). An earlier install
20
+ * that is already byte-identical to this payload is left untouched
21
+ * (`filesWritten` is empty); otherwise any existing `SKILL.md` is removed
22
+ * first, then each payload file is removed and recreated. A symlinked
23
+ * `.claude`, `.claude/skills` or `.claude/skills/customize` is refused, not
24
+ * routed around.
25
+ *
26
+ * @throws `Error` ("could not install the /customize skill ...", raw error
27
+ * as `cause`) on a missing or unreadable source file, a directory at any
28
+ * payload name, a payload name or existing file that cannot be `lstat`ed,
29
+ * or an existing regular file whose read fails with anything other than
30
+ * `EACCES`/`EPERM` (all before anything is removed or written), a symlinked
31
+ * or non-directory directory component, any fs failure, or a failed write
32
+ * -- after removing every file this call wrote. An existing regular file
33
+ * whose read fails with `EACCES` or `EPERM` is not a failure: it is replaced
34
+ * like any stale copy. Entries it replaced before the failure are not
35
+ * restored; the error names them. A failure to locate the default
36
+ * `sourceDir` is thrown the same way. The message ends, once, by saying to
37
+ * fix the cause (for a symlink: remove it), then retry
38
+ * the same command with `--fresh --force` added -- a plain re-run would
39
+ * adopt the now-non-empty target -- and nowhere in the error chain gives
40
+ * adopt mode's bare "re-run the CLI" advice.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { installCustomizeSkill } from "./plugin.js";
45
+ *
46
+ * installCustomizeSkill("/work/app").filesWritten.length; // 5
47
+ * ```
7
48
  */
8
49
  export declare function installCustomizeSkill(targetDir: string, sourceDir?: string): InstallPluginResult;
9
50
  type InstallLocation = "claude" | "groundwork" | "already-present";
51
+ /**
52
+ * What the adopt-mode install did, and where.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * import { installCustomizeSkillGuarded } from "./plugin.js";
57
+ *
58
+ * const result = installCustomizeSkillGuarded("/work/app");
59
+ * if (result.fallbackReason !== undefined) console.log(result.fallbackReason);
60
+ * ```
61
+ */
10
62
  export interface GuardedInstallResult {
63
+ /** Paths relative to the project root, in write order (`SKILL.md` last); empty for `"already-present"`. */
11
64
  filesWritten: string[];
12
65
  location: InstallLocation;
66
+ /**
67
+ * Set on every `"groundwork"` result, and only then: why
68
+ * `.claude/skills/customize/` could not be used, naming the path
69
+ * responsible -- a symlinked or non-directory component, or the existing
70
+ * project entry under one of the skill's payload names.
71
+ */
72
+ fallbackReason?: string;
73
+ /**
74
+ * Set exactly when `fallbackReason` is: `"component"` when a
75
+ * `.claude`/`.claude/skills`/`.claude/skills/customize` component is a
76
+ * symlink or not a directory (no project-local copy of the skill exists),
77
+ * `"entry"` when a project-owned entry sits under one of the skill's
78
+ * payload names (a project copy exists, and is what a user would replace).
79
+ */
80
+ fallbackCause?: "entry" | "component";
13
81
  }
14
82
  /**
15
- * Adopt-mode install: purely additive, never overwrites. If the project
16
- * already has its own `.claude/skills/customize/SKILL.md` and its content
17
- * differs from what this CLI ships, the skill is written to
18
- * `.groundwork/customize/` instead -- reported in the adoption report
19
- * rather than silently overwriting whatever the project already had there.
83
+ * Adopt-mode install: purely additive, never overwrites or removes a project
84
+ * entry under `.claude/skills/customize/`.
85
+ *
86
+ * - If `.claude`, `.claude/skills` or `.claude/skills/customize` is a
87
+ * symlink or not a directory, the skill is written to
88
+ * `.groundwork/customize/` instead, `fallbackReason` names that path and
89
+ * `fallbackCause` is `"component"` -- the entry (and any link target) is
90
+ * left untouched.
91
+ * - Otherwise, if every payload file already there is a regular file
92
+ * matching what this CLI ships byte-for-byte: with all five present the
93
+ * result is `"already-present"` (nothing written); with no `SKILL.md` file
94
+ * (none at all, or an install interrupted before writing it) the missing
95
+ * files are written into `.claude/skills/customize/`, `SKILL.md` last,
96
+ * never rewriting or removing the correct ones.
97
+ * - Anything else under a payload name (a differing file, a regular file
98
+ * that cannot be read, a symlink -- dangling or not -- a directory, a
99
+ * `SKILL.md` without its data; detected by `lstat`) is kept as the
100
+ * project's own: the skill is written to `.groundwork/customize/` instead,
101
+ * `fallbackReason` names that entry (saying so when it could not be read)
102
+ * and `fallbackCause` is `"entry"`. Adopt mode never guesses at a project
103
+ * entry it cannot compare, and the fallback does not guess either: it
104
+ * leaves that entry exactly as it was. Claude Code does not load a skill
105
+ * from there; the caller must say so.
106
+ *
107
+ * Writes into `.claude/skills/customize/` use `"wx"` only, so an entry that
108
+ * appears there mid-install fails the run (rolled back) rather than being
109
+ * replaced. Writes into the CLI-owned `.groundwork/customize/` replace that
110
+ * directory's payload files (any `SKILL.md` removed first, then each file
111
+ * removed and recreated with `"wx"`); a symlinked `.groundwork` or
112
+ * `.groundwork/customize`, or a directory at any payload name there, is
113
+ * refused, never routed around.
114
+ *
115
+ * @throws `Error` ("could not install the /customize skill ...", raw error
116
+ * as `cause`) on a missing or unreadable source file (before anything is
117
+ * written), a payload name under `.claude/skills/customize/` that cannot be
118
+ * `lstat`ed or read (a regular file there whose read is refused with
119
+ * `EACCES`/`EPERM` falls back instead; any other read failure throws before
120
+ * anything is written), any other fs failure while probing or writing, a
121
+ * symlinked `.groundwork`/`.groundwork/customize`, or a directory at a
122
+ * payload name there -- after removing every file this call wrote. A failed
123
+ * `.groundwork/customize/` install also names why the fallback was taken.
124
+ * A failure to locate the default `sourceDir` is thrown the same way. The
125
+ * message ends by
126
+ * saying to fix the cause (for a symlink: remove it) and re-run the CLI,
127
+ * once.
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * import { installCustomizeSkillGuarded } from "./plugin.js";
132
+ *
133
+ * const { location } = installCustomizeSkillGuarded("/work/app");
134
+ * // "claude" | "groundwork" | "already-present"
135
+ * ```
20
136
  */
21
137
  export declare function installCustomizeSkillGuarded(targetDir: string, sourceDir?: string): GuardedInstallResult;
22
138
  export {};