@skyf0xx/hedgehog-core-full-stack-app 1.0.12 → 1.0.14

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.
@@ -32,9 +32,9 @@ build exactly what its ALLOWED SCOPE names, one layer at a time, gated by
32
32
  - **PostgreSQL** via Docker Compose — never a natively-installed Postgres.
33
33
 
34
34
  Use `nx-run-tasks` (build/lint/test/typecheck), `nx-workspace` (inspecting
35
- project/target config), `nx-generate` (scaffolding a new library/app), and
36
- `link-workspace-packages` (wiring a new package into a consumer) as
37
- needed.
35
+ project/target config), `nx-generate` (running the packet's
36
+ `tools/generators:<layer>` command), and `link-workspace-packages`
37
+ (wiring a new package into a consumer) as needed.
38
38
 
39
39
  **Every layer you own starts from its generator in `tools/generators/`** —
40
40
  one per layer (`schema`, `contract`, `repository`, `service`,
@@ -30,9 +30,9 @@ before the next starts.
30
30
  routes directly.
31
31
 
32
32
  Use `nx-run-tasks` (build/lint/test/typecheck), `nx-workspace` (inspecting
33
- project/target config), `nx-generate` (scaffolding a new library/app), and
34
- `link-workspace-packages` (wiring a new package into a consumer) as
35
- needed.
33
+ project/target config), `nx-generate` (running the packet's
34
+ `tools/generators:<layer>` command), and `link-workspace-packages`
35
+ (wiring a new package into a consumer) as needed.
36
36
 
37
37
  **Both layers you own start from their generator in `tools/generators/`** —
38
38
  `hook` lands `packages/hooks`'s shell, `nx.tags`, the query hook set, and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyf0xx/hedgehog-core-full-stack-app",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "Hedgehog's full-stack-app core: an Nx/pnpm/NestJS/Next.js workspace, backend-first domain module build discipline, and the agents and skills that drive it.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -163,9 +163,14 @@ write — same treatment as an out-of-scope `apps/mobile`.
163
163
 
164
164
  ```bash
165
165
  npx nx g @nx/js:lib packages/auth --bundler=none --unitTestRunner=vitest
166
- pnpm add better-auth @thallesp/nestjs-better-auth
167
166
  ```
168
167
 
168
+ `better-auth` and `@thallesp/nestjs-better-auth` are already declared in
169
+ root `package.json` and resolved by `pnpm-lock.yaml` — the core ships
170
+ them, so there is nothing to install here. Don't run `pnpm add` for
171
+ either: an add resolves against npm at whatever is latest today, which
172
+ is the drift this core pins them to avoid.
173
+
169
174
  Configure the Drizzle adapter against `packages/db`. Add
170
175
  `BETTER_AUTH_SECRET: z.string().min(32)` to `packages/config/env.schema.ts`
