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

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 CHANGED
@@ -1,80 +1,57 @@
1
- # @skyf0xx/hedgehog-core-full-stack-app
1
+ # Hedgehog Full-Stack App Core ⭐
2
2
 
3
- Hedgehog's full-stack-app core: a pre-built, pre-verified Nx/pnpm
4
- workspace (NestJS + Drizzle + PostgreSQL on the backend, Next.js +
5
- ShadCN + Tailwind on the frontend, ts-rest contracts, TanStack Query
6
- hooks) plus the agents, skills, and manifest that drive a Hedgehog
7
- project built on it.
3
+ ### For: Well Architechted Full Stack Apps
8
4
 
9
- ## Contents
5
+ Every AI coding tool can scaffold an app. Most let the backend rot as it
6
+ grows: auth logic scattered across routes, contracts drifting from the
7
+ client, schema changes nobody tested.
10
8
 
11
- - `workspace/` the workspace a Hedgehog install copies to a
12
- project's repo root: Nx configuration, `packages/config`,
13
- `packages/db`, `apps/api`, `apps/web`, and every enforcement file
14
- (lefthook, commitlint, the CI phase gate).
15
- - `agents/` — `backend-eng`, `ux-planner`, `front-end-eng`.
16
- - `skills/` — `hedgehog-loop`, `hedgehog-bootstrap`,
17
- `hedgehog-bootstrap-full-stack-app-core`, and the Nx tooling skills
18
- (`nx-generate`, `nx-run-tasks`, `nx-workspace`,
19
- `link-workspace-packages`).
20
- - `vendor-skills/GSAP` — the vendored asset set `hedgehog-loop`'s
21
- build steps reference.
22
- - `CLAUDE.core.md` — fills a Hedgehog project's root `CLAUDE.md`
23
- `{{CORE_SECTION}}` placeholder for this core.
24
- - `hedgehog-core.yaml` — this package's manifest: name, flag, the
25
- selection prose the Hedgehog planner matches a project description
26
- against, and which agents/skills/vendor skills it carries.
27
- - `scripts/regenerate-full-stack-app-core.sh` — the deterministic
28
- generator that regenerates `workspace/` from scratch. Run by hand
29
- when a workspace dependency needs bumping; not part of any install
30
- path.
31
- - `repro/` — reproductions that drive `workspace/`'s real lefthook
32
- configuration and pinned lefthook binary against a real `git commit`,
33
- proving the commit gate runs on a fresh install and fails closed when
34
- its tooling is missing.
9
+ This core gives Hedgehog a backend that stays honest as it grows: one
10
+ opinionated stack, one enforced build order, and a phase gate that
11
+ blocks the next layer until the current one passes.
35
12
 
36
- ## Using this package
13
+ ```mermaid
14
+ flowchart LR
15
+ A[Schema] --> B[Contract]
16
+ B --> C[Repository]
17
+ C --> D[Service]
18
+ D --> E[Controller]
19
+ E --> F[Hook]
20
+ F --> G[Screen]
21
+ ```
37
22
 
38
- A Hedgehog installation depends on this package for the `full-stack-app`
39
- core rather than carrying its content directly. See the Hedgehog engine
40
- (`@skyf0xx/hedgehog`) for the installer and build-graph tooling that
41
- consumes it.
23
+ ## What you get
42
24
 
43
- ## Working on this core
25
+ - **NestJS + Drizzle + PostgreSQL** on the backend, **Next.js + ShadCN +
26
+ Tailwind** on the frontend, locked in once so every feature reuses the
27
+ same stack.
28
+ - **ts-rest contracts** so the client can't drift from the API: one
29
+ shared type definition feeds both sides.
30
+ - **TanStack Query hooks**, generated straight from the contracts.
31
+ - **A commit gate** (lefthook + commitlint) that blocks a broken build
32
+ from ever reaching your history.
44
33
 
