@monte3l/groundwork 1.0.0-rc.4 → 1.0.0-rc.5

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 (31) hide show
  1. package/dist/customize-paths.d.ts +51 -15
  2. package/dist/customize-paths.js +32 -13
  3. package/dist/fs-guard.d.ts +2 -2
  4. package/dist/harness/rules.d.ts +2 -1
  5. package/dist/harness/rules.js +3 -1
  6. package/dist/plugin.d.ts +12 -12
  7. package/dist/plugin.js +34 -26
  8. package/package.json +1 -1
  9. package/plugin/skills/customize/SKILL.md +33 -403
  10. package/plugin/skills/customize/step-0-reconcile.md +261 -0
  11. package/plugin/skills/customize/step-3-round-1.md +170 -0
  12. package/plugin/src/plugin-map.ts +131 -10
  13. package/templates/core/.claude/agents/Explore.md +1 -1
  14. package/templates/core/.claude/hooks/guard-no-commonjs.mjs +3 -2
  15. package/templates/core/.claude/hooks/inject-decision-gate.mjs +7 -7
  16. package/templates/core/.claude/skills/triaging-ci/SKILL.md +2 -2
  17. package/templates/core/.claude/skills/writing-commits/SKILL.md +4 -4
  18. package/templates/core/.prettierignore +1 -0
  19. package/templates/core/_gitignore +1 -0
  20. package/templates/core/bin/check-exports.mjs +5 -3
  21. package/templates/core/bin/lib/harness-rules.mjs +3 -1
  22. package/templates/core/tsconfig.base.json +10 -6
  23. package/templates/packs/README.md +6 -0
  24. package/templates/packs/github/files/.github/workflows/claude-pr-review.yml +1 -1
  25. package/templates/packs/github/files/.github/workflows/claude.yml +1 -1
  26. package/templates/packs/github/pack.json +1 -1
  27. package/templates/packs/harness-extras/files/.claude/hooks/subagent-statusline.mjs +29 -14
  28. package/templates/packs/harness-extras/pack.json +1 -1
  29. package/templates/packs/publishing/pack.json +1 -1
  30. package/templates/packs/quality/files/.claude/agents/type-design-analyzer.md +1 -1
  31. package/templates/packs/quality/pack.json +1 -1
@@ -1,7 +1,8 @@
1
1
  /**
2
- * The skill's entry file: the one payload file that lives under the plugin
3
- * source's `skills/customize/` (every other one lives under its `src/`), and
4
- * the one whose presence makes Claude Code load the skill -- which is why
2
+ * The skill's entry file: it lives under the plugin source's
3
+ * `skills/customize/` beside {@link CUSTOMIZE_SKILL_STEP_FILE_NAMES} (the
4
+ * backing-data files live under its `src/`), and it is the one payload file
5
+ * whose presence makes Claude Code load the skill -- which is why
5
6
  * {@link CUSTOMIZE_SKILL_WRITE_ORDER} writes it last.
6
7
  *
7
8
  * @example
@@ -12,6 +13,24 @@
12
13
  * ```
13
14
  */
14
15
  export declare const CUSTOMIZE_SKILL_ENTRY_FILE = "SKILL.md";
16
+ /**
17
+ * The step files `SKILL.md` delegates to (Step 0's adopt-mode reconcile and
18
+ * Step 3's Round 1), sourced from the plugin's `skills/customize/` beside
19
+ * {@link CUSTOMIZE_SKILL_ENTRY_FILE}. Like the backing-data files, they are
20
+ * written before `SKILL.md`, so a loadable `SKILL.md` never sits beside a
21
+ * missing step file.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { CUSTOMIZE_SKILL_STEP_FILE_NAMES } from "./customize-paths.js";
26
+ *
27
+ * CUSTOMIZE_SKILL_STEP_FILE_NAMES[0]; // "step-0-reconcile.md"
28
+ * ```
29
+ */
30
+ export declare const CUSTOMIZE_SKILL_STEP_FILE_NAMES: readonly [
31
+ "step-0-reconcile.md",
32
+ "step-3-round-1.md"
33
+ ];
15
34
  /**
16
35
  * Every payload file's name inside an installed copy of the skill.
17
36
  *
@@ -22,19 +41,28 @@ export declare const CUSTOMIZE_SKILL_ENTRY_FILE = "SKILL.md";
22
41
  * CUSTOMIZE_SKILL_FILE_NAMES.includes("SKILL.md"); // true
23
42
  * ```
24
43
  */
