@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
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Upstream tooling sources -- the allowlist
|
|
2
|
+
|
|
3
|
+
The sibling allowlist to `typescript-sources.md` in this same directory
|
|
4
|
+
(reused directly for the TypeScript-owner tier, not duplicated). This file
|
|
5
|
+
is `gaps` mode's ecosystem-tooling list and covers the TypeScript-adjacent
|
|
6
|
+
tooling `research` and `refresh` don't sweep: the package manager, the lint
|
|
7
|
+
runner's non-TypeScript-specific config, the test runner, the formatter,
|
|
8
|
+
dependency hygiene, and Node's own release schedule.
|
|
9
|
+
|
|
10
|
+
**A `gaps`-mode research brief passes the union of both files' domain lists**
|
|
11
|
+
when an area touches TypeScript itself (the tsconfig/typed-linting areas
|
|
12
|
+
always need `typescript-sources.md`'s list too); an area this file alone
|
|
13
|
+
covers (pnpm settings, Node pinning) needs only this file's list. Each file's
|
|
14
|
+
own GitHub caveat applies only to the GitHub paths it names regardless -- a
|
|
15
|
+
path allowed by `typescript-sources.md`'s caveat is not automatically allowed
|
|
16
|
+
by this file's caveat, and vice versa.
|
|
17
|
+
|
|
18
|
+
## Domain allowlist
|
|
19
|
+
|
|
20
|
+
Pass verbatim as `WebSearch`'s `allowed_domains`, alongside
|
|
21
|
+
`typescript-guidance`'s own list when both are in scope for a given area:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
pnpm.io, knip.dev, vitest.dev, eslint.org, prettier.io, docs.npmjs.com,
|
|
25
|
+
nodejs.org
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Plus **the official docs of a tool the project's interview actually
|
|
29
|
+
selected** for bundling, if one was chosen and isn't already covered above
|
|
30
|
+
(a specific bundler's own docs).
|
|
31
|
+
|
|
32
|
+
One of the fixed domains is **path-scoped within a domain
|
|
33
|
+
`typescript-guidance` also uses, for a different path**:
|
|
34
|
+
|
|
35
|
+
- `nodejs.org` hosts the whole Node.js documentation site.
|
|
36
|
+
`typescript-guidance`'s own allowlist scopes it to `/api/typescript.html`
|
|
37
|
+
(the runtime type-stripping boundary). This file's own scope is
|
|
38
|
+
`/en/about/previous-releases` (the LTS/EOL schedule), for the
|
|
39
|
+
Node-version-pinning area only. Passing a bare `nodejs.org` to
|
|
40
|
+
`allowed_domains` allows both paths; treat a citation from any other
|
|
41
|
+
`nodejs.org` path as out of scope for either allowlist.
|
|
42
|
+
|
|
43
|
+
## The tier
|
|
44
|
+
|
|
45
|
+
Every domain here is **T1 by default** for its own tool -- owner-normative,
|
|
46
|
+
the same standing `typescript-guidance`'s T1 gives `typescriptlang.org` for
|
|
47
|
+
TypeScript itself. Most of these tools have exactly one canonical doc
|
|
48
|
+
source, unlike TypeScript's ecosystem of adjacent linters/checkers, so most
|
|
49
|
+
citations from this file carry `TIER: T1` in the findings format `research` mode defines (which `gaps`
|
|
50
|
+
mode reuses).
|
|
51
|
+
|
|
52
|
+
- `pnpm.io` -- pnpm's own CLI, workspace, and `.npmrc`/supply-chain-setting
|
|
53
|
+
reference.
|
|
54
|
+
- `knip.dev` -- unused-dependency/unused-export tooling.
|
|
55
|
+
- `vitest.dev` -- the default test runner this baseline ships. **Tier here
|
|
56
|
+
is T1**, for a different purpose than its T2 listing in
|
|
57
|
+
`typescript-sources.md`: that file's T2 covers auditing the config of a
|
|
58
|
+
test runner the interview has already selected (`research`/`refresh`);
|
|
59
|
+
this file's T1 covers recommending vitest be **added** to a project that
|
|
60
|
+
has no test runner configured at all yet (`gaps`). Once a runner is
|
|
61
|
+
selected and configured, further scrutiny of its config is
|
|
62
|
+
`research`/`refresh` territory at T2, not `gaps` mode's -- the same domain
|
|
63
|
+
carries two tier labels because the modes consult it for two different
|
|
64
|
+
purposes.
|
|
65
|
+
- `eslint.org` -- ESLint's own core rules and flat-config reference (as
|
|
66
|
+
opposed to `typescript-eslint.io`, which stays `research`/`refresh`'s
|
|
67
|
+
territory for typed-linting presets specifically).
|
|
68
|
+
- `prettier.io` -- formatting.
|
|
69
|
+
- `docs.npmjs.com` -- npm-the-registry conventions (`package.json` fields,
|
|
70
|
+
`engines`, publishing) as distinct from any one package manager's CLI.
|
|
71
|
+
- `nodejs.org/en/about/previous-releases` -- the LTS/EOL schedule, for the
|
|
72
|
+
Node-version-pinning area. See the path-scope note above.
|
|
73
|
+
|
|
74
|
+
**Explicitly out of scope**, named so an agent that finds one drops it
|
|
75
|
+
rather than substituting it for missing coverage:
|
|
76
|
+
|
|
77
|
+
- A package manager's or tool's community wiki, forum post, or blog
|
|
78
|
+
aggregator (as opposed to its own docs site).
|
|
79
|
+
- An individual author's blog post about a tool, however highly ranked.
|
|
80
|
+
- `github.com/tsconfig/bases` and similar community-consensus
|
|
81
|
+
repositories -- consensus, not an owner's own word.
|
|
82
|
+
|
|
83
|
+
## GitHub caveat
|
|
84
|
+
|
|
85
|
+
`allowed_domains` filters by domain, not path, so a bare `github.com`
|
|
86
|
+
allowance would let through any repo. Agents researching an area covered by
|
|
87
|
+
this file may include `github.com` and `raw.githubusercontent.com` in their
|
|
88
|
+
search domains, but must **only cite or fetch URLs under**:
|
|
89
|
+
|
|
90
|
+
- `changesets/changesets` (release automation)
|
|
91
|
+
- `typescript-eslint/typescript-eslint` (only for the release-compatibility
|
|
92
|
+
question -- "does this typescript-eslint version support this TypeScript
|
|
93
|
+
version" -- the rule semantics themselves stay `typescript-guidance`'s
|
|
94
|
+
T2 territory via `typescript-eslint.io`)
|
|
95
|
+
- `nodejs/Release` (the machine-readable Node release schedule, cross-checked
|
|
96
|
+
against `nodejs.org/en/about/previous-releases`)
|
|
97
|
+
|
|
98
|
+
Drop any other GitHub result, however highly ranked, the same as
|
|
99
|
+
`typescript-guidance`'s own caveat requires.
|
|
100
|
+
|
|
101
|
+
## Coverage discipline
|
|
102
|
+
|
|
103
|
+
Reject any non-allowlisted domain outright and say so in the report, rather
|
|
104
|
+
than substituting a community blog, an individual author's material, or a
|
|
105
|
+
Stack Overflow answer for missing coverage. A facet that turns up no
|
|
106
|
+
qualifying source is itself a reportable coverage gap, not a reason to lower
|
|
107
|
+
the bar -- see `SKILL.md`'s Gaps mode, step 2.
|
|
108
|
+
|
|
109
|
+
## Current-date anchor
|
|
110
|
+
|
|
111
|
+
Every research brief must state today's date explicitly, the same discipline
|
|
112
|
+
`typescript-guidance` applies -- a `retrieved <date>` stamp otherwise depends
|
|
113
|
+
on the spoke inferring the date itself, which is unreliable.
|
|
@@ -31,7 +31,7 @@ reviewer who wasn't in the room.
|
|
|
31
31
|
```bash
|
|
32
32
|
git diff --staged # the files about to be committed
|
|
33
33
|
git diff # unstaged context (reference only)
|
|
34
|
-
git log main
|
|
34
|
+
git log main..HEAD --oneline # commits already on this branch
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
Read all three outputs before drafting anything. The staged diff is the
|
|
@@ -62,7 +62,7 @@ Rules enforced by commitlint:
|
|
|
62
62
|
|
|
63
63
|
- **Imperative present tense** — "implement", "add", "fix", not "implemented"
|
|
64
64
|
- **All lowercase** after `type:` — never `Feat:` or `feat: Add`
|
|
65
|
-
- **≤ 70 characters** (
|
|
65
|
+
- **≤ 70 characters** (this skill's own target; commitlint's `config-conventional` only rejects headers over 100)
|
|
66
66
|
- **No trailing period**
|
|
67
67
|
- **Be specific** — name the module, file, class, or exported symbol
|
|
68
68
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
|
|
3
|
+
updates:
|
|
4
|
+
# Keeps the action majors in .github/workflows/ from going stale. Every
|
|
5
|
+
# `uses:` line is pinned by commit SHA (not a floating tag), so Dependabot
|
|
6
|
+
# opening a PR to move the pin forward is what keeps that pinning
|
|
7
|
+
# affordable to maintain -- the same mechanism it would use for a floating
|
|
8
|
+
# tag, closing the "a compromised upstream tag" gap a floating `@vN`
|
|
9
|
+
# doesn't. npm updates are deliberately not enabled here -- add them later
|
|
10
|
+
# with `groups:` batching if the project wants it.
|
|
11
|
+
- package-ecosystem: "github-actions"
|
|
12
|
+
directory: "/"
|
|
13
|
+
schedule:
|
|
14
|
+
interval: "weekly"
|
|
15
|
+
commit-message:
|
|
16
|
+
prefix: "ci"
|
|
17
|
+
labels:
|
|
18
|
+
- "dependencies"
|
|
@@ -24,11 +24,11 @@ jobs:
|
|
|
24
24
|
runs-on: ubuntu-latest
|
|
25
25
|
timeout-minutes: 10
|
|
26
26
|
steps:
|
|
27
|
-
- uses: actions/checkout@
|
|
27
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
28
28
|
with:
|
|
29
29
|
persist-credentials: false
|
|
30
|
-
- uses: pnpm/action-setup@
|
|
31
|
-
- uses: actions/setup-node@v7
|
|
30
|
+
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
31
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
|
32
32
|
with:
|
|
33
33
|
node-version-file: .node-version
|
|
34
34
|
cache: pnpm
|
|
@@ -40,11 +40,11 @@ jobs:
|
|
|
40
40
|
runs-on: ubuntu-latest
|
|
41
41
|
timeout-minutes: 10
|
|
42
42
|
steps:
|
|
43
|
-
- uses: actions/checkout@
|
|
43
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
44
44
|
with:
|
|
45
45
|
persist-credentials: false
|
|
46
|
-
- uses: pnpm/action-setup@
|
|
47
|
-
- uses: actions/setup-node@v7
|
|
46
|
+
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
47
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
|
48
48
|
with:
|
|
49
49
|
node-version-file: .node-version
|
|
50
50
|
cache: pnpm
|
|
@@ -56,11 +56,11 @@ jobs:
|
|
|
56
56
|
runs-on: ubuntu-latest
|
|
57
57
|
timeout-minutes: 10
|
|
58
58
|
steps:
|
|
59
|
-
- uses: actions/checkout@
|
|
59
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
60
60
|
with:
|
|
61
61
|
persist-credentials: false
|
|
62
|
-
- uses: pnpm/action-setup@
|
|
63
|
-
- uses: actions/setup-node@v7
|
|
62
|
+
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
63
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
|
64
64
|
with:
|
|
65
65
|
node-version-file: .node-version
|
|
66
66
|
cache: pnpm
|
|
@@ -72,11 +72,11 @@ jobs:
|
|
|
72
72
|
runs-on: ubuntu-latest
|
|
73
73
|
timeout-minutes: 10
|
|
74
74
|
steps:
|
|
75
|
-
- uses: actions/checkout@
|
|
75
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
76
76
|
with:
|
|
77
77
|
persist-credentials: false
|
|
78
|
-
- uses: pnpm/action-setup@
|
|
79
|
-
- uses: actions/setup-node@v7
|
|
78
|
+
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
79
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
|
80
80
|
with:
|
|
81
81
|
node-version-file: .node-version
|
|
82
82
|
cache: pnpm
|
|
@@ -88,11 +88,11 @@ jobs:
|
|
|
88
88
|
runs-on: ubuntu-latest
|
|
89
89
|
timeout-minutes: 15
|
|
90
90
|
steps:
|
|
91
|
-
- uses: actions/checkout@
|
|
91
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
92
92
|
with:
|
|
93
93
|
persist-credentials: false
|
|
94
|
-
- uses: pnpm/action-setup@
|
|
95
|
-
- uses: actions/setup-node@v7
|
|
94
|
+
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
95
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
|
96
96
|
with:
|
|
97
97
|
node-version-file: .node-version
|
|
98
98
|
cache: pnpm
|
|
@@ -17,10 +17,10 @@ jobs:
|
|
|
17
17
|
runs-on: ubuntu-latest
|
|
18
18
|
timeout-minutes: 10
|
|
19
19
|
steps:
|
|
20
|
-
- uses: actions/checkout@
|
|
20
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
21
21
|
with:
|
|
22
22
|
persist-credentials: false
|
|
23
|
-
- uses: actions/dependency-review-action@
|
|
23
|
+
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5
|
|
24
24
|
with:
|
|
25
25
|
fail-on-severity: high
|
|
26
26
|
allow-licenses: MIT, MIT-0, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, 0BSD, CC0-1.0, Unlicense, CC-BY-4.0
|
|
@@ -10,6 +10,12 @@ on:
|
|
|
10
10
|
permissions:
|
|
11
11
|
contents: read
|
|
12
12
|
|
|
13
|
+
# A manual dispatch overlapping the daily run would otherwise race to open
|
|
14
|
+
# the same failure issue.
|
|
15
|
+
concurrency:
|
|
16
|
+
group: security-audit
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
|
|
13
19
|
jobs:
|
|
14
20
|
audit:
|
|
15
21
|
name: Dependency audit
|
|
@@ -21,11 +27,11 @@ jobs:
|
|
|
21
27
|
contents: read
|
|
22
28
|
issues: write
|
|
23
29
|
steps:
|
|
24
|
-
- uses: actions/checkout@
|
|
30
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
25
31
|
with:
|
|
26
32
|
persist-credentials: false
|
|
27
|
-
- uses: pnpm/action-setup@
|
|
28
|
-
- uses: actions/setup-node@v7
|
|
33
|
+
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
34
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
|
29
35
|
with:
|
|
30
36
|
node-version-file: .node-version
|
|
31
37
|
cache: pnpm
|
|
@@ -34,7 +40,7 @@ jobs:
|
|
|
34
40
|
run: pnpm audit --audit-level=high
|
|
35
41
|
- name: Open an issue on failure
|
|
36
42
|
if: failure()
|
|
37
|
-
uses: actions/github-script@v8
|
|
43
|
+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
|
|
38
44
|
with:
|
|
39
45
|
script: |
|
|
40
46
|
const title = "Scheduled security audit failed";
|
|
@@ -3,3 +3,7 @@ dist/
|
|
|
3
3
|
coverage/
|
|
4
4
|
pnpm-lock.yaml
|
|
5
5
|
CHANGELOG.md
|
|
6
|
+
# A worktree the harness creates (see .gitignore) is a full, independent
|
|
7
|
+
# checkout under here -- without this, prettier double-visits (and can fail
|
|
8
|
+
# on) that copy's own in-progress state, which is a different session's WIP.
|
|
9
|
+
.claude/worktrees/
|
package/templates/core/CLAUDE.md
CHANGED
|
@@ -29,7 +29,7 @@ Run any task with `pnpm <script>`.
|
|
|
29
29
|
| `pnpm knip` | Unused-dependency / unused-export hygiene; a `verify` step. `knip.json` ignores `@commitlint/config-conventional` and `@commitlint/types`, which are loaded by a string and a JSDoc type knip cannot see |
|
|
30
30
|
| `pnpm check:exports` | publint + are-the-types-wrong against a packed tarball |
|
|
31
31
|
| `pnpm check:node-version` | `.node-version` is authoritative; forbids a hardcoded pin in CI |
|
|
32
|
-
| `pnpm verify` | Every gate above, in
|
|
32
|
+
| `pnpm verify` | Every gate above plus the `harness`/`toolchain` graders, in `verify-steps.mjs` order; CI runs them as five parallel group lanes |
|
|
33
33
|
| `pnpm prepare` | Installs the lefthook git hooks |
|
|
34
34
|
|
|
35
35
|
Run `pnpm verify` before considering any task done — it reproduces CI
|
|
@@ -71,6 +71,53 @@ contract:
|
|
|
71
71
|
Must-fix findings route back to `code-implementer`, and the loop repeats
|
|
72
72
|
until clean.
|
|
73
73
|
|
|
74
|
+
**The guard also screens `Bash`, but only conservatively.** The same hook
|
|
75
|
+
runs on every `Bash` call and blocks a command that visibly writes into
|
|
76
|
+
`src/` or `tests/` (redirects, `tee`, `sed -i`, `cp`/`mv` into them, a
|
|
77
|
+
`python`/`node`/`php` snippet that writes or deletes there, a copy, move or
|
|
78
|
+
removal of a parent of `src/` such as `rsync -a /tmp/x/ ./` or `rm -rf .`, and
|
|
79
|
+
similar) unless the caller is `test-author` or `code-implementer`. It cannot
|
|
80
|
+
catch an indirect write -- an interpreter running a script from a project
|
|
81
|
+
file, an `eval`, a computed path, a parent of the project root (`rm -rf ..`), a workspace container below the project root (`tools/packages/foo`), a build step, a formatter or fixer
|
|
82
|
+
(`prettier --write`, `eslint --fix`), `git rm`/`git mv`, `find -exec`, `xargs` with a computed operand, `tar`/`curl -o`, a very long
|
|
83
|
+
interpreter call (allowed with a stderr note) -- so hub-and-spoke remains a convention backed by a guard that raises the bar,
|
|
84
|
+
not a proof. To override it deliberately, run the command yourself with the
|
|
85
|
+
`!` prefix at the Claude Code prompt, or edit the hook's registration in
|
|
86
|
+
`.claude/settings.json`.
|
|
87
|
+
|
|
88
|
+
**A Claude Code Enterprise/managed deployment sits above this and can
|
|
89
|
+
silently disable it.** Managed settings (a `managed-settings.json` file, an
|
|
90
|
+
MDM policy, or a claude.ai-console-managed remote policy) take precedence
|
|
91
|
+
over every file this baseline installs, with no project-level override, and
|
|
92
|
+
two managed-only keys -- `allowManagedHooksOnly` and
|
|
93
|
+
`allowManagedPermissionRulesOnly` -- make Claude Code skip this project's
|
|
94
|
+
own `.claude/settings.json` hooks and permission rules entirely rather than
|
|
95
|
+
merge with them (see
|
|
96
|
+
[Claude Code's managed-settings docs](https://code.claude.com/docs/en/managed-settings)).
|
|
97
|
+
Nothing in this project can detect or gate against that from inside the
|
|
98
|
+
repo -- the managed file lives outside any working tree, at an OS-level
|
|
99
|
+
path. Run `/status` on a machine you don't control before trusting
|
|
100
|
+
`guard-hub-src-writes.mjs`/`guard-branch-isolation.mjs`: its "Setting
|
|
101
|
+
sources" line names every active source, and if these hooks aren't among
|
|
102
|
+
what's actually running, treat hub-and-spoke as an unenforced checklist
|
|
103
|
+
until confirmed otherwise.
|
|
104
|
+
|
|
105
|
+
**An installed Claude Code mod is a second silent override, below managed
|
|
106
|
+
settings.** Per the
|
|
107
|
+
[hooks guide](https://code.claude.com/docs/en/hooks-guide), a mod that
|
|
108
|
+
handles `tool.check` "can approve a call that your `PreToolUse` hook blocked,
|
|
109
|
+
unless the hook is in managed settings", and project `PreToolUse` hooks run
|
|
110
|
+
only after the last mod calls `next` (see the
|
|
111
|
+
[mods events reference](https://code.claude.com/docs/en/plugins/mods/events)).
|
|
112
|
+
Only managed-settings hooks outrank a mod, and nothing in the repo can detect
|
|
113
|
+
one. Check `/plugin` for installed mods alongside `/status`.
|
|
114
|
+
|
|
115
|
+
**The guard keys on `agent_id` as well as `agent_type`.** Claude Code sends
|
|
116
|
+
`agent_type` both inside a subagent and in a main session started with
|
|
117
|
+
`--agent <name>`; only a call inside a subagent also carries `agent_id`. A
|
|
118
|
+
call counts as a writer spoke only with both present, so a hub launched as
|
|
119
|
+
`claude --agent code-implementer` is still the hub and is blocked.
|
|
120
|
+
|
|
74
121
|
Full dispatch-sizing and recovery guidance: `.claude/rules/agent-dispatch.md`
|
|
75
122
|
(auto-loads when editing `.claude/skills/**` or `.claude/agents/**`).
|
|
76
123
|
|
|
@@ -111,7 +158,9 @@ fix the config it points at.
|
|
|
111
158
|
**Enforced at write time by hooks:** `any` implied by CommonJS constructs
|
|
112
159
|
(`require`, `module.exports`, `__dirname`, `__filename`), a missing `.js`
|
|
113
160
|
extension on a relative import, a hand-edit to `dist/` or `coverage/`, a
|
|
114
|
-
write to `src/`/`tests/` while on `main`, a real secret written to disk
|
|
161
|
+
write to `src/`/`tests/` while on `main`, a real secret written to disk,
|
|
162
|
+
an unsigned `git push` when `commit.gpgsign` is on, and a `run_in_background`
|
|
163
|
+
Bash call stacked with a shell-level detach construct.
|
|
115
164
|
|
|
116
165
|
**No automated guard — need conscious care:** no `any` in the public API;
|
|
117
166
|
never swallow an error silently; no top-level side effects; never
|
|
@@ -122,6 +171,7 @@ never swallow an error silently; no top-level side effects; never
|
|
|
122
171
|
This baseline is frozen at the moment `m3l-groundwork` last emitted it. Run
|
|
123
172
|
`/customize`'s guidance pass — or `.claude/skills/typescript-guidance/` /
|
|
124
173
|
`.claude/skills/harness-guidance/` directly in refresh mode — periodically
|
|
125
|
-
to sweep the toolchain and harness against current upstream guidance
|
|
174
|
+
to sweep the toolchain and harness against current upstream guidance; its
|
|
175
|
+
`gaps` mode recommends tooling the project doesn't have yet. See
|
|
126
176
|
`docs/research/typescript-refresh.md` and `docs/research/harness-refresh.md`
|
|
127
177
|
for the living trackers.
|
package/templates/core/README.md
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
Bootstrapped by [m3l-groundwork](https://github.com/monte3l/m3l-groundwork) —
|
|
4
4
|
a deterministic TypeScript + Claude Code project bootstrapper.
|
|
5
5
|
|
|
6
|
+
## What you just got
|
|
7
|
+
|
|
8
|
+
A TypeScript project wired up with a strict compiler configuration, ESLint,
|
|
9
|
+
Prettier, Vitest (with a coverage gate), and a Claude Code harness under
|
|
10
|
+
`.claude/` — agents, skills, hooks, and rules that shape how Claude Code
|
|
11
|
+
works in this repository. All of it is deliberately generic: a correct,
|
|
12
|
+
working starting point for any TypeScript project, not yet specific to what
|
|
13
|
+
__PROJECT_NAME__ actually does.
|
|
14
|
+
|
|
6
15
|
## Getting started
|
|
7
16
|
|
|
8
17
|
```bash
|
|
@@ -10,15 +19,26 @@ pnpm install
|
|
|
10
19
|
pnpm verify
|
|
11
20
|
```
|
|
12
21
|
|
|
13
|
-
`pnpm verify` runs the same checks CI runs
|
|
14
|
-
and test with coverage
|
|
15
|
-
the
|
|
22
|
+
`pnpm verify` runs the same checks CI runs — format, lint, typecheck, build,
|
|
23
|
+
and test with coverage — in one command, so you can catch a failure locally
|
|
24
|
+
before pushing. See `CLAUDE.md` for the full command reference and this
|
|
25
|
+
project's conventions.
|
|
26
|
+
|
|
27
|
+
## Tailor it to your project
|
|
28
|
+
|
|
29
|
+
This baseline is frozen at the moment it was generated, and deliberately
|
|
30
|
+
generic until you adapt it. To tailor it to __PROJECT_NAME__:
|
|
31
|
+
|
|
32
|
+
1. Open this repository in [Claude Code](https://claude.com/claude-code).
|
|
33
|
+
2. Run the `/customize` slash command.
|
|
34
|
+
3. Answer a short interview (project kind, runtime target, test strictness,
|
|
35
|
+
CI depth). Claude Code then tailors the baseline to your answers and
|
|
36
|
+
runs a live guidance pass against current official TypeScript and
|
|
37
|
+
Anthropic documentation, so the result reflects up-to-date recommended
|
|
38
|
+
practice rather than what was true when this baseline was generated.
|
|
16
39
|
|
|
17
|
-
##
|
|
40
|
+
## Glossary
|
|
18
41
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
let the guidance pass validate the result against current official
|
|
23
|
-
TypeScript and Anthropic guidance rather than what was true when the
|
|
24
|
-
baseline was built.
|
|
42
|
+
Run into an unfamiliar term in `CLAUDE.md`, this README, or the `.claude/`
|
|
43
|
+
harness? See the upstream
|
|
44
|
+
[glossary](https://github.com/monte3l/m3l-groundwork/blob/main/docs/glossary.md).
|
|
@@ -14,6 +14,23 @@ coverage/
|
|
|
14
14
|
# Local overrides
|
|
15
15
|
lefthook-local.yml
|
|
16
16
|
|
|
17
|
+
# A worktree the harness creates (`claude --worktree`, Agent tool
|
|
18
|
+
# `isolation: "worktree"`, or `EnterWorktree`) lands under here as a full,
|
|
19
|
+
# independent checkout -- including its own copy of every file this project
|
|
20
|
+
# already scans. Without this, prettier/eslint/vitest all double-visit (and
|
|
21
|
+
# can fail on) that copy's own in-progress state, which belongs to a
|
|
22
|
+
# different session, not this project's tracked content.
|
|
23
|
+
.claude/worktrees/
|
|
24
|
+
|
|
25
|
+
# Never commit secrets. (Also relevant to worktrees: a project that adds a
|
|
26
|
+
# `.worktreeinclude` file -- gitignore-syntax, Claude Code convention, see
|
|
27
|
+
# code.claude.com/docs/en/worktrees -- can only carry a gitignored file like
|
|
28
|
+
# this into a new worktree, never a tracked one, so it stays gitignored
|
|
29
|
+
# regardless of whether that file exists here.)
|
|
30
|
+
.env
|
|
31
|
+
.env.local
|
|
32
|
+
.env.*.local
|
|
33
|
+
|
|
17
34
|
# Scratch state written by opt-in harness-extras pack hooks (e.g. the
|
|
18
35
|
# compaction-handoff artifact) -- harmless if the pack isn't installed.
|
|
19
36
|
tmp/
|
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Real packaging correctness: packs the target package (`--cwd <dir>`,
|
|
4
4
|
* default the repo root) with `pnpm pack`, then runs publint and
|
|
5
|
-
* are-the-types-wrong (attw) against the resulting tarball
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* are-the-types-wrong (attw) against the resulting tarball -- checking the
|
|
6
|
+
* actual published artifact, not just the source tree. publint checks that
|
|
7
|
+
* `package.json` (its `exports` map, `main`/`module`/`types` fields, and
|
|
8
|
+
* which files are actually included) resolves the way consumers and
|
|
9
|
+
* bundlers expect. attw checks that the package's TypeScript type
|
|
10
|
+
* declarations actually match what each entry point resolves to at runtime
|
|
11
|
+
* -- e.g. that an ESM import doesn't quietly get pointed at CommonJS-shaped
|
|
12
|
+
* types. Skips cleanly (exit 0, one warning) when the target has no
|
|
13
|
+
* `exports` field -- a project that isn't published doesn't need this gate,
|
|
14
|
+
* and `/customize` removes the step entirely for non-library project kinds
|
|
15
|
+
* rather than leaving a permanently-skipped one behind.
|
|
10
16
|
*/
|
|
11
17
|
import process from "node:process";
|
|
12
18
|
import { execFileSync } from "node:child_process";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The writer-spoke roster: the only subagent names a PreToolUse[Write|Edit]
|
|
2
|
+
* The writer-spoke roster: the only subagent names a PreToolUse[Write|Edit|Bash]
|
|
3
3
|
* hook trusts to write into a guarded `src/`/`tests/` path. Kept as one
|
|
4
4
|
* small, static source so `guard-hub-src-writes.mjs` and this project's
|
|
5
5
|
* `code-implementer`/`test-author` agent definitions can't silently drift
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
* list scalars. Not supported: nested mappings (recorded as an empty string
|
|
6
6
|
* rather than misparsed), anchors, tags. Every string result is trimmed.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Also used by m3l-groundwork's own adopt mode (the tool that generated this
|
|
9
|
+
* project's harness); if you're contributing a change back upstream, keep
|
|
10
|
+
* this file's behavior in sync with its source at
|
|
11
|
+
* `packages/cli/src/harness/frontmatter.ts` there.
|
|
10
12
|
*/
|
|
11
13
|
|
|
12
14
|
const KEY_LINE = /^([A-Za-z_][\w-]*):(?:[ \t]+(.*))?$/;
|