45
- This is a versioned npm package that the Hedgehog engine's `init` fetches
46
- by name, carrying `full-stack-app`'s own agents, skills, a pre-built
47
- workspace, and the `hedgehog-core.yaml` manifest that names all three to
48
- the engine. See the engine repo
49
- ([`skyf0xx/hedgehog`](https://github.com/skyf0xx/hedgehog)) and its
50
- [`ARCHITECTURE.md`](https://github.com/skyf0xx/hedgehog/blob/master/ARCHITECTURE.md)
51
- for how `init` resolves and fetches a core package — that mechanism lives
52
- there, not here.
34
+ ## Built for production backend work
53
35
 
54
- No root `CLAUDE.md` lives in this repo. `CLAUDE.core.md` is a payload
55
- file: its content is installed into a *consuming project's* generated
56
- `CLAUDE.md`, filling that project's `{{CORE_SECTION}}` placeholder. A
57
- plain root `CLAUDE.md` here would auto-load into any coding agent working
58
- on this package itself, bleeding project-build context into a repo where
59
- no Hedgehog build ever runs — build guidance for a project using this
60
- core lives in that project's own generated `CLAUDE.md`, never here.
36
+ Reach for this core when the project needs authorization beyond
37
+ per-object rules, background jobs, scheduled work, webhooks, or
38
+ server-rendered pages. These are the features that turn "add a database"
39
+ into an ongoing maintenance job.
61
40
 
62
- Changing this core means editing one of: the `workspace/` template (the
63
- scaffold a Hedgehog install copies into a project's repo root), an agent
64
- under `agents/`, a skill under `skills/`, or the vendored asset set under
65
- `vendor-skills/GSAP`. `scripts/regenerate-full-stack-app-core.sh` is the
66
- deterministic generator that rebuilds `workspace/` from scratch — run it
67
- by hand after bumping a workspace dependency, then diff the result before
68
- committing. A change here is a release of this package, not of the
69
- engine: bump `package.json`'s version, commit, and merge to `main` — this
70
- repo's own `publish.yml` tags and publishes from there.
41
+ ## Easy to install and use
71
42
 
72
- When `workspace/`'s template needs a new piece of repeatable boilerplate
73
- a new module shape, a new generated file type — prefer building or
74
- extending a generator over hand-authoring the output once. This core
75
- already models the pattern: `workspace/tools/generators/` carries Nx
76
- generators for every domain-module layer (`schema`, `contract`,
77
- `repository`, `service`, `controller`, `hook`, `screen`) that
78
- `nx-generate` drives instead of an agent writing that boilerplate
79
- freehand. Other cores and future add-ons should model new scaffolding
80
- against this one.
43
+ Ask your agent:
44
+ *"Install Hedgehog and build me a [your app idea]"*
45
+
46
+ <details>
47
+ <summary>For your agent</summary>
48
+
49
+ ```
50
+ npx @skyf0xx/hedgehog init
51
+ ```
52
+
53
+ ```
54
+ npx @skyf0xx/hedgehog init --ts-full-stack-app
55
+ ```
56
+
57
+ Technical details: [ARCHITECTURE.md](ARCHITECTURE.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyf0xx/hedgehog-core-full-stack-app",
3
- "version": "1.0.14",
3
+ "version": "1.1.0",
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": {
@@ -153,20 +153,42 @@ writes `docs/design/<module>.md`, not its own compiled layer — the
153
153
  zero. `hedgehog ready` previews the same decision without claiming
154
154
  anything — CLAIMABLE vs HELD BACK, with the reason for each holdback —
155
155
  useful for understanding the scheduler before committing to a claim.
156
- 2. **Dispatch each claimed packet to its own subagent** `backend-eng`
157
- (Phase A) or `front-end-eng` (Phase B), matching each packet's ALLOWED
158
- SCOPE in ONE message with parallel tool calls, not one agent call
159
- after another. This is a Claude session orchestrating via the Agent
160
- tool's parallel-call mechanism: N claimed tasks means N Agent calls in
161
- the same message. If a dispatch by name reports the agent as not
162
- found expected right after `init`/`update` installed it this same
156
+ 2. **For each claimed packet, decide inline vs. dispatch, then act.**
157
+ Default to dispatching to its own subagent — `backend-eng` (Phase A)
158
+ or `front-end-eng` (Phase B), matching the packet's ALLOWED SCOPE
159
+ in ONE message with parallel tool calls, not one agent call after
160
+ another. This is a Claude session orchestrating via the Agent tool's
161
+ parallel-call mechanism: N claimed tasks dispatched this way means N
162
+ Agent calls in the same message. Build or confirm the packet
163
+ directly instead, with no subagent, only when the packet clears one
164
+ of these from the packet alone:
165
+ - **ALLOWED SCOPE** names a small, bounded set of files the
166
+ orchestrator can read directly without ballooning its own context.
167
+ - **RELEVANT RULES or the module name** make the layer's irrelevance
168
+ checkable in one read — the task's own rules describe a concern
169
+ that plainly doesn't touch this layer's area.
170
+ - The change, once its shape is known, is small and mechanical — a
171
+ rename, an import fix, a one-line registration — rather than
172
+ something needing a subagent's isolated, fresh-context judgment.
173
+
174
+ Escalate to a full `backend-eng`/`front-end-eng` dispatch mid-layer
175
+ the moment any of these turns out false — a "quick check" that
176
+ surfaces real cross-file reasoning, an unclear scope, or a diff
177
+ bigger than expected. Never lock in "inline" once guessed. Either
178
+ way, the layer's own VERIFICATION command and ALLOWED SCOPE gate
179
+ apply identically in step 4 — this choice changes who reads, writes,
180
+ and checks, never what gets checked before it's accepted. A no-op
181
+ found inline is still reported per the packet's HONESTY rules, never
182
+ assumed. If a dispatch by name reports the agent as not found —
183
+ expected right after `init`/`update` installed it this same
163
184
  session — see root CLAUDE.md's "Delegating on this host" note rather
164
185
  than treating it as fatal.
165
- 3. Each agent **runs typecheck/lint/test on its own work** (mirrors
166
- lefthook, wired at bootstrap) as a sanity check before reporting
167
- back necessary, not sufficient. Per task, per agent: the agent
168
- reports its work as done; it does not move the task and does not
169
- commit.
186
+ 3. Whoever built the packet the dispatched agent, or the orchestrator
187
+ itself when it went inline **runs typecheck/lint/test on that
188
+ work** (mirrors lefthook, wired at bootstrap) as a sanity check
189
+ before reporting back necessary, not sufficient. Per task: the
190
+ work is reported as done; the task is not moved and nothing is
191
+ committed yet.
170
192
  4. **As each report arrives, verify it — one at a time, serially.** Run
171
193
  `hedgehog verify <task-id> --owner <owner>` (the same owner that
172
194
  claimed it; verify requires the lease owner). Building happens in
@@ -46,11 +46,23 @@
46
46
  "executor": "@nx/js:prune-lockfile",
47
47
  "outputs": [
48
48
  "{workspaceRoot}/apps/api/dist/package.json",
49
- "{workspaceRoot}/apps/api/dist/pnpm-lock.yaml"
49
+ "{workspaceRoot}/apps/api/dist/pnpm-lock.yaml",
50
+ "{workspaceRoot}/apps/api/dist/pnpm-workspace.yaml",
51
+ "{workspaceRoot}/apps/api/dist/patches",
52
+ "{workspaceRoot}/apps/api/dist/local_path_modules"
50
53
  ],
51
54
  "options": {
52
55
  "buildTarget": "build"
53
- }
56
+ },
57
+ "inputs": [
58
+ "default",
59
+ "^default",
60
+ "{workspaceRoot}/pnpm-workspace.yaml",
61
+ "{workspaceRoot}/package.json",
62
+ {
63
+ "runtime": "node -e \"try{console.log('pnpm major '+require('child_process').execSync('pnpm --version',{stdio:['ignore','pipe','ignore']}).toString().trim().split('.')[0])}catch{console.log('pnpm major unavailable')}\""
64
+ }
65
+ ]
54
66
  },
55
67
  "copy-workspace-modules": {
56
68
  "dependsOn": [
@@ -1,7 +1,7 @@
1
1
  import { defineConfig } from 'vitest/config';
2
2
 
3
3
  export default defineConfig(() => ({
4
- root: __dirname,
4
+ root: import.meta.dirname,
5
5
  cacheDir: '../../node_modules/.vite/apps/api',
6
6
  test: {
7
7
  name: 'api',
@@ -1,7 +1,7 @@
1
1
  import { defineConfig } from 'vitest/config';
2
2
 
3
3
  export default defineConfig(() => ({
4
- root: __dirname,
4
+ root: import.meta.dirname,
5
5
  cacheDir: '../../node_modules/.vite/apps/api-e2e',
6
6
  test: {
7
7
  name: 'api-e2e',
@@ -0,0 +1,9 @@
1
+ <!-- BEGIN:nextjs-agent-rules -->
2
+
3
+ # This is NOT the Next.js you know
4
+
5
+ This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.
6
+
7
+ This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.
8
+
9
+ <!-- END:nextjs-agent-rules -->
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -1,7 +1,7 @@
1
1
  /// <reference types="next" />
2
2
  /// <reference types="next/image-types/global" />
3
- import "./.next/types/routes.d.ts";
4
- import "./.next/types/root-params.d.ts";
3
+ import "./.next/dev/types/routes.d.ts";
4
+ import "./.next/dev/types/root-params.d.ts";
5
5
 
6
6
  // NOTE: This file should not be edited
7
7
  // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -3,7 +3,7 @@ import react from '@vitejs/plugin-react';
3
3
  import { fileURLToPath } from 'node:url';
4
4
 
5
5
  export default defineConfig(() => ({
6
- root: __dirname,
6
+ root: import.meta.dirname,
7
7
  cacheDir: '../../node_modules/.vite/apps/web',
8
8
  plugins: [react()],
9
9
  resolve: {
@@ -14,17 +14,17 @@
14
14
  "@nestjs/schematics": "^11.0.0",
15
15
  "@nestjs/testing": "^11.0.0",
16
16
  "@next/eslint-plugin-next": "^16.1.6",
17
- "@nx/devkit": "23.1.2",
18
- "@nx/eslint": "23.1.2",
19
- "@nx/eslint-plugin": "23.1.2",
20
- "@nx/js": "23.1.2",
21
- "@nx/nest": "23.1.2",
22
- "@nx/next": "23.1.2",
23
- "@nx/node": "23.1.2",
24
- "@nx/playwright": "23.1.2",
25
- "@nx/vitest": "23.1.2",
26
- "@nx/web": "23.1.2",
27
- "@nx/webpack": "23.1.2",
17
+ "@nx/devkit": "23.2.0",
18
+ "@nx/eslint": "23.2.0",
19
+ "@nx/eslint-plugin": "23.2.0",
20
+ "@nx/js": "23.2.0",
21
+ "@nx/nest": "23.2.0",
22
+ "@nx/next": "23.2.0",
23
+ "@nx/node": "23.2.0",
24
+ "@nx/playwright": "23.2.0",
25
+ "@nx/vitest": "23.2.0",
26
+ "@nx/web": "23.2.0",
27
+ "@nx/webpack": "23.2.0",
28
28
  "@playwright/test": "^1.37.0",
29
29
  "@swc-node/register": "~1.11.1",
30
30
  "@swc/cli": "~0.8.1",
@@ -52,7 +52,7 @@
52
52
  "eslint-plugin-react-hooks": "7.1.1",
53
53
  "jsdom": "^30.0.1",
54
54
  "lefthook": "^2.1.10",
55
- "nx": "23.1.2",
55
+ "nx": "23.2.0",
56
56
  "prettier": "~3.6.2",
57
57
  "tslib": "^2.3.0",
58
58
  "typescript": "~6.0.3",
@@ -97,7 +97,7 @@
97
97
  }
98
98
  },
99
99
  "overrides": {
100
- "@nx/module-federation": "23.1.2",
100
+ "@nx/module-federation": "23.2.0",
101
101
  "esbuild": "0.25.12",
102
102
  "axios": "^1.18.0",
103
103
  "brace-expansion@1": "^1.1.18",
@@ -1,7 +1,7 @@
1
1
  import { defineConfig } from 'vitest/config';
2
2
 
3
3
  export default defineConfig(() => ({
4
- root: __dirname,
4
+ root: import.meta.dirname,
5
5
  cacheDir: '../../node_modules/.vite/packages/config',
6
6
  test: {
7
7
  name: 'config',
@@ -1,7 +1,7 @@
1
1
  import { defineConfig } from 'vitest/config';
2
2
 
3
3
  export default defineConfig(() => ({
4
- root: __dirname,
4
+ root: import.meta.dirname,
5
5
  cacheDir: '../../node_modules/.vite/packages/db',
6
6
  test: {
7
7
  name: 'db',