25
- export declare const CUSTOMIZE_SKILL_FILE_NAMES: readonly ["SKILL.md", "kind-facet-map.ts", "domain-map.ts", "pack-map.ts", "plugin-map.ts"];
44
+ export declare const CUSTOMIZE_SKILL_FILE_NAMES: readonly [
45
+ "SKILL.md",
46
+ "kind-facet-map.ts",
47
+ "domain-map.ts",
48
+ "pack-map.ts",
49
+ "plugin-map.ts",
50
+ "step-0-reconcile.md",
51
+ "step-3-round-1.md"
52
+ ];
26
53
  /**
27
- * The order an install writes the payload in: every backing-data file
28
- * first, {@link CUSTOMIZE_SKILL_ENTRY_FILE} last. A run that fails part-way
29
- * (and whose rollback cannot remove everything) therefore never leaves a
30
- * loadable `SKILL.md` beside missing or stale data files -- given the
31
- * precondition that no `SKILL.md` already sits at the destination. Wherever
32
- * an install replaces existing entries -- fresh mode's
54
+ * The order an install writes the payload in: every backing-data file, then
55
+ * every step file, {@link CUSTOMIZE_SKILL_ENTRY_FILE} last. A run that fails
56
+ * part-way (and whose rollback cannot remove everything) therefore never
57
+ * leaves a loadable `SKILL.md` beside missing or stale data or step files --
58
+ * given the precondition that no `SKILL.md` already sits at the destination.
59
+ * Wherever an install replaces existing entries -- fresh mode's
33
60
  * `.claude/skills/customize/` (a `--force` re-run over an earlier install)
34
61
  * and the CLI-owned `.groundwork/customize/` -- `plugin.ts` establishes that
35
62
  * precondition by removing any existing `SKILL.md` entry before the first
36
- * data file is rewritten. Adopt mode's additive `.claude/skills/customize/`
37
- * install only ever writes there when no `SKILL.md` entry exists.
63
+ * data or step file is rewritten. Adopt mode's additive
64
+ * `.claude/skills/customize/` install only ever writes there when no
65
+ * `SKILL.md` entry exists.
38
66
  *
39
67
  * @example
40
68
  * ```ts
@@ -43,7 +71,15 @@ export declare const CUSTOMIZE_SKILL_FILE_NAMES: readonly ["SKILL.md", "kind-fac
43
71
  * CUSTOMIZE_SKILL_WRITE_ORDER.at(-1); // "SKILL.md"
44
72
  * ```
45
73
  */
