@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
|
@@ -53,9 +53,173 @@ may or may not touch.
|
|
|
53
53
|
|
|
54
54
|
## Step 0 — Reconcile (adopt mode only)
|
|
55
55
|
|
|
56
|
-
1. Look for `.groundwork/inventory.json`.
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
1. Look for `.groundwork/inventory.json`.
|
|
57
|
+
- **Absent, and no `.groundwork/` directory either → this is a fresh
|
|
58
|
+
bootstrap; skip straight to Step 1.** Everything below this step applies
|
|
59
|
+
only when an inventory exists.
|
|
60
|
+
- **Absent, but `.groundwork/` exists → a previous CLI adopt run did not
|
|
61
|
+
complete** (the CLI deletes the old inventory before it stages anything
|
|
62
|
+
and writes the new one last, so no inventory beside a `.groundwork/`
|
|
63
|
+
directory means the run died part-way). **Stop. Never fall through to
|
|
64
|
+
the fresh flow** -- that would run fresh-mode tailoring on an
|
|
65
|
+
established project. Tell the user: "`.groundwork/` is incomplete: a
|
|
66
|
+
previous adopt run did not finish, or `inventory.json` was removed.
|
|
67
|
+
If this project was never adopted (it was bootstrapped fresh), delete
|
|
68
|
+
`.groundwork/` and run `/customize` again. Otherwise re-run
|
|
69
|
+
`npx @monte3l/groundwork@rc .` and then run `/customize` again."
|
|
70
|
+
Change nothing.
|
|
71
|
+
- **Present, but not valid JSON, or its `schemaVersion` is not an integer
|
|
72
|
+
of at least 1 → stop and change nothing.** Tell the user: "`.groundwork/inventory.json`
|
|
73
|
+
is not valid JSON or has no usable `schemaVersion`. Re-run
|
|
74
|
+
`npx @monte3l/groundwork@rc .` and then run `/customize` again."
|
|
75
|
+
|
|
76
|
+
**Check `inventory.schemaVersion` before reading anything else.** This
|
|
77
|
+
skill understands schema versions **1 through 5** (the highest it knows is
|
|
78
|
+
5). If `schemaVersion` is **higher than 5**, the CLI that wrote it is newer
|
|
79
|
+
than this plugin: **stop and change nothing**, do not interpret the
|
|
80
|
+
inventory (a newer schema may have renamed or repurposed fields, and a
|
|
81
|
+
confident misreading is worse than none), and tell the user to update the
|
|
82
|
+
plugin and re-run `/customize`. Say which update applies to the copy
|
|
83
|
+
that is running. For the plugin install, run `/plugin update`. For a
|
|
84
|
+
project-local copy in `.claude/skills/customize/`, `/plugin update` does
|
|
85
|
+
not touch it, and re-running the CLI alone does not either: the CLI
|
|
86
|
+
never overwrites a copy that differs (nor removes any other entry the
|
|
87
|
+
project owns there, nor writes through a symlinked `.claude`), it writes a
|
|
88
|
+
fresh one to `.groundwork/customize/`, which Claude Code does not load. So delete
|
|
89
|
+
that directory first (this discards any local edits the project made to
|
|
90
|
+
its copy) and then re-run `npx @monte3l/groundwork@rc .`. A
|
|
91
|
+
copy in `.groundwork/customize/` is refreshed by re-running the CLI. What
|
|
92
|
+
each version added:
|
|
93
|
+
|
|
94
|
+
| `schemaVersion` | Adds | If absent |
|
|
95
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
96
|
+
| 1 | the survey, `conflicts` | (the floor) |
|
|
97
|
+
| 2 | `packs` | no packs to offer; skip the pack question |
|
|
98
|
+
| 3 | `harnessGrade`, `harnessConformance` | skip the harness-grade starting point |
|
|
99
|
+
| 4 | `toolchainGrade`, `toolchainConformance` | skip the toolchain-grade starting point |
|
|
100
|
+
| 5 | `stagedBaseline` (`{ dir, suffix, files }`): the baseline additions staged at `.groundwork/baseline/`, each as `{ path, staged, sha256 }`; `stagedPacks` (per pack: `{ name, dir, suffix, manifest, files }`): every pack staged at `.groundwork/packs/<name>/`, its manifest and each file as `{ path, staged, sha256 }` | schema 1-4 only: read baseline additions from `inventory.templateRoot`; packs use the unsuffixed copy under `.groundwork/packs/` |
|
|
101
|
+
|
|
102
|
+
**For a schema 5 inventory only: verify the staged baseline now, before
|
|
103
|
+
anything is offered to the user.** A schema 1-4 inventory has no
|
|
104
|
+
`stagedBaseline`: skip this whole block (every bullet below, including
|
|
105
|
+
its stop list) and use the `inventory.templateRoot` fallback in Round 1.
|
|
106
|
+
The inventory lives in the project tree and is untrusted input, so check
|
|
107
|
+
it before trusting any entry:
|
|
108
|
+
|
|
109
|
+
- `stagedBaseline.dir` must equal `.groundwork/baseline` exactly, and
|
|
110
|
+
`stagedBaseline.suffix` must equal `.staged` exactly. Take both values
|
|
111
|
+
from this list, not from the inventory: a `dir` of `.` with an empty
|
|
112
|
+
`suffix` would make you "verify" live project files.
|
|
113
|
+
- For every entry of `inventory.stagedBaseline.files`, require
|
|
114
|
+
`staged === path + ".staged"`, and require `path` to be relative, free
|
|
115
|
+
of any `..` segment, and not absolute. Reject the entry if `path` is
|
|
116
|
+
`""` or `"."`. Reject it too if `path` contains a `\` or a `:` (a
|
|
117
|
+
Windows `..\..` or `C:foo` would slip past the other checks). Reject a
|
|
118
|
+
duplicate `path` or a duplicate `staged` among the entries. These fields
|
|
119
|
+
use `/` separators on every platform: `conflicts[].relPath`,
|
|
120
|
+
`packs[].fileConflicts[].relPath`, `stagedBaseline.dir`,
|
|
121
|
+
`stagedBaseline.files[].path` and its `.staged` name, `stagedPacks[].dir`,
|
|
122
|
+
`stagedPacks[].files[].path` and `stagedPacks[].files[].staged`. Other paths in
|
|
123
|
+
the inventory are not normalized: `templateRoot` and `targetDir` are
|
|
124
|
+
absolute native paths, as are the survey's tsconfig chain entries.
|
|
125
|
+
- The `absent` conflicts in `inventory.conflicts` and the paths in
|
|
126
|
+
`stagedBaseline.files` must name the same set of files. If they
|
|
127
|
+
disagree (an `absent` conflict with no staged entry, or a staged entry
|
|
128
|
+
that is not an `absent` conflict), that is a mismatch: stop, with the
|
|
129
|
+
same message as a hash mismatch, before anything is offered or approved.
|
|
130
|
+
- Read each staged file at `.groundwork/baseline/<staged>` **once**.
|
|
131
|
+
It must exist, and the SHA-256 of its **raw bytes** (no end-of-line
|
|
132
|
+
normalization, no decoding) must equal the entry's `sha256`. Compute it
|
|
133
|
+
with, for example, this one-liner (it targets a POSIX shell or Git Bash,
|
|
134
|
+
not `cmd.exe` or an old PowerShell), passing the file as a single quoted
|
|
135
|
+
argument in place of `<file>`:
|
|
136
|
+
`node -e 'process.stdout.write(require("crypto").createHash("sha256").update(require("fs").readFileSync(process.argv[1])).digest("hex"))' <file>`
|
|
137
|
+
Keep those same bytes for the install in Round 1 (substitute tokens into
|
|
138
|
+
them) rather than reading the file a second time.
|
|
139
|
+
- **Staged packs, in the same block.** For every entry of
|
|
140
|
+
`inventory.stagedPacks`:
|
|
141
|
+
- `dir` must equal `.groundwork/packs/<name>`, built from the entry's
|
|
142
|
+
own `name`, and `suffix` must equal `.staged`. Take both from this
|
|
143
|
+
list, not from the inventory.
|
|
144
|
+
- `name` must be a single path segment: not empty, not `.` or `..`, and
|
|
145
|
+
free of `/`, `\` and `:`. Reject a duplicate pack `name`.
|
|
146
|
+
- `manifest.path` must equal `pack.json` and `manifest.staged` must
|
|
147
|
+
equal `pack.json.staged`.
|
|
148
|
+
- For every entry of its `files`, require `staged === path + ".staged"`,
|
|
149
|
+
and apply the same path checks as the staged baseline's files above
|
|
150
|
+
(relative, no `..` segment, not absolute, not `""` or `"."`, no `\` or
|
|
151
|
+
`:`). Reject a duplicate `path` or a duplicate `staged` among one
|
|
152
|
+
pack's files.
|
|
153
|
+
- The pack names in `inventory.packs` and in `inventory.stagedPacks`
|
|
154
|
+
must be the same set, and for each pack its `fileConflicts[].relPath`
|
|
155
|
+
set must equal its `files[].path` set.
|
|
156
|
+
- Read the staged manifest at `<dir>/pack.json.staged` and each staged
|
|
157
|
+
file at `<dir>/files/<staged>` once, and apply the SHA-256 check above
|
|
158
|
+
to the raw bytes of each. Keep the bytes Step 0.1 read (hash-checked
|
|
159
|
+
when a command could run): Round 1's install and the prototype-key
|
|
160
|
+
check in Step 0.4(c) use them, with no second read.
|
|
161
|
+
- **No shell tool available.** If a Bash or other command-running tool is
|
|
162
|
+
available, compute the hash as above. If you cannot run a command, do
|
|
163
|
+
not work around it: write no scratch script; while verifying, make no
|
|
164
|
+
`Write` or `Edit` outside `.groundwork/` (Round 1's confirmed installs are
|
|
165
|
+
not part of verification), dispatch no subagent to look for a shell, and
|
|
166
|
+
search for a command tool at most once. Skip only the SHA-256
|
|
167
|
+
comparison. Run every other check in this block with the file tools
|
|
168
|
+
(`Read`, `Glob`, `Grep`): the files exist, `staged === path + ".staged"`,
|
|
169
|
+
the paths are relative with no `..`, `\` or `:`, no duplicates, `dir`
|
|
170
|
+
and `suffix` exact, the `absent` conflicts and `stagedBaseline.files`
|
|
171
|
+
name the same set, and no extra staged file exists: list the staged
|
|
172
|
+
files with the `Glob` pattern `.groundwork/baseline/**/*.staged` and
|
|
173
|
+
compare with `stagedBaseline.files`. A `Glob` can skip hidden paths
|
|
174
|
+
(most staged files are dot-paths), honour an ignore file or truncate a
|
|
175
|
+
long list, so a result shorter than `stagedBaseline.files.length`, or
|
|
176
|
+
that looks truncated, is undetermined: report it in the Step 0.4 summary
|
|
177
|
+
and continue, since every listed entry's existence is already checked
|
|
178
|
+
one by one; only an extra `*.staged` file, one whose path is not in
|
|
179
|
+
`stagedBaseline.files`, stops the run. Run the same structural checks
|
|
180
|
+
for `inventory.stagedPacks`: each pack's `<dir>/pack.json.staged` and
|
|
181
|
+
every `<dir>/files/<staged>` exists, `staged === path + ".staged"` with
|
|
182
|
+
paths that are relative and free of `..`, `\` and `:`, no duplicates,
|
|
183
|
+
`name`, `dir`, `suffix`, `manifest.path` and `manifest.staged` exact,
|
|
184
|
+
the pack names in `inventory.packs` and `inventory.stagedPacks` the
|
|
185
|
+
same set, and each pack's `fileConflicts[].relPath` and `files[].path`
|
|
186
|
+
the same set. List each pack's staged files with the `Glob` pattern
|
|
187
|
+
`.groundwork/packs/**/*.staged` (the same hidden-path and
|
|
188
|
+
truncation caveats apply) and compare with every listed manifest and
|
|
189
|
+
file: an extra `*.staged` file at any depth under `.groundwork/packs/` that is neither a listed manifest nor a listed file stops the run. This is a partial no-shell
|
|
190
|
+
substitute for what the hash proves, and it is not tamper-resistance.
|
|
191
|
+
Then spend no further turns on verification and go on to the deep
|
|
192
|
+
read. State this plainly at the top of your first message to the user (the Step 0.4 summary, not a
|
|
193
|
+
separate earlier stop), and ask whether to continue or stop in that
|
|
194
|
+
same confirmation: the SHA-256 check was skipped because no command
|
|
195
|
+
could be run; a passing check would only have proven that the staging
|
|
196
|
+
is complete and matches the inventory, not that the files are
|
|
197
|
+
untampered; and which structural checks you did verify instead. Also
|
|
198
|
+
record the skip in `.groundwork/adoption-report.md` when you write the
|
|
199
|
+
findings back in Step 0.3. A structural failure, including an extra staged file, still stops, exactly as the stop list below says.
|
|
200
|
+
- An empty `files` list is legitimate (nothing was missing from the
|
|
201
|
+
project) and creates no `.groundwork/baseline/` directory; that alone is
|
|
202
|
+
not a failure.
|
|
203
|
+
- **For a schema 5 inventory, a `stagedBaseline` that is missing, not an
|
|
204
|
+
object, or whose `files` is not an array also stops the run** (a
|
|
205
|
+
`files: {}` is not an empty list); so does a `stagedPacks` that is
|
|
206
|
+
missing or not an array, or a pack entry that is not an object or whose
|
|
207
|
+
`files` is not an array. **Any invalid entry, missing file or hash mismatch (including a
|
|
208
|
+
wrong `dir` or `suffix`), any duplicate `staged` or `path` or pack `name`, any
|
|
209
|
+
`absent` conflicts and `stagedBaseline.files` that do not name the same
|
|
210
|
+
set, any pack whose names or file paths disagree with `inventory.packs`, and
|
|
211
|
+
(no-shell path) an extra `*.staged` file not named in
|
|
212
|
+
`stagedBaseline.files`, a pack's `files` or a pack's manifest
|
|
213
|
+
means stop -- all of Round 1, including conflicts and packs -- and
|
|
214
|
+
change nothing.** This is the single stop list for the staged baseline and the staged packs.
|
|
215
|
+
Tell the user: "The staged baseline in `.groundwork/baseline/` or a staged pack in `.groundwork/packs/` is incomplete or does not match `.groundwork/inventory.json` (<the first entry that failed and why>). Re-run `npx @monte3l/groundwork@rc .` and then run `/customize` again." **Never fall back to `inventory.templateRoot` for a schema 5 inventory, packs included:** that fallback exists for a schema 1-4 inventory only, and only for the baseline additions (a schema 1-4 inventory's packs are read from their unsuffixed copy, see Step 0.4(c) and Round 1).
|
|
216
|
+
- What a passing check proves: the staging is complete and matches the
|
|
217
|
+
inventory. It does **not** prove the files are untampered -- anyone who
|
|
218
|
+
can edit the staged files can edit the inventory's hashes too.
|
|
219
|
+
|
|
220
|
+
An inventory with `schemaVersion` below 5 has no staged copy; its
|
|
221
|
+
approved additions are read from `inventory.templateRoot` (see Round 1).
|
|
222
|
+
|
|
59
223
|
2. **The deep read.** The CLI's survey is an index, not an interpretation —
|
|
60
224
|
it flagged what it found but could not parse (`needsReading: true` on
|
|
61
225
|
git-hook config, workflow files; anything in `survey.undetermined`) and
|
|
@@ -95,7 +259,9 @@ may or may not touch.
|
|
|
95
259
|
3. **Write the findings back** into `.groundwork/adoption-report.md`,
|
|
96
260
|
replacing the CLI's index-level sections ("a `lefthook.yml` exists")
|
|
97
261
|
with semantic ones ("pre-push runs lint and typecheck; tests do not
|
|
98
|
-
gate").
|
|
262
|
+
gate"). If the no-shell bullet in step 1 applied, carry its skip note
|
|
263
|
+
into the rewritten report: this step replaces the report's sections, so
|
|
264
|
+
a note written earlier would be dropped.
|
|
99
265
|
4. **Confirm.** Give a short summary in chat, then ask **one**
|
|
100
266
|
`AskUserQuestion` covering: (a) _did this miss anything about your
|
|
101
267
|
project?_ — the free-text option is the point of this question, not a
|
|
@@ -114,8 +280,26 @@ may or may not touch.
|
|
|
114
280
|
dropped. This is index-level evidence from the CLI, not a kind-based
|
|
115
281
|
judgment — see Step 3's note on revisiting it once the interview confirms
|
|
116
282
|
the project's kind.
|
|
283
|
+
|
|
284
|
+
The same question also carries (d) if the no-shell bullet applied: say the
|
|
285
|
+
SHA-256 check was skipped, what a passing check would have proven,
|
|
286
|
+
which checks ran instead and any undetermined result, and
|
|
287
|
+
ask whether to continue or stop.
|
|
288
|
+
|
|
289
|
+
Before offering any pack, check each staged `.groundwork/packs/<name>/pack.json.staged` (the bytes Step 0.1 read, hash-checked when a command could run; not a fresh read):
|
|
290
|
+
if `__proto__`, `constructor` or `prototype` is a key of its `wiring.settings`
|
|
291
|
+
(hook event names), `wiring.settingsTopLevel` or `wiring.packageScripts`
|
|
292
|
+
(script names), stop. The project tree is untrusted, and the CLI refuses such a
|
|
293
|
+
pack before staging it, so a staged manifest carrying one was edited after
|
|
294
|
+
staging. Name the pack, the field and the key, tell the user to delete
|
|
295
|
+
`.groundwork/` and re-run the CLI, and offer nothing from this run. Change nothing.
|
|
296
|
+
For a schema 1-4 inventory (the layout of the CLI releases before the `.staged` convention) there is no `.staged` copy and no hash: read the unsuffixed `.groundwork/packs/<name>/pack.json` (not hash-verified) and run this same prototype-key check on it.
|
|
297
|
+
|
|
117
298
|
5. **Record the confirmed decisions** to `.groundwork/adoption-decisions.json`
|
|
118
299
|
so a compacted or resumed session doesn't silently lose them and re-ask.
|
|
300
|
+
A CLI re-run deletes this file along with the old inventory, because its
|
|
301
|
+
decisions were made against the previous staging; a decisions file found
|
|
302
|
+
beside a fresh inventory therefore belongs to this inventory.
|
|
119
303
|
|
|
120
304
|
## Step 1 — Interview
|
|
121
305
|
|
|
@@ -206,25 +390,53 @@ CI, husky locally, whatever it is), not to `lefthook.yml`/`ci.yml` by name.
|
|
|
206
390
|
Concretely, adopt-mode Round 1 applies exactly three things, all already
|
|
207
391
|
confirmed in Step 0.4:
|
|
208
392
|
|
|
209
|
-
- The **approved additions** — files `templates/core`
|
|
210
|
-
|
|
211
|
-
|
|
393
|
+
- The **approved additions** — files `templates/core` would add that the
|
|
394
|
+
project doesn't have and the user approved adding. For a schema 5 inventory, install them from the staged copy Step 0.1 already verified,
|
|
395
|
+
using the bytes you read then (Step 0.1 also already checked that the
|
|
396
|
+
staged files match the `absent` conflicts). Write them to the project at `path` (the
|
|
397
|
+
`.staged` suffix stripped, never to the staged name), filling in the
|
|
398
|
+
`__KEY__` tokens with the project's real values as you copy, same as
|
|
399
|
+
staged packs. Only a **schema 1-4** inventory has no staged copy and reads
|
|
400
|
+
additions from `inventory.templateRoot`; if that path no longer exists (a
|
|
401
|
+
pruned `npx` cache, a deleted temp checkout), say so and ask for a CLI
|
|
402
|
+
re-run rather than guessing at the baseline's contents.
|
|
212
403
|
- The **approved conflict resolutions** — for each divergent file the user
|
|
213
404
|
decided on, apply that decision (keep theirs / take groundwork's / merge
|
|
214
405
|
the named keys).
|
|
215
406
|
- The **approved packs** — installed from `.groundwork/packs/<name>/` (the
|
|
216
|
-
CLI's staged, self-contained copy
|
|
217
|
-
may not exist by the time this runs). Before installing, call
|
|
407
|
+
CLI's staged, self-contained copy of inert `.staged` files — never
|
|
408
|
+
`inventory.templateRoot`, which may not exist by the time this runs). Before installing, call
|
|
218
409
|
`recommendPacks(answers)` from `pack-map.ts` (alongside this file, same
|
|
219
410
|
copy mechanism as `kind-facet-map.ts`) with the now-confirmed
|
|
220
|
-
`InterviewAnswers` and compare its verdict against Step 0.4's decision.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
411
|
+
`InterviewAnswers` and compare its verdict against Step 0.4's decision.
|
|
412
|
+
`harness-extras`, `github`, `supply-chain`, `quality`, and `worktrees`
|
|
413
|
+
never disagree (none of the five's recommendation varies by kind or
|
|
414
|
+
answer -- `worktrees` is always `recommended: false`, since it changes the
|
|
415
|
+
day-to-day workflow rather than adding a nicety, and the other four are
|
|
416
|
+
always `recommended: true`), but `publishing`'s does (recommended for
|
|
417
|
+
`library`/`cli`, not for `frontend`/`service`) — if the comparison surfaces a real
|
|
418
|
+
conflict there or for any future kind-scoped pack, raise it rather than
|
|
419
|
+
silently overriding the user's Step 0.4 answer, mirroring Step 4's "the
|
|
420
|
+
one exception" rule for guidance findings. Before installing, check the
|
|
421
|
+
pack's own `modes`: a pack whose `modes` doesn't include `"adopt"` (today,
|
|
422
|
+
`publishing` — its release flow encodes decisions too project-specific to
|
|
423
|
+
apply blind) is never auto-installed here even if staged and approved;
|
|
424
|
+
instead, state in Step 6 that it needs a manual install (point at `.groundwork/packs/<name>/` and the pack's own `adoptNotes`, and say to strip the `.staged` suffix from every name when copying by hand and to replace every `__KEY__` token with the project's real value) and stop
|
|
425
|
+
there for that pack. Before merging any staged `pack.json.staged` wiring, repeat
|
|
426
|
+
the prototype-key check from Step 0.4(c): if a key of `wiring.settings`,
|
|
427
|
+
`wiring.settingsTopLevel` or `wiring.packageScripts` is `__proto__`,
|
|
428
|
+
`constructor` or `prototype`, stop the same way and change nothing. For an
|
|
429
|
+
adopt-capable pack, install each file from
|
|
430
|
+
`.groundwork/packs/<name>/files/<path>.staged`, using the bytes Step 0.1 read (hash-checked when a command could run), and write it to the project at `path` (the `.staged` suffix
|
|
431
|
+
stripped, never to the staged name), filling in the `__KEY__` tokens with
|
|
432
|
+
the project's real values as you copy (respecting any approved per-file
|
|
433
|
+
conflict decision the same way the baseline's own additions are applied).
|
|
434
|
+
For a schema 1-4 inventory, install each file from the unsuffixed
|
|
435
|
+
`.groundwork/packs/<name>/files/<path>` instead (no `.staged` suffix to strip,
|
|
436
|
+
not hash-verified; token substitution still applies).
|
|
437
|
+
Then, for either schema, translate `pack.json`'s `wiring` by hand, reading it
|
|
438
|
+
from `pack.json.staged` (the bytes Step 0.1 read) for a schema 5 inventory and
|
|
439
|
+
from the unsuffixed `pack.json` for schema 1-4,
|
|
228
440
|
against what Step 0.2's deep read already found — a `.claude/settings.json`
|
|
229
441
|
hook fragment merges the same way the baseline's own hook entries would;
|
|
230
442
|
`wiring.settingsTopLevel` is a set of top-level keys (e.g. `statusLine`)
|
|
@@ -233,7 +445,13 @@ confirmed in Step 0.4:
|
|
|
233
445
|
`mergeSettingsTopLevel` treats a differing value as a hard error and this
|
|
234
446
|
hand-applied path must not be laxer than the automated one (also check
|
|
235
447
|
`.claude/settings.local.json` and the user's `~/.claude/settings.json`,
|
|
236
|
-
either of which can shadow a project `statusLine`)
|
|
448
|
+
either of which can shadow a project `statusLine`). For `harness-extras`
|
|
449
|
+
specifically, a `statusLine`/`subagentStatusLine` collision is never a
|
|
450
|
+
reason to fail the whole pack install: skip just those two settings keys
|
|
451
|
+
and the three statusline scripts (`statusline.mjs`, `statusline-layout.mjs`,
|
|
452
|
+
`subagent-statusline.mjs`) and install the pack's other artifacts (the
|
|
453
|
+
compaction-handoff hooks and `guard-readonly-bash`) normally, stating the
|
|
454
|
+
skip plainly in Step 6;
|
|
237
455
|
`wiring.verifySteps` becomes a step in whatever this project's real gate
|
|
238
456
|
runner is (a `package.json` script plus a line in its `lefthook.yml`/
|
|
239
457
|
`.husky/pre-push`/CI workflow, written by hand to match its actual shape)
|
|
@@ -241,6 +459,49 @@ confirmed in Step 0.4:
|
|
|
241
459
|
other artifacts and state plainly in Step 6 that the gate was not wired,
|
|
242
460
|
rather than inventing a runner the project never asked for.
|
|
243
461
|
|
|
462
|
+
**Plugins (both modes), after packs are settled above.** Build a
|
|
463
|
+
`PluginRecommendationContext`: `chosenPacks` is whatever the packs decision
|
|
464
|
+
just above actually landed on (fresh: what `--pack` installed at bootstrap
|
|
465
|
+
time, detectable from the installed files -- e.g. `.changeset/config.json`
|
|
466
|
+
means `publishing`, `.github/workflows/claude-pr-review.yml` means `github`
|
|
467
|
+
(the only marker `plugin-map.ts` actually reads; `harness-extras` has no
|
|
468
|
+
plugin that varies by its presence, so it needs no marker here); adopt: the
|
|
469
|
+
packs Step 0.4(c) confirmed, revised by this step's own `recommendPacks`
|
|
470
|
+
comparison if it changed anything); `hasCustomSkills` is `false` for a fresh
|
|
471
|
+
bootstrap (nothing has authored a skill yet) and, for adopt mode, whatever
|
|
472
|
+
Step 0's survey found beyond the baseline's own known skill names and any
|
|
473
|
+
already-installed pack's skills (e.g. the `github` pack's three). Call
|
|
474
|
+
`recommendPlugins(answers, context)` from `plugin-map.ts`
|
|
475
|
+
(alongside this file, same copy mechanism as `pack-map.ts`) with the
|
|
476
|
+
now-confirmed `InterviewAnswers`, and ask **one** `AskUserQuestion`
|
|
477
|
+
(multi-select) offering all seven, pre-selected per each entry's
|
|
478
|
+
`recommended` boolean with its `because` shown as the evidence -- same
|
|
479
|
+
"visible reasoning" principle as every other inference in this skill.
|
|
480
|
+
|
|
481
|
+
Write every confirmed `true` entry into `.claude/settings.json`'s
|
|
482
|
+
`enabledPlugins` (`{"<id>": true}` per entry, e.g.
|
|
483
|
+
`"context7@claude-plugins-official": true`) -- additive and entry-by-entry,
|
|
484
|
+
same discipline as the CLI's own `mergeSettingsHooks` (which owns the
|
|
485
|
+
`hooks` block entry-by-entry, as opposed to `mergeSettingsTopLevel`'s
|
|
486
|
+
whole-key-at-a-time semantics): never remove or flip an entry the project
|
|
487
|
+
already sets explicitly (an existing `false` is a decision the user made,
|
|
488
|
+
not an oversight to correct), and never touch `.claude/settings.local.json`
|
|
489
|
+
or the user's own `~/.claude/settings.json` scope. `claude-plugins-official`
|
|
490
|
+
is a built-in marketplace, so no `extraKnownMarketplaces` entry is needed
|
|
491
|
+
for any of the seven.
|
|
492
|
+
|
|
493
|
+
**Committing this entry does not install the plugin for anyone.** A
|
|
494
|
+
project-scope `enabledPlugins: true` with no local install produces no
|
|
495
|
+
folder-trust auto-prompt -- Claude Code's `/plugin` Errors tab instead shows
|
|
496
|
+
"enabled in project settings but isn't installed here" until someone runs
|
|
497
|
+
the install by hand. So for every newly-`true` entry, print the exact
|
|
498
|
+
follow-up command in Step 6's report: `claude plugin install <id> --scope
|
|
499
|
+
project` (or `/plugin install <id>` inside a running session) -- the user,
|
|
500
|
+
and every collaborator who pulls this change, still has to run it once. Do
|
|
501
|
+
the same for each recommendation's `prerequisites` (the
|
|
502
|
+
`typescript-language-server` binary, Python 3.8+) -- print them as
|
|
503
|
+
follow-ups, never attempt to install them.
|
|
504
|
+
|
|
244
505
|
Nothing else is touched. A project file the user didn't approve a change to
|
|
245
506
|
stays exactly as it was.
|
|
246
507
|
|
|
@@ -263,6 +524,12 @@ Step 2's plan to decide which facet gets the deepest attention this run,
|
|
|
263
524
|
not which facets it's allowed to touch — and enters plan mode with a
|
|
264
525
|
remediation plan if it finds drift.
|
|
265
526
|
|
|
527
|
+
Also offer `typescript-guidance`'s `gaps` mode here, for gaps rather than
|
|
528
|
+
drift — what TypeScript-ecosystem tooling the project is missing entirely, as
|
|
529
|
+
opposed to either sweep's "is what's already configured still current." It
|
|
530
|
+
is not a third mandatory sweep: run it only if the user wants a tooling-gap
|
|
531
|
+
pass alongside the two refreshes.
|
|
532
|
+
|
|
266
533
|
**In adopt mode**, a sweep's domain is the project's real files, classified
|
|
267
534
|
by `domain-map.ts`'s `classifyPath` (the same module and glob lists that
|
|
268
535
|
guard the emitted baseline — broadened to cover common non-baseline
|
|
@@ -303,3 +570,10 @@ the CLI's report missed (if anything), which conflicts were resolved and
|
|
|
303
570
|
how, any domain-map coverage gap Step 4 surfaced, and **which packs were
|
|
304
571
|
installed and what each wired** (or, for a pack whose gate had no runner to
|
|
305
572
|
attach to, that it was skipped and why).
|
|
573
|
+
|
|
574
|
+
Also list **which plugins were enabled** (each newly-`true`
|
|
575
|
+
`enabledPlugins` entry, with the exact `claude plugin install <id> --scope
|
|
576
|
+
project` follow-up command it still needs) and which were offered but
|
|
577
|
+
declined, plus any prerequisite named against an enabled plugin
|
|
578
|
+
(`typescript-language-server` on `PATH`, Python 3.8+) as a follow-up the
|
|
579
|
+
user still has to satisfy.
|
package/plugin/src/domain-map.ts
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright the m3l-groundwork contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
|
-
* Which files each guidance sweep is responsible for.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* the
|
|
5
|
+
* Which files each guidance sweep is responsible for. A "guidance sweep" is
|
|
6
|
+
* the live research pass `/customize` runs over official upstream sources for
|
|
7
|
+
* one domain: `typescript-guidance` sweeps the TypeScript toolchain against
|
|
8
|
+
* official TypeScript sources, and `harness-guidance` sweeps the Claude Code
|
|
9
|
+
* harness against official Anthropic sources. Each sweep covers a fixed set of
|
|
10
|
+
* "facets" (research topics within its domain, such as `compiler-config-flags`
|
|
11
|
+
* or `hooks-lifecycle`); the interview's project "kind" (a `ProjectKind`: the
|
|
12
|
+
* archetype -- library, cli, frontend or service -- the project is classified
|
|
13
|
+
* as) only changes which facets get the most emphasis, never which files a
|
|
14
|
+
* sweep owns. This module answers the file-ownership question.
|
|
15
|
+
*
|
|
16
|
+
* Used two ways: against the emitted baseline, to confirm neither sweep has a
|
|
17
|
+
* blind spot in `templates/core` before reporting a clean run (unit-tested
|
|
18
|
+
* directly against the real tree in `tests/domain-map.test.ts`, so a new
|
|
19
|
+
* template file added later can't silently fall outside both domains without
|
|
20
|
+
* a test noticing); and in adopt mode, to classify a real pre-existing
|
|
21
|
+
* project's files, which is why the glob lists also cover common
|
|
22
|
+
* non-baseline equivalents (`.eslintrc.*`, `jest.config.*`, `.husky/**`,
|
|
23
|
+
* ...) alongside the baseline's own exact filenames.
|
|
11
24
|
*/
|
|
12
25
|
|
|
13
26
|
/** Simple glob support: `**` matches any sequence (including `/`), `*` matches within a segment. */
|
|
@@ -28,7 +41,7 @@ export function matchesAnyGlob(
|
|
|
28
41
|
return globs.some((glob) => globToRegExp(glob).test(path));
|
|
29
42
|
}
|
|
30
43
|
|
|
31
|
-
/** Every TypeScript-facing file `typescript-guidance` is responsible for. */
|
|
44
|
+
/** Every TypeScript-facing file the `typescript-guidance` sweep is responsible for. */
|
|
32
45
|
export const TYPESCRIPT_DOMAIN_GLOBS = [
|
|
33
46
|
"tsconfig*.json",
|
|
34
47
|
"**/tsconfig*.json",
|
|
@@ -60,6 +73,11 @@ export const TYPESCRIPT_DOMAIN_GLOBS = [
|
|
|
60
73
|
"bin/lib/*.mjs",
|
|
61
74
|
"bin/lib/*.json",
|
|
62
75
|
".github/workflows/*.yml",
|
|
76
|
+
".github/dependabot.yml",
|
|
77
|
+
".github/release-tools/**",
|
|
78
|
+
".changeset/**",
|
|
79
|
+
".gitleaks.toml",
|
|
80
|
+
"REUSE.toml",
|
|
63
81
|
"docs/research/typescript-refresh.md",
|
|
64
82
|
"src/**",
|
|
65
83
|
"tests/**",
|
|
@@ -69,16 +87,22 @@ export const TYPESCRIPT_DOMAIN_GLOBS = [
|
|
|
69
87
|
* Harness-grader files that live under `bin/`. `bin/*.mjs` and
|
|
70
88
|
* `bin/lib/*.mjs` are typescript-domain globs, so without this list the
|
|
71
89
|
* grader's own rules would be swept by `typescript-guidance` -- wrong,
|
|
72
|
-
* because they encode Claude Code harness guidance.
|
|
73
|
-
*
|
|
90
|
+
* because they encode Claude Code harness guidance. The Claude Code Action
|
|
91
|
+
* workflows (`claude.yml`, and the `github` pack's automated-review
|
|
92
|
+
* `claude-pr-review.yml`) are here for the same reason against
|
|
93
|
+
* `.github/workflows/*.yml`: their trigger, action pin and model choice are
|
|
94
|
+
* Anthropic guidance, not toolchain. Consulted before the typescript list in
|
|
95
|
+
* `classifyPath`.
|
|
74
96
|
*/
|
|
75
97
|
export const HARNESS_OVERRIDE_GLOBS = [
|
|
76
98
|
"bin/check-harness.mjs",
|
|
77
99
|
"bin/lib/harness-rules.mjs",
|
|
78
100
|
"bin/lib/frontmatter.mjs",
|
|
101
|
+
".github/workflows/claude.yml",
|
|
102
|
+
".github/workflows/claude-pr-review.yml",
|
|
79
103
|
] as const;
|
|
80
104
|
|
|
81
|
-
/** Every `.claude/`-facing file `harness-guidance` is responsible for. */
|
|
105
|
+
/** Every `.claude/`-facing file the `harness-guidance` sweep is responsible for. */
|
|
82
106
|
export const HARNESS_DOMAIN_GLOBS = [
|
|
83
107
|
".claude/settings.json",
|
|
84
108
|
".claude/settings.local.json",
|
|
@@ -90,11 +114,12 @@ export const HARNESS_DOMAIN_GLOBS = [
|
|
|
90
114
|
".claude/commands/**",
|
|
91
115
|
".claude-plugin/**",
|
|
92
116
|
".mcp.json",
|
|
117
|
+
".worktreeinclude",
|
|
93
118
|
"CLAUDE.md",
|
|
94
119
|
"docs/research/harness-refresh.md",
|
|
95
120
|
] as const;
|
|
96
121
|
|
|
97
|
-
/** Files neither sweep governs by design -- not a gap, an explicit exclusion. */
|
|
122
|
+
/** Files neither guidance sweep governs by design -- not a gap, an explicit exclusion. */
|
|
98
123
|
export const NEUTRAL_GLOBS = [
|
|
99
124
|
"README.md",
|
|
100
125
|
".gitignore",
|
package/plugin/src/index.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright the m3l-groundwork contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
/** Public surface of `@monte3l/groundwork-plugin`: the /customize skill's deterministic backing data. */
|
|
2
5
|
export * from "./kind-facet-map.js";
|
|
3
6
|
export * from "./domain-map.js";
|
|
4
7
|
export * from "./pack-map.js";
|
|
8
|
+
export * from "./plugin-map.js";
|
|
@@ -1,14 +1,31 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: Copyright the m3l-groundwork contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
|
-
* The kind-to-facet table `/customize` reads to plan its guidance-
|
|
3
|
-
* research priority.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* The kind-to-facet table `/customize` reads to plan its guidance-sweep
|
|
6
|
+
* research priority. Three terms recur throughout this file:
|
|
7
|
+
*
|
|
8
|
+
* - A "kind" is a `ProjectKind`: the project archetype the interview
|
|
9
|
+
* classifies the project as (library, cli, frontend or service).
|
|
10
|
+
* - A "guidance sweep" is the live research pass `/customize` runs over
|
|
11
|
+
* official TypeScript and Anthropic sources, once per domain (TypeScript
|
|
12
|
+
* toolchain, Claude Code harness).
|
|
13
|
+
* - A "facet" is one fixed research topic within a domain -- for example
|
|
14
|
+
* `compiler-config-flags` is a TypeScript facet and `hooks-lifecycle` is a
|
|
15
|
+
* harness facet. A guidance sweep always covers every facet of its domain,
|
|
16
|
+
* whether or not the interview emphasized it.
|
|
17
|
+
*
|
|
18
|
+
* This table is a stored, unit-tested module -- not a judgment made afresh
|
|
19
|
+
* each run -- so the same interview answers always produce the same facet
|
|
20
|
+
* plan.
|
|
6
21
|
*
|
|
7
|
-
* Scope note (load-bearing): this table scopes research PRIORITY only.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
22
|
+
* Scope note (load-bearing): this table scopes research PRIORITY only. It
|
|
23
|
+
* decides which facets get the most emphasis, never what a guidance sweep
|
|
24
|
+
* is allowed to touch. Both guidance skills
|
|
25
|
+
* (templates/core/.claude/skills/typescript-guidance and harness-guidance)
|
|
26
|
+
* retain full authority to amend anything in their domain, regardless of what
|
|
10
27
|
* this table emphasizes -- see their SKILL.md "Authority" sections. A facet
|
|
11
|
-
* with low priority here still gets swept
|
|
28
|
+
* with low priority here still gets swept. It just isn't the one a dedicated
|
|
12
29
|
* research agent digs into deepest.
|
|
13
30
|
*/
|
|
14
31
|
|