171
176
  now (it doesn't exist in the core schema `hedgehog-bootstrap-full-stack-app-core`
@@ -175,9 +180,10 @@ line reproduces the exact `loadEnv()` crash-on-boot that
175
180
  `hedgehog-bootstrap-full-stack-app-core`'s `DATABASE_URL` entry exists to prevent, just
176
181
  for this var instead. Tag: `scope:auth`, `type:adapter`.
177
182
 
178
- Also wire the global auth guard on `apps/api`: `pnpm add
179
- @thallesp/nestjs-better-auth` there too and register the guard
180
- (secure-by-default) against `packages/auth`. `apps/api`'s
183
+ Also wire the global auth guard on `apps/api`: register the guard
184
+ (secure-by-default) against `packages/auth` the root declaration
185
+ already resolves `@thallesp/nestjs-better-auth` for every project in the
186
+ workspace, so `apps/api` needs no add of its own. `apps/api`'s
181
187
  `depConstraints` entry needs `scope:auth` added to its allowed
182
188
  dependencies now — the one deliberate exception to "api reaches things
183
189
  only through ports," since auth is cross-cutting infra, not a domain
@@ -195,9 +201,12 @@ skipped, say so plainly and move on — same treatment as an out-of-scope
195
201
 
196
202
  ```bash
197
203
  npx nx g @nx/node:app apps/worker
198
- pnpm add bullmq ioredis
199
204
  ```
200
205
 
206
+ `bullmq` and `ioredis` are already declared in root `package.json` and
207
+ resolved by `pnpm-lock.yaml` — same as Auth's packages above. Nothing to
208
+ install here; don't run `pnpm add` for either.
209
+
201
210
  Add a `redis` service to the root `docker-compose.yml` that
202
211
  `hedgehog-bootstrap-full-stack-app-core` landed (Postgres-only) and
203
212
  `REDIS_URL: z.string().url()` to `packages/config/env.schema.ts` (it
@@ -235,12 +244,49 @@ Skip this step entirely if Mobile isn't on for this project (check
235
244
  say so plainly and move on — same pattern as Auth (step 1) and Queue
236
245
  (step 2) when their add-on is off.
237
246
 
247
+ Mobile's packages are pinned in `addon-versions.json` at the workspace
248
+ root, not named inline here and not declared in root `package.json` —
249
+ Expo pulls a native build matrix that has no business in a project that
250
+ never scaffolds `apps/mobile`. Read every version from that file rather
251
+ than typing one, so this step installs what the core was last gated
252
+ against:
253
+
238
254
  ```bash
255
+ NX_EXPO=$(node -p "require('./addon-versions.json').mobile['@nx/expo']")
256
+ NATIVEWIND=$(node -p "require('./addon-versions.json').mobile.nativewind")
257
+ RNR=$(node -p "require('./addon-versions.json').mobile['@react-native-reusables/cli']")
258
+
259
+ pnpm add -w -D "@nx/expo@$NX_EXPO"
260
+ pnpm add -w "nativewind@$NATIVEWIND"
261
+
239
262
  npx nx g @nx/expo:app apps/mobile --unitTestRunner=jest
240
- npx @react-native-reusables/cli@latest init
241
- npx @react-native-reusables/cli@latest add button text
263
+
264
+ npx "@react-native-reusables/cli@$RNR" init
265
+ npx "@react-native-reusables/cli@$RNR" add button text
242
266
  ```
243
267
 
268
+ `-w` is required: this is a pnpm workspace, and an add without it fails
269
+ with `ERR_PNPM_ADDING_TO_ROOT` rather than installing.
270
+
271
+ `@nx/expo:app` generates `apps/mobile/src/test-setup.ts` with an untyped
272
+ `defineGlobal` helper, which is a `TS7006` error under the core's
273
+ `strict: true` base tsconfig — `mobile:typecheck` fails on a fresh
274
+ scaffold until it is annotated:
275
+
276
+ ```ts
277
+ const defineGlobal = (name: string, value: unknown) => {
278
+ ```
279
+
280
+ Make that edit before the step's commit. `nx-migrate.yml`'s add-on gate
281
+ applies the same annotation, so the day `@nx/expo` ships the types both
282
+ stop being needed together.
283
+
284
+ `@nx/expo`'s pin is byte-identical to every other `@nx/*` entry in root
285
+ `package.json` — Nx requires its plugin matrix to be version-identical,
286
+ and a mismatch fails at generator time with a resolution error rather
287
+ than at install. If the pin and the `@nx/*` entries have drifted apart,
288
+ stop and fix `addon-versions.json` rather than installing anyway.
289
+
244
290
  `@nx/expo:app`'s own default for `--unitTestRunner` is `none` — pass it
245
291
  explicitly, or `apps/mobile` has no `test` target at all and the `screen`
246
292
  layer's verify command below fails on a missing target rather than a
@@ -253,7 +299,7 @@ NativeWind and the `@/*` path alias into `apps/mobile/tsconfig.json`
253
299
  named components' source into `apps/mobile/src/components/ui/`. `button`
254
300
  and `text` are the two the `screen` generator's mobile output imports —
255
301
  add any further components `front-end-eng` needs the same way, per
256
- module, as it builds.
302
+ module, as it builds, at the same pinned CLI version.
257
303
 
258
304
  Edit `init`'s generated theme (`tailwind.config.js` colors, light/dark)
259
305
  to match `apps/web`'s base theme (landed by
@@ -355,6 +401,19 @@ time via `hedgehog next`/`hedgehog verify`, each its own commit.
355
401
  (written by `planner` at planning intake) turns that add-on on — say so
356
402
  plainly and skip otherwise, don't leave it ambiguous whether the step
357
403
  was considered.
404
+ - A skipped Auth or Queue step leaves that add-on's packages declared but
405
+ unused, since the core ships them in root `package.json`. Delete the
406
+ skipped add-on's entries (`better-auth` and
407
+ `@thallesp/nestjs-better-auth` for Auth; `bullmq` and `ioredis` for
408
+ Queue) and re-run `pnpm install` so the lockfile drops them. Do this in
409
+ the same commit that records the skip. Mobile needs nothing — its
410
+ packages were never in the install to begin with.
411
+ - Never write a version number into a command in this file. Auth and
412
+ Queue versions come from root `package.json`; Mobile's come from
413
+ `addon-versions.json`. A version typed into a step is invisible to
414
+ `nx migrate`, to `pnpm outdated`, and to CI's add-on gate, so it drifts
415
+ silently in whichever direction the day's npm resolution happens to
416
+ take it.
358
417
  - Don't add domain schema, contracts, or any `libs/<module>/*` content —
359
418
  that's Phase A, started after Bootstrap, one module at a time.
360
419
  - Don't deviate from the package/library choices above, for whichever
@@ -1,33 +1,38 @@
1
1
  ---
2
2
  name: link-workspace-packages
3
- description: 'Link workspace packages in the Hedgehog pnpm monorepo. USE WHEN: (1) you just created or generated new packages and need to wire up their dependencies, (2) code imports from a sibling package and needs it added as a dependency, (3) you get resolution errors for workspace packages (@org/*) like "cannot find module", "failed to resolve import", "TS2307", or "cannot resolve". DO NOT patch around with tsconfig paths or manual package.json edits - use pnpm''s workspace commands to fix actual linking.'
3
+ description: 'Link workspace packages in the Hedgehog pnpm monorepo. USE WHEN: (1) you just created or generated new packages and need to wire up their dependencies, (2) code imports from a sibling package and needs it added as a dependency, (3) you get resolution errors for workspace packages like "cannot find module", "failed to resolve import", "TS2307", or "cannot resolve". DO NOT patch around with tsconfig paths or manual package.json edits - use pnpm''s workspace commands to fix actual linking.'
4
4
  ---
5
5
 
6
6
  # Link Workspace Packages
7
7
 
8
+ Adapted from Nx's stock workspace-linking skill for this core's own
9
+ package names — plain, unscoped (`db`, `contracts`, `hooks`, `config`,
10
+ plus each module's `libs/<module>/repository` and
11
+ `libs/<module>/service`), not `@org/*`-scoped.
12
+
8
13
  Add dependencies between packages in the workspace using pnpm's `workspace:` protocol — symlinks are only created when a dependency is explicitly declared this way.
9
14
 
10
15
  ## Workflow
11
16
 
12
- 1. Identify consumer package (the one importing)
13
- 2. Identify provider package(s) (being imported)
17
+ 1. Identify consumer package (the one importing) — e.g. `apps/api`
18
+ 2. Identify provider package(s) (being imported) — e.g. a module's `libs/<module>/service`
14
19
  3. Add the dependency:
15
20
 
16
21
  ```bash
17
22
  # From consumer directory
18
- pnpm add @org/ui --workspace
23
+ pnpm add <module>-service --workspace
19
24
 
20
25
  # Or with --filter from anywhere
21
- pnpm add @org/ui --filter @org/app --workspace
26
+ pnpm add <module>-service --filter api --workspace
22
27
  ```
23
28
 
24
29
  Result in `package.json`:
25
30
 
26
31
  ```json
27
- { "dependencies": { "@org/ui": "workspace:*" } }
32
+ { "dependencies": { "<module>-service": "workspace:*" } }
28
33
  ```
29
34
 
30
- 4. Verify the symlink was created in the consumer's `node_modules/@org/<package>`
35
+ 4. Verify the symlink was created in the consumer's `node_modules/<package>`
31
36
 
32
37
  ## Debugging "Cannot find module"
33
38
 
@@ -1,165 +1,73 @@
1
1
  ---
2
2
  name: nx-generate
3
- description: Generate code using nx generators. INVOKE IMMEDIATELY when user mentions scaffolding, setup, structure, creating apps/libs, or setting up project structure. Trigger words - scaffold, setup, create a new app, create a new lib, project structure, generate, add a new project. ALWAYS use this BEFORE calling nx_docs or exploring - this skill handles discovery internally.
4
- subagent: general-purpose
5
- context: fork
3
+ description: Run one of this core's own Nx generators to scaffold a domain-module layer. INVOKE when a claimed packet's LAYER SHAPE section names a `tools/generators:<layer>` command to run.
6
4
  ---
7
5
 
8
6
  # Run Nx Generator
9
7
 
10
- Nx generators are powerful tools that scaffold projects, make automated code migrations or automate repetitive tasks in a monorepo. They ensure consistency across the codebase and reduce boilerplate work.
11
-
12
- This skill applies when the user wants to:
13
-
14
- - Create new projects like libraries or applications
15
- - Scaffold features or boilerplate code
16
- - Run workspace-specific or custom generators
17
- - Do anything else that an nx generator exists for
18
-
19
- ## Key Principles
20
-
21
- 1. **Always use `--no-interactive`** - Prevents prompts that would hang execution
22
- 2. **Read the generator source code** - The schema alone is not enough; understand what the generator actually does
23
- 3. **Match existing repo patterns** - Study similar artifacts in the repo and follow their conventions
24
- 4. **Verify with lint/test/build/typecheck etc.** - Generated code must pass verification, using whatever targets are appropriate for this workspace (CI config is a good guide for which ones are critical).
8
+ Adapted from Nx's stock `nx-generate` skill for this core's closed set of
9
+ generators: `tools/generators/` holds exactly one generator per domain
10
+ module layer (`schema`, `contract`, `repository`, `service`, `controller`,
11
+ `hook`, `screen`), and every layer's task packet already names which one
12
+ to run and with what flags — there is no generator discovery or matching
13
+ step here. `hedgehog-loop`'s "Scaffolding a layer" section owns the full
14
+ flag contract; this skill covers only the mechanics of invoking one.
25
15
 
26
16
  ## Steps
27
17
 
28
- ### 1. Discover Available Generators
29
-
30
- Use the Nx CLI to discover available generators:
31
-
32
- - List all generators for a plugin: `pnpm nx list @nx/react`
33
- - View available plugins: `pnpm nx list`
34
-
35
- This includes plugin generators (e.g., `@nx/react:library`) and local workspace generators.
36
-
37
- ### 2. Match Generator to User Request
38
-
39
- Identify which generator(s) could fulfill the user's needs. Consider what artifact type they want, which framework is relevant, and any specific generator names mentioned.
40
-
41
- **IMPORTANT**: When both a local workspace generator and an external plugin generator could satisfy the request, **always prefer the local workspace generator**. Local generators are customized for the specific repo's patterns.
42
-
43
- If no suitable generator exists, you can stop using this skill. However, the burden of proof is high—carefully consider all available generators before deciding none apply.
44
-
45
- ### 3. Get Generator Options
46
-
47
- Use the `--help` flag to understand available options:
48
-
49
- ```bash
50
- pnpm nx g @nx/react:library --help
51
- ```
52
-
53
- Pay attention to required options, defaults that might need overriding, and options relevant to the user's request.
54
-
55
- ### Library Buildability
56
-
57
- **Default to non-buildable libraries** unless there's a specific reason for buildable.
58
-
59
- | Type | When to use | Generator flags |
60
- | --------------------------- | ----------------------------------------------------------------- | ----------------------------------- |
61
- | **Non-buildable** (default) | Internal monorepo libs consumed by apps | No `--bundler` flag |
62
- | **Buildable** | Publishing to npm, cross-repo sharing, stable libs for cache hits | `--bundler=vite` or `--bundler=swc` |
63
-
64
- Non-buildable libs:
65
-
66
- - Export `.ts`/`.tsx` source directly
67
- - Consumer's bundler compiles them
68
- - Faster dev experience, less config
18
+ ### 1. Run the packet's command
69
19
 
70
- Buildable libs:
71
-
72
- - Have their own build target
73
- - Useful for stable libs that rarely change (cache hits)
74
- - Required for npm publishing
75
-
76
- **If unclear, ask the user:** "Should this library be buildable (own build step, better caching) or non-buildable (source consumed directly, simpler setup)?"
77
-
78
- ### 4. Read Generator Source Code
79
-
80
- **This step is critical.** The schema alone does not tell you everything. Reading the source code helps you:
81
-
82
- - Know exactly what files will be created/modified and where
83
- - Understand side effects (updating configs, installing deps, etc.)
84
- - Identify behaviors and options not obvious from the schema
85
- - Understand how options interact with each other
86
-
87
- To find generator source code:
88
-
89
- - For plugin generators: Use `node -e "console.log(require.resolve('@nx/<plugin>/generators.json'));"` to find the generators.json, then locate the source from there
90
- - If that fails, read directly from `node_modules/<plugin>/generators.json`
91
- - For local generators: Typically in `tools/generators/` or a local plugin directory. Search the repo for the generator name.
92
-
93
- After reading the source, reconsider: Is this the right generator? If not, go back to step 2.
94
-
95
- > **⚠️ `--directory` flag behavior can be misleading.**
96
- > It should specify the full path of the generated library or component, not the parent path that it will be generated in.
97
- >
98
- > ```bash
99
- > # ✅ Correct - directory is the full path for the library
100
- > nx g @nx/react:library --directory=libs/my-lib
101
- > # generates libs/my-lib/package.json and more
102
- >
103
- > # ❌ Wrong - this will create files at libs and libs/src/...
104
- > nx g @nx/react:library --name=my-lib --directory=libs
105
- > # generates libs/package.json and more
106
- > ```
107
-
108
- ### 5. Examine Existing Patterns
109
-
110
- Before generating, examine the target area of the codebase:
111
-
112
- - Look at similar existing artifacts (other libraries, applications, etc.)
113
- - Identify naming conventions, file structures, and configuration patterns
114
- - Note which test runners, build tools, and linters are used
115
- - Configure the generator to match these patterns
116
-
117
- ### 6. Dry-Run to Verify File Placement
118
-
119
- **Always run with `--dry-run` first** to verify files will be created in the correct location:
20
+ The claimed packet's LAYER SHAPE section prints the exact command,
21
+ already filled in with `--module` and `--fields`. Run it as given:
120
22
 
121
23
  ```bash
122
- pnpm nx g @nx/react:library --name=my-lib --dry-run --no-interactive
24
+ nx g ./tools/generators:<layer> --module=<module> [--fields='<name:type,...>'] [--toggleField=<boolField>]
123
25
  ```
124
26
 
125
- Review the output carefully. If files would be created in the wrong location, adjust your options based on what you learned from the generator source code.
27
+ Always pass `--no-interactive` if the command is going to run
28
+ unattended and might otherwise prompt.
126
29
 
127
- Note: Some generators don't support dry-run (e.g., if they install npm packages). If dry-run fails for this reason, proceed to running the generator for real.
128
-
129
- ### 7. Run the Generator
130
-
131
- Execute the generator:
30
+ ### 2. Dry-run first when the placement is unfamiliar
132
31
 
133
32
  ```bash
134
- pnpm nx generate <generator-name> <options> --no-interactive
33
+ nx g ./tools/generators:<layer> --module=<module> --dry-run --no-interactive
135
34
  ```
136
35
 
137
- > **Tip:** New packages often need workspace dependencies wired up (e.g., importing shared types, being consumed by apps). The `link-workspace-packages` skill can help add these correctly.
36
+ Most of the time the generator's target paths are already well
37
+ understood (they're fixed by layer, per `hedgehog-loop`), so this step is
38
+ optional — reach for it when something about the module name or flags is
39
+ unusual enough to want to see the file list before it lands.
138
40
 
139
- ### 8. Modify Generated Code (If Needed)
41
+ ### 3. Read the generator source if a flag's effect is unclear
140
42
 
141
- Generators provide a starting point. Modify the output as needed to:
43
+ The generator's own source lives in `tools/generators/<layer>/generator.ts`
44
+ next to its `schema.json`. Read it before guessing at what a flag does —
45
+ the schema alone doesn't show side effects (barrel wiring, tag
46
+ assignment, module registration).
142
47
 
143
- - Add or modify functionality as requested
144
- - Adjust imports, exports, or configurations
145
- - Integrate with existing code patterns
48
+ ### 4. Author the entity-specific delta
146
49
 
147
- **Important:** If you replace or delete generated test files (e.g., `*.spec.ts`), either write meaningful replacement tests or remove the `test` target from the project configuration. Empty test suites will cause `nx test` to fail.
50
+ The generator lands the layer's skeleton package shell, `nx.tags`,
51
+ port-discipline file suffixes, barrel wiring, and (for `screen`)
52
+ placeholder sections. It does not write the module's field-specific
53
+ logic, business rules, or UX. Author that on top, per the packet's
54
+ INTENT and RELEVANT RULES.
148
55
 
149
- ### 9. Format and Verify
56
+ **Important:** if a generated test file needs replacing rather than
57
+ extending, write a meaningful replacement — an empty test suite fails
58
+ `nx test`.
150
59
 
151
- Format all generated/modified files:
60
+ ### 5. Wire the new package into the workspace
152
61
 
153
- ```bash
154
- pnpm nx format --fix
155
- ```
156
-
157
- This example is for built-in nx formatting with prettier. There might be other formatting tools for this workspace, use these when appropriate.
158
-
159
- Then verify the generated code works. Keep in mind that the changes you make with a generator or subsequent modifications might impact various projects so it's usually not enough to only run targets for the artifact you just created.
62
+ A layer that's the first arrival in its package needs
63
+ `pnpm install && pnpm nx sync` before verify can see it — see
64
+ `hedgehog-loop`'s "First arrival in a package" for which layers this
65
+ applies to and the override that widens scope for it. The
66
+ `link-workspace-packages` skill covers adding a dependency between two
67
+ existing packages.
160
68
 
161
- ```bash
162
- pnpm nx run-many -t build,lint,test,typecheck
163
- ```
69
+ ### 6. Verify
164
70
 
165
- If verification fails with manageable issues (a few lint errors, minor type issues), fix them. If issues are extensive, attempt obvious fixes first, then escalate to the user with details about what was generated, what's failing, and what you've attempted.
71
+ Run whatever the packet's VERIFICATION command specifies. `nx-run-tasks`
72
+ covers running build/lint/test/typecheck directly if you need to check
73
+ something the packet's own command doesn't cover.
@@ -3,6 +3,11 @@ name: nx-run-tasks
3
3
  description: Helps with running tasks in an Nx workspace. USE WHEN the user wants to execute build, test, lint, serve, or run any other tasks defined in the workspace.
4
4
  ---
5
5
 
6
+ Adapted from Nx's stock task-running skill for this workspace's own
7
+ targets (`build`, `lint`, `test`, `typecheck`, `serve`) and projects
8
+ (`api`, `web`, `mobile` when the Mobile add-on is on, plus each domain
9
+ module's `libs/<module>/*`).
10
+
6
11
  Run tasks via `pnpm nx` (see the `nx-workspace` skill for the pnpm-only convention and for checking which targets a project has before running one).
7
12
 
8
13
  For more details on any command, run it with `--help` (e.g. `pnpm nx run-many --help`, `pnpm nx affected --help`).
@@ -13,7 +18,7 @@ For more details on any command, run it with `--help` (e.g. `pnpm nx run-many --
13
18
  pnpm nx run <project>:<task>
14
19
  ```
15
20
 
16
- where `project` is the project name defined in `package.json` or `project.json` (if present).
21
+ where `project` is the project name defined in `package.json` or `project.json` (if present) — e.g. `pnpm nx run api:test`, `pnpm nx run web:build`.
17
22
 
18
23
  ## Run multiple tasks
19
24
 
@@ -25,9 +30,9 @@ You can pass a `-p` flag to filter to specific projects, otherwise it runs on al
25
30
 
26
31
  Examples:
27
32
 
28
- - `pnpm nx run-many -t test -p proj1 proj2` — test specific projects
29
- - `pnpm nx run-many -t test --projects=*-app --exclude=excluded-app` — test projects matching a pattern
30
- - `pnpm nx run-many -t test --projects=tag:api-*` — test projects by tag
33
+ - `pnpm nx run-many -t test -p api web` — test specific projects
34
+ - `pnpm nx run-many -t test --projects=*-e2e` — test projects matching a pattern
35
+ - `pnpm nx run-many -t test --projects=tag:type:service` — test projects by tag (see `hedgehog-loop`'s "Port discipline" for this core's tag scheme)
31
36
 
32
37
  ## Run tasks for affected projects
33
38