46
- export declare const CUSTOMIZE_SKILL_WRITE_ORDER: readonly ["kind-facet-map.ts", "domain-map.ts", "pack-map.ts", "plugin-map.ts", "SKILL.md"];
74
+ export declare const CUSTOMIZE_SKILL_WRITE_ORDER: readonly [
75
+ "kind-facet-map.ts",
76
+ "domain-map.ts",
77
+ "pack-map.ts",
78
+ "plugin-map.ts",
79
+ "step-0-reconcile.md",
80
+ "step-3-round-1.md",
81
+ "SKILL.md"
82
+ ];
47
83
  /**
48
84
  * The fresh-mode destination -- and adopt mode's, when nothing is there yet
49
85
  * or an earlier install was interrupted before its `SKILL.md` -- as path
@@ -63,7 +99,7 @@ export declare const CLAUDE_DEST_SEGMENTS: readonly [".claude", "skills", "custo
63
99
  * project root. Used whenever {@link CLAUDE_DEST_SEGMENTS} cannot be written
64
100
  * additively: a project-owned entry under any of the skill's payload names
65
101
  * that is not this CLI's current copy (a differing file, a symlink, a
66
- * directory, a `SKILL.md` without its data), or a component of
102
+ * directory, a `SKILL.md` without its data or step files), or a component of
67
103
  * `.claude/skills/customize` that is a symlink or not a directory.
68
104
  *
69
105
  * @example
@@ -85,7 +121,7 @@ export declare const GROUNDWORK_DEST_SEGMENTS: readonly [".groundwork", "customi
85
121
  * import { plannedCustomizeSkillPaths } from "./customize-paths.js";
86
122
  *
87
123
  * plannedCustomizeSkillPaths();
88
- * // [".claude/skills/customize/SKILL.md", ..., ".groundwork/customize/plugin-map.ts"]
124
+ * // [".claude/skills/customize/SKILL.md", ..., ".groundwork/customize/step-3-round-1.md"]
89
125
  * ```
90
126
  */
91
127
  export declare function plannedCustomizeSkillPaths(): readonly string[];
@@ -7,9 +7,10 @@
7
7
  */
8
8
  import { join } from "node:path";
9
9
  /**
10
- * The skill's entry file: the one payload file that lives under the plugin
11
- * source's `skills/customize/` (every other one lives under its `src/`), and
12
- * the one whose presence makes Claude Code load the skill -- which is why
10
+ * The skill's entry file: it lives under the plugin source's
11
+ * `skills/customize/` beside {@link CUSTOMIZE_SKILL_STEP_FILE_NAMES} (the
12
+ * backing-data files live under its `src/`), and it is the one payload file
13
+ * whose presence makes Claude Code load the skill -- which is why
13
14
  * {@link CUSTOMIZE_SKILL_WRITE_ORDER} writes it last.
14
15
  *
15
16
  * @example
@@ -27,6 +28,21 @@ const CUSTOMIZE_SKILL_DATA_FILE_NAMES = [
27
28
  "pack-map.ts",
28
29
  "plugin-map.ts",
29
30
  ];
31
+ /**
32
+ * The step files `SKILL.md` delegates to (Step 0's adopt-mode reconcile and
33
+ * Step 3's Round 1), sourced from the plugin's `skills/customize/` beside
34
+ * {@link CUSTOMIZE_SKILL_ENTRY_FILE}. Like the backing-data files, they are
35
+ * written before `SKILL.md`, so a loadable `SKILL.md` never sits beside a
36
+ * missing step file.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { CUSTOMIZE_SKILL_STEP_FILE_NAMES } from "./customize-paths.js";
41
+ *
42
+ * CUSTOMIZE_SKILL_STEP_FILE_NAMES[0]; // "step-0-reconcile.md"
43
+ * ```
44
+ */
45
+ export const CUSTOMIZE_SKILL_STEP_FILE_NAMES = ["step-0-reconcile.md", "step-3-round-1.md"];
30
46
  /**
31
47
  * Every payload file's name inside an installed copy of the skill.
32
48
  *
@@ -40,19 +56,21 @@ const CUSTOMIZE_SKILL_DATA_FILE_NAMES = [
40
56
  export const CUSTOMIZE_SKILL_FILE_NAMES = [
41
57
  CUSTOMIZE_SKILL_ENTRY_FILE,
42
58
  ...CUSTOMIZE_SKILL_DATA_FILE_NAMES,
59
+ ...CUSTOMIZE_SKILL_STEP_FILE_NAMES,
43
60
  ];
44
61
  /**
45
- * The order an install writes the payload in: every backing-data file
46
- * first, {@link CUSTOMIZE_SKILL_ENTRY_FILE} last. A run that fails part-way
47
- * (and whose rollback cannot remove everything) therefore never leaves a
48
- * loadable `SKILL.md` beside missing or stale data files -- given the
49
- * precondition that no `SKILL.md` already sits at the destination. Wherever
50
- * an install replaces existing entries -- fresh mode's
62
+ * The order an install writes the payload in: every backing-data file, then
63
+ * every step file, {@link CUSTOMIZE_SKILL_ENTRY_FILE} last. A run that fails
64
+ * part-way (and whose rollback cannot remove everything) therefore never
65
+ * leaves a loadable `SKILL.md` beside missing or stale data or step files --
66
+ * given the precondition that no `SKILL.md` already sits at the destination.
67
+ * Wherever an install replaces existing entries -- fresh mode's
51
68
  * `.claude/skills/customize/` (a `--force` re-run over an earlier install)
52
69
  * and the CLI-owned `.groundwork/customize/` -- `plugin.ts` establishes that
53
70
  * precondition by removing any existing `SKILL.md` entry before the first
54
- * data file is rewritten. Adopt mode's additive `.claude/skills/customize/`
55
- * install only ever writes there when no `SKILL.md` entry exists.
71
+ * data or step file is rewritten. Adopt mode's additive
72
+ * `.claude/skills/customize/` install only ever writes there when no
73
+ * `SKILL.md` entry exists.
56
74
  *
57
75
  * @example
58
76
  * ```ts
@@ -63,6 +81,7 @@ export const CUSTOMIZE_SKILL_FILE_NAMES = [
63
81
  */
64
82
  export const CUSTOMIZE_SKILL_WRITE_ORDER = [
65
83
  ...CUSTOMIZE_SKILL_DATA_FILE_NAMES,
84
+ ...CUSTOMIZE_SKILL_STEP_FILE_NAMES,
66
85
  CUSTOMIZE_SKILL_ENTRY_FILE,
67
86
  ];
68
87
  /**
@@ -84,7 +103,7 @@ export const CLAUDE_DEST_SEGMENTS = [".claude", "skills", "customize"];
84
103
  * project root. Used whenever {@link CLAUDE_DEST_SEGMENTS} cannot be written
85
104
  * additively: a project-owned entry under any of the skill's payload names
86
105
  * that is not this CLI's current copy (a differing file, a symlink, a
87
- * directory, a `SKILL.md` without its data), or a component of
106
+ * directory, a `SKILL.md` without its data or step files), or a component of
88
107
  * `.claude/skills/customize` that is a symlink or not a directory.
89
108
  *
90
109
  * @example
@@ -106,7 +125,7 @@ export const GROUNDWORK_DEST_SEGMENTS = [".groundwork", "customize"];
106
125
  * import { plannedCustomizeSkillPaths } from "./customize-paths.js";
107
126
  *
108
127
  * plannedCustomizeSkillPaths();
109
- * // [".claude/skills/customize/SKILL.md", ..., ".groundwork/customize/plugin-map.ts"]
128
+ * // [".claude/skills/customize/SKILL.md", ..., ".groundwork/customize/step-3-round-1.md"]
110
129
  * ```
111
130
  */
112
131
  export function plannedCustomizeSkillPaths() {
@@ -12,7 +12,7 @@
12
12
  * endsWithRerunAdvice(message); // true
13
13
  * ```
14
14
  */
15
- export declare const FIX_AND_RERUN_ADVICE = "fix the cause and re-run the CLI";
15
+ export declare const FIX_AND_RERUN_ADVICE: string;
16
16
  /**
17
17
  * Whether `message` already ENDS with "re-run the CLI" advice, in any
18
18
  * wording that ends that way (e.g. {@link assertNotSymlink}'s "remove it and
@@ -138,5 +138,5 @@ export declare function assertNotDirectory(path: string, advice: string): void;
138
138
  * assertNotSymlink("/work/app/package.json", FRESH_SYMLINK_ADVICE);
139
139
  * ```
140
140
  */
141
- export declare const FRESH_SYMLINK_ADVICE = "remove it, then retry the same command with --fresh --force added";
141
+ export declare const FRESH_SYMLINK_ADVICE: string;
142
142
  //# sourceMappingURL=fs-guard.d.ts.map
@@ -59,7 +59,8 @@ export interface HarnessRule {
59
59
  * Model ids and aliases the rubric accepts: the current ids and aliases, plus
60
60
  * ids that were once listed here, kept until Anthropic deprecates them. The
61
61
  * ids follow Anthropic's models overview and model-deprecations pages
62
- * (retrieved 2026-10-01). A legacy id that was never listed here is
62
+ * (retrieved 2026-10-08): Haiku 5.5 (released 2026-10-07) is current, and
63
+ * Haiku 4.5 is legacy but still active. A legacy id that was never listed here is
63
64
  * deliberately not added, so the rule keeps nudging pins toward current
64
65
  * models. Bump alongside the `harness-guidance` refresh sweep;
65
66
  * `templates/core/bin/lib/harness-rules.mjs` carries the same list and the
@@ -20,7 +20,8 @@ import { fieldList, fieldText, parseFrontmatter } from "./frontmatter.js";
20
20
  * Model ids and aliases the rubric accepts: the current ids and aliases, plus
21
21
  * ids that were once listed here, kept until Anthropic deprecates them. The
22
22
  * ids follow Anthropic's models overview and model-deprecations pages
23
- * (retrieved 2026-10-01). A legacy id that was never listed here is
23
+ * (retrieved 2026-10-08): Haiku 5.5 (released 2026-10-07) is current, and
24
+ * Haiku 4.5 is legacy but still active. A legacy id that was never listed here is
24
25
  * deliberately not added, so the rule keeps nudging pins toward current
25
26
  * models. Bump alongside the `harness-guidance` refresh sweep;
26
27
  * `templates/core/bin/lib/harness-rules.mjs` carries the same list and the
@@ -37,6 +38,7 @@ export const CURRENT_MODELS = [
37
38
  "claude-sonnet-5",
38
39
  "claude-sonnet-5-5",
39
40
  "claude-fable-5-1",
41
+ "claude-haiku-5-5",
40
42
  "claude-haiku-4-5",
41
43
  "claude-haiku-4-5-20251001",
42
44
  ];
package/dist/plugin.d.ts CHANGED
@@ -89,20 +89,20 @@ export interface GuardedInstallResult {
89
89
  * `fallbackCause` is `"component"` -- the entry (and any link target) is
90
90
  * left untouched.
91
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.
92
+ * matching what this CLI ships byte-for-byte: with every payload file
93
+ * present the result is `"already-present"` (nothing written); with no
94
+ * `SKILL.md` file (none at all, or an install interrupted before writing
95
+ * it) the missing files are written into `.claude/skills/customize/`,
96
+ * `SKILL.md` last, never rewriting or removing the correct ones.
97
97
  * - Anything else under a payload name (a differing file, a regular file
98
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.
99
+ * `SKILL.md` without its data or step files; detected by `lstat`) is kept
100
+ * as the project's own: the skill is written to `.groundwork/customize/`
101
+ * instead, `fallbackReason` names that entry (saying so when it could not
102
+ * be read) and `fallbackCause` is `"entry"`. Adopt mode never guesses at a
103
+ * project entry it cannot compare, and the fallback does not guess either:
104
+ * it leaves that entry exactly as it was. Claude Code does not load a
105
+ * skill from there; the caller must say so.
106
106
  *
107
107
  * Writes into `.claude/skills/customize/` use `"wx"` only, so an entry that
108
108
  * appears there mid-install fails the run (rolled back) rather than being
package/dist/plugin.js CHANGED
@@ -4,14 +4,14 @@
4
4
  * Installs the `/customize` skill into a bootstrapped or adopted project.
5
5
  * Claude Code's marketplace-based plugin installation is an interactive,
6
6
  * network-involving flow this offline CLI can't drive; instead this copies
7
- * the skill's SKILL.md plus its deterministic backing data directly into a
8
- * destination directory, so `/customize` works immediately with no further
9
- * setup step.
7
+ * the skill's SKILL.md, its step files and its deterministic backing data
8
+ * into a destination directory, so `/customize` works immediately with no
9
+ * further setup step.
10
10
  */
11
11
  import { lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
12
12
  import { join } from "node:path";
13
13
  import { resolveAsset } from "./assets.js";
14
- import { CLAUDE_DEST_SEGMENTS, CUSTOMIZE_SKILL_ENTRY_FILE, CUSTOMIZE_SKILL_WRITE_ORDER, GROUNDWORK_DEST_SEGMENTS, } from "./customize-paths.js";
14
+ import { CLAUDE_DEST_SEGMENTS, CUSTOMIZE_SKILL_ENTRY_FILE, CUSTOMIZE_SKILL_STEP_FILE_NAMES, CUSTOMIZE_SKILL_WRITE_ORDER, GROUNDWORK_DEST_SEGMENTS, } from "./customize-paths.js";
15
15
  import { assertNotSymlink, endsWithRerunAdvice, FIX_AND_RERUN_ADVICE, FRESH_RETRY, FRESH_SYMLINK_ADVICE, } from "./fs-guard.js";
16
16
  /** Resolves the plugin payload for a source checkout (`packages/plugin`) or a published tarball (`plugin/`). */
17
17
  function pluginDir() {
@@ -107,6 +107,14 @@ function errnoField(error, field) {
107
107
  const value = Reflect.get(error, field);
108
108
  return typeof value === "string" ? value : undefined;
109
109
  }
110
+ /**
111
+ * The payload files sourced from the plugin's `skills/customize/` (the
112
+ * entry file and its step files); every other one comes from its `src/`.
113
+ */
114
+ const SKILL_DIR_FILE_NAMES = new Set([
115
+ CUSTOMIZE_SKILL_ENTRY_FILE,
116
+ ...CUSTOMIZE_SKILL_STEP_FILE_NAMES,
117
+ ]);
110
118
  /**
111
119
  * Reads every payload file from the plugin source, in
112
120
  * {@link CUSTOMIZE_SKILL_WRITE_ORDER} (`SKILL.md` last), before anything is
@@ -117,7 +125,7 @@ function errnoField(error, field) {
117
125
  */
118
126
  function readCustomizeSkillPayload(sourceDir) {
119
127
  return CUSTOMIZE_SKILL_WRITE_ORDER.map((name) => {
120
- const from = name === CUSTOMIZE_SKILL_ENTRY_FILE
128
+ const from = SKILL_DIR_FILE_NAMES.has(name)
121
129
  ? join(sourceDir, "skills", "customize", name)
122
130
  : join(sourceDir, "src", name);
123
131
  try {
@@ -201,13 +209,13 @@ function assertNoDirectoryAtPayloadNames(destDir, payload, alreadyCurrent, polic
201
209
  /**
202
210
  * For every policy that replaces existing entries: removes an existing
203
211
  * `SKILL.md` entry (a file or a symlink, unlinked, never followed) BEFORE any
204
- * data file is rewritten, so a later failure never leaves a stale `SKILL.md`
205
- * loadable beside missing or half-rewritten data. Runs after
206
- * {@link assertNoDirectoryAtPayloadNames}, so a directory there has already
207
- * been refused (one raced in since makes `rmSync` throw). Returns the
208
- * removed path, if any; throws (wrapped) before anything is written when the
209
- * removal fails. `label` is how the entry is described: `"existing"` for a
210
- * project's own `.claude/` copy, `"stale"` for the CLI-owned staging.
212
+ * data or step file is rewritten, so a later failure never leaves a stale
213
+ * `SKILL.md` loadable beside missing or half-rewritten data or step files.
214
+ * Runs after {@link assertNoDirectoryAtPayloadNames}, so a directory there
215
+ * has already been refused (one raced in since makes `rmSync` throw). Returns
216
+ * the removed path, if any; throws (wrapped) before anything is written when
217
+ * the removal fails. `label` is how the entry is described: `"existing"` for
218
+ * a project's own `.claude/` copy, `"stale"` for the CLI-owned staging.
211
219
  */
212
220
  function removeStaleSkillEntry(destDir, label) {
213
221
  const staleEntry = join(destDir, CUSTOMIZE_SKILL_ENTRY_FILE);
@@ -323,8 +331,8 @@ function replacedClause(policy, skillRemoved, replaced, skillMaybeLeft) {
323
331
  if (skillRemoved === undefined && others === "") {
324
332
  return "";
325
333
  }
326
- // One sentence for SKILL.md and the data files alike: every one of
327
- // them was removed and none is restored.
334
+ // One sentence for SKILL.md and the other payload files alike: every
335
+ // one of them was removed and none is restored.
328
336
  const removedPaths = [
329
337
  ...(skillRemoved === undefined
330
338
  ? []
@@ -668,20 +676,20 @@ function installGuarded(targetDir, sourceDir) {
668
676
  * `fallbackCause` is `"component"` -- the entry (and any link target) is
669
677
  * left untouched.
670
678
  * - Otherwise, if every payload file already there is a regular file
671
- * matching what this CLI ships byte-for-byte: with all five present the
672
- * result is `"already-present"` (nothing written); with no `SKILL.md` file
673
- * (none at all, or an install interrupted before writing it) the missing
674
- * files are written into `.claude/skills/customize/`, `SKILL.md` last,
675
- * never rewriting or removing the correct ones.
679
+ * matching what this CLI ships byte-for-byte: with every payload file
680
+ * present the result is `"already-present"` (nothing written); with no
681
+ * `SKILL.md` file (none at all, or an install interrupted before writing
682
+ * it) the missing files are written into `.claude/skills/customize/`,
683
+ * `SKILL.md` last, never rewriting or removing the correct ones.
676
684
  * - Anything else under a payload name (a differing file, a regular file
677
685
  * that cannot be read, a symlink -- dangling or not -- a directory, a
678
- * `SKILL.md` without its data; detected by `lstat`) is kept as the
679
- * project's own: the skill is written to `.groundwork/customize/` instead,
680
- * `fallbackReason` names that entry (saying so when it could not be read)
681
- * and `fallbackCause` is `"entry"`. Adopt mode never guesses at a project
682
- * entry it cannot compare, and the fallback does not guess either: it
683
- * leaves that entry exactly as it was. Claude Code does not load a skill
684
- * from there; the caller must say so.
686
+ * `SKILL.md` without its data or step files; detected by `lstat`) is kept
687
+ * as the project's own: the skill is written to `.groundwork/customize/`
688
+ * instead, `fallbackReason` names that entry (saying so when it could not
689
+ * be read) and `fallbackCause` is `"entry"`. Adopt mode never guesses at a
690
+ * project entry it cannot compare, and the fallback does not guess either:
691
+ * it leaves that entry exactly as it was. Claude Code does not load a
692
+ * skill from there; the caller must say so.
685
693
  *
686
694
  * Writes into `.claude/skills/customize/` use `"wx"` only, so an entry that
687
695
  * appears there mid-install fails the run (rolled back) rather than being
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monte3l/groundwork",
3
- "version": "1.0.0-rc.4",
3
+ "version": "1.0.0-rc.5",
4
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",