@skyf0xx/hedgehog 5.0.0 → 5.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 +7 -14
- package/bin/cli.mjs +24 -6
- package/package.json +1 -1
- package/src/agents/planner.md +142 -26
- package/src/db/claim.mjs +7 -0
- package/src/db/core.mjs +1 -1
- package/src/hosts/capabilities.mjs +1 -0
- package/src/hosts/cursor/DISPATCH.md +3 -0
- package/src/registry/cores.json +11 -2
- package/src/registry/index.mjs +1 -1
- package/src/skills/hedgehog-planning-intake/SKILL.md +40 -29
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Turn AI from a code generator into a reliable software engineer ⭐
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@skyf0xx/hedgehog)
|
|
4
|
+
[](https://ko-fi.com/skyf0xx)
|
|
4
5
|
|
|
5
6
|
AI can write code in seconds.
|
|
6
7
|
|
|
@@ -42,6 +43,7 @@ Hedgehog combines:
|
|
|
42
43
|
- **TDD and progressive layering** — build one tested layer at a time
|
|
43
44
|
- **Mechanical enforcement** — use tooling and phase gates instead of trusting the AI to follow instructions
|
|
44
45
|
- **Small context loops** — keep every change focused, verifiable, and easy to review
|
|
46
|
+
- **Deterministic scaffolding** — generate boilerplate and schemas instead of asking the AI to write it freehand
|
|
45
47
|
|
|
46
48
|
Software that stays structured as it grows.
|
|
47
49
|
|
|
@@ -138,7 +140,7 @@ Artifact
|
|
|
138
140
|
|
|
139
141
|
### Anything else
|
|
140
142
|
|
|
141
|
-
A CLI, a library, a browser extension, a data pipeline, etc. fitting neither shape gets its own build order, designed at intake rather than chosen from a menu — starting from a
|
|
143
|
+
A CLI, a library, a browser extension, a data pipeline, etc. fitting neither shape gets its own build order, designed at intake rather than chosen from a menu — starting from a battle-tested blueprint (in [`hedgehog-core-authored`](https://github.com/skyf0xx/hedgehog-core-authored)'s `hedgehog-core-design` skill) for the system's shape where one exists.
|
|
142
144
|
|
|
143
145
|
Run `init` with no core flag: planning intake names the system shape, picks
|
|
144
146
|
the stack, derives the layers, and locks them to `.hedgehog/core.yaml`,
|
|
@@ -195,17 +197,6 @@ npx @skyf0xx/hedgehog update
|
|
|
195
197
|
|
|
196
198
|
This refreshes the installed agents and skills in a specific repo (note, not vendor skills)
|
|
197
199
|
|
|
198
|
-
### Installing a specific core
|
|
199
|
-
|
|
200
|
-
Naming a core up front installs it with the shared payload. Without one, `init` installs the shared payload alone and leaves the choice to planning intake, where `planner` selects a core — `full-stack-app`, `landing-page`, or one it designs for the project:
|
|
201
|
-
|
|
202
|
-
``` bash
|
|
203
|
-
npx @skyf0xx/hedgehog init --core full-stack-app
|
|
204
|
-
npx @skyf0xx/hedgehog cores list # every core this release can install, and what each is for
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
Each named core ships as its own npm package (`@skyf0xx/hedgehog-core-full-stack-app`, `@skyf0xx/hedgehog-core-landing-page`); `init` fetches the version `src/registry/cores.json` names and caches it locally, so a repeat install on the same version needs no network.
|
|
208
|
-
|
|
209
200
|
## Why Hedgehog
|
|
210
201
|
|
|
211
202
|
Most AI coding tools improve prompting.
|
|
@@ -253,6 +244,8 @@ pnpm-only workspace convention.
|
|
|
253
244
|
|
|
254
245
|
## Support Hedgehog
|
|
255
246
|
|
|
256
|
-
If Hedgehog helps you build better software with AI, give it a ⭐ on GitHub.
|
|
247
|
+
If Hedgehog helps you build better software with AI, **give it a ⭐ on GitHub**, or [buy me a coffee on Ko-fi](https://ko-fi.com/skyf0xx).
|
|
257
248
|
|
|
258
|
-
[](https://github.com/skyf0xx/hedgehog/stargazers)
|
|
250
|
+
[](https://www.npmjs.com/package/@skyf0xx/hedgehog)
|
|
251
|
+
[](https://ko-fi.com/skyf0xx)
|
package/bin/cli.mjs
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// Usage:
|
|
6
6
|
// npx @skyf0xx/hedgehog init install; planner picks the core at intake
|
|
7
7
|
// npx @skyf0xx/hedgehog init --ts-full-stack-app scaffold the full-stack-app core now
|
|
8
|
+
// npx @skyf0xx/hedgehog init --pwa-app scaffold the pwa-app core now
|
|
8
9
|
// npx @skyf0xx/hedgehog init --landing-page scaffold the landing-page core now
|
|
9
10
|
// npx @skyf0xx/hedgehog init --cursor install for Cursor (default: Claude Code)
|
|
10
11
|
// npx @skyf0xx/hedgehog init --all-hosts install for every supported coding agent
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
releaseTask,
|
|
37
38
|
renewLease,
|
|
38
39
|
retryTask,
|
|
40
|
+
reapExpiredLeases,
|
|
39
41
|
} from '../src/db/claim.mjs';
|
|
40
42
|
import { readyTasks, formatReady } from '../src/db/ready.mjs';
|
|
41
43
|
import { graphStatus, formatStatus } from '../src/db/status.mjs';
|
|
@@ -104,7 +106,7 @@ const DOTFILE_RENAMES = { 'gitignore.template': '.gitignore' };
|
|
|
104
106
|
|
|
105
107
|
// Build artifacts that must never be copied into a consuming project,
|
|
106
108
|
// even if a future publish accidentally includes them: the full-stack-app
|
|
107
|
-
//
|
|
109
|
+
// core documents that `node_modules` is regenerated by `pnpm
|
|
108
110
|
// install` in step 4, not shipped, and a platform-specific `node_modules`
|
|
109
111
|
// snapshot from the publisher's machine can be stale or broken for
|
|
110
112
|
// everyone else (e.g. a dangling optional-dependency symlink).
|
|
@@ -148,7 +150,7 @@ async function namedCore(args) {
|
|
|
148
150
|
// which core applies left for `planner` to decide. `bootstrap` lands the
|
|
149
151
|
// core workspace and fills the CLAUDE.md section for whichever core
|
|
150
152
|
// `planner` picks — the first time either way. An explicit flag
|
|
151
|
-
// (`--ts-full-stack-app`, `--landing-page`) is a confirmed choice, so it
|
|
153
|
+
// (`--ts-full-stack-app`, `--pwa-app`, `--landing-page`) is a confirmed choice, so it
|
|
152
154
|
// scaffolds that workspace immediately, at install time.
|
|
153
155
|
//
|
|
154
156
|
// A core is passed in as `{ manifest, root }` from fetchCore — the parsed
|
|
@@ -482,6 +484,7 @@ ${bold('Usage')}
|
|
|
482
484
|
npx @skyf0xx/hedgehog init install; planner picks the core at intake
|
|
483
485
|
npx @skyf0xx/hedgehog init --core <name> install that core now, by name
|
|
484
486
|
npx @skyf0xx/hedgehog init --ts-full-stack-app scaffold the full-stack-app core now
|
|
487
|
+
npx @skyf0xx/hedgehog init --pwa-app scaffold the pwa-app core now
|
|
485
488
|
npx @skyf0xx/hedgehog init --landing-page scaffold the landing-page core now
|
|
486
489
|
npx @skyf0xx/hedgehog cores list every core this release can install
|
|
487
490
|
npx @skyf0xx/hedgehog init --cursor install for Cursor (default: Claude Code)
|
|
@@ -811,7 +814,7 @@ async function update({ hosts }) {
|
|
|
811
814
|
// refresh.
|
|
812
815
|
const UNRESOLVED = Symbol('unresolved core');
|
|
813
816
|
|
|
814
|
-
// A root `core.yaml` is a
|
|
817
|
+
// A root `core.yaml` is a core's own file: `corePayload` lands it
|
|
815
818
|
// as part of that core's `workspace` at install time, so its presence is
|
|
816
819
|
// direct evidence a core package's files are on disk — independent of
|
|
817
820
|
// `.hedgehog/core.yaml`, the authored-core path, which is a different
|
|
@@ -928,7 +931,7 @@ async function dbCommand(args) {
|
|
|
928
931
|
}
|
|
929
932
|
|
|
930
933
|
// Resolves the project's core definition: an authored .hedgehog/core.yaml
|
|
931
|
-
// takes precedence (spec: "Authored cores"); otherwise the
|
|
934
|
+
// takes precedence (spec: "Authored cores"); otherwise the core's
|
|
932
935
|
// own core.yaml, which lands at repo root along with the rest of that
|
|
933
936
|
// core package's workspace. Neither exists yet on a deferred install
|
|
934
937
|
// (plain `init`, no core named) until `bootstrap` runs — this returns
|
|
@@ -1222,7 +1225,9 @@ async function intentCommand(args) {
|
|
|
1222
1225
|
try {
|
|
1223
1226
|
intent = await addIntent(db, record);
|
|
1224
1227
|
} catch (err) {
|
|
1225
|
-
console.error(
|
|
1228
|
+
console.error(
|
|
1229
|
+
`${red('Failed to add intent:')} ${err.message}\n\nUsage: hedgehog intent add --id <id> --goal <goal> --outcome <outcome> [--rule <r>]... [--depends-on <id>]...\n or: hedgehog intent add --file <path.json>\n`,
|
|
1230
|
+
);
|
|
1226
1231
|
process.exitCode = 1;
|
|
1227
1232
|
return;
|
|
1228
1233
|
} finally {
|
|
@@ -2062,6 +2067,12 @@ async function statusCommand() {
|
|
|
2062
2067
|
const db = openDb();
|
|
2063
2068
|
let result;
|
|
2064
2069
|
try {
|
|
2070
|
+
// A task whose lease expired with no intervening `claim`/`verify`
|
|
2071
|
+
// call is still sitting in `building`/`verifying` in the DB —
|
|
2072
|
+
// without this, status keeps reporting a dead agent's task as
|
|
2073
|
+
// in-flight indefinitely, and `hedgehog retry` refuses it as "not
|
|
2074
|
+
// blocked" until some other command happens to reap it first.
|
|
2075
|
+
reapExpiredLeases(db);
|
|
2065
2076
|
result = graphStatus(db, { core, overrides });
|
|
2066
2077
|
} finally {
|
|
2067
2078
|
db.close();
|
|
@@ -2136,6 +2147,7 @@ async function quiesceCommand() {
|
|
|
2136
2147
|
const db = openDb();
|
|
2137
2148
|
let inFlight;
|
|
2138
2149
|
try {
|
|
2150
|
+
reapExpiredLeases(db);
|
|
2139
2151
|
({ inFlight } = graphStatus(db));
|
|
2140
2152
|
} finally {
|
|
2141
2153
|
db.close();
|
|
@@ -2612,7 +2624,9 @@ async function debtCommand(args) {
|
|
|
2612
2624
|
try {
|
|
2613
2625
|
entry = addDebt(db, { taskId, note });
|
|
2614
2626
|
} catch (err) {
|
|
2615
|
-
console.error(
|
|
2627
|
+
console.error(
|
|
2628
|
+
`${red('Failed to declare debt:')} ${err.message}\n\nRun ${bold('hedgehog status')} to see valid task ids.\n`,
|
|
2629
|
+
);
|
|
2616
2630
|
process.exitCode = 1;
|
|
2617
2631
|
return;
|
|
2618
2632
|
} finally {
|
|
@@ -2698,6 +2712,10 @@ async function main() {
|
|
|
2698
2712
|
await help();
|
|
2699
2713
|
return;
|
|
2700
2714
|
}
|
|
2715
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
2716
|
+
console.log(PKG_VERSION);
|
|
2717
|
+
return;
|
|
2718
|
+
}
|
|
2701
2719
|
const cmd = args[0];
|
|
2702
2720
|
const force = args.includes('--force') || args.includes('-f');
|
|
2703
2721
|
|
package/package.json
CHANGED
package/src/agents/planner.md
CHANGED
|
@@ -89,26 +89,85 @@ A core whose `when` fits and whose `flag` is listed is chosen by name
|
|
|
89
89
|
and handed to `bootstrap`, which installs that core's package and
|
|
90
90
|
follows the bootstrap skill it ships.
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
**Before matching against `when` paragraphs, ask up to three
|
|
93
|
+
clarifying questions if the description alone doesn't already settle
|
|
94
|
+
them.** Most users describing a project for the first time are not
|
|
95
|
+
naming their own architecture — they're naming what the thing does —
|
|
96
|
+
so this step exists to pull out the handful of facts that actually
|
|
97
|
+
distinguish one core's `when` from another's, in the same plain
|
|
98
|
+
language the user already used, not in the vocabulary of the cores
|
|
99
|
+
themselves. Skip a question outright whenever the description already
|
|
100
|
+
answers it; skip the whole step when the description is unambiguous
|
|
101
|
+
(a landing page with no state, an obvious full-stack SaaS with several
|
|
102
|
+
described entities and accounts) — this is a gap-filler, not a
|
|
103
|
+
mandatory interview. Never exceed three, and never ask more than one
|
|
104
|
+
at a time if the conversation is turn-by-turn.
|
|
105
|
+
|
|
106
|
+
The three questions this step exists for, asked as an engineer
|
|
107
|
+
eliciting requirements would ask them, never as an architecture quiz
|
|
108
|
+
the user can't answer without already knowing the answer:
|
|
109
|
+
|
|
110
|
+
- **Where does the data really need to live?** — "does this need to
|
|
111
|
+
work on one device, or be the same for you across your phone and
|
|
112
|
+
laptop, or shared with other people?" Distinguishes `pwa-app`
|
|
113
|
+
(single-device or a small, known set of people) from `full-stack-app`
|
|
114
|
+
(a system other people or services interact with independently) —
|
|
115
|
+
never phrase this as "will your app have a full API backend," which
|
|
116
|
+
assumes the answer.
|
|
117
|
+
- **Is there ongoing behavior, or just a page?** — "once it's built,
|
|
118
|
+
does anything keep happening on its own — reminders, scheduled
|
|
119
|
+
updates, other people's actions showing up — or is it something you
|
|
120
|
+
open and use?" Distinguishes `landing-page` (nothing ongoing, no
|
|
121
|
+
state of its own) from either app core.
|
|
122
|
+
- **Is this a one-time thing, or a real, evolving artifact?** — "is
|
|
123
|
+
this a one-off script or document, or something you'll keep coming
|
|
124
|
+
back to and adding to?" Separates "nothing to build here" and
|
|
125
|
+
"authored core" from the shipped cores above.
|
|
126
|
+
|
|
127
|
+
Answers here are inputs to the `when`-paragraph match below, not a
|
|
128
|
+
replacement for it — don't skip reading every core's `when` just
|
|
129
|
+
because a question landed on a name. State which questions you're
|
|
130
|
+
asking and why in one line each, so the user can see this is
|
|
131
|
+
narrowing a real ambiguity rather than a rote checklist. This step
|
|
132
|
+
never runs on re-entry (Phase 0 as a whole is skipped there) and never
|
|
133
|
+
substitutes for `hedgehog-planning-intake`'s own elicitation once a
|
|
134
|
+
core is chosen — that's a full BMAD-driven pass; this is three
|
|
135
|
+
questions to pick which pass to run.
|
|
136
|
+
|
|
137
|
+
Data that gets stored is not, by itself, `full-stack-app` — that used to
|
|
138
|
+
be the rule, and it swallowed every candidate for `pwa-app` (a tracker,
|
|
139
|
+
journal, notebook, or planner whose data belongs on the user's own
|
|
140
|
+
device). The real question is where the data lives and who needs to
|
|
141
|
+
enforce the rules around it. A description naming a local-first app —
|
|
142
|
+
offline capability or installability named explicitly is a strong
|
|
143
|
+
signal — is `pwa-app`, even with sharing, accounts, or multi-device sync
|
|
144
|
+
in scope (Dexie Cloud covers that), and even with a small number of
|
|
145
|
+
entities that must be server-authoritative (those go `--remote`, backed
|
|
146
|
+
by Supabase, without moving the whole project off `pwa-app`). What
|
|
147
|
+
routes a project to `full-stack-app` instead is server-side logic across
|
|
148
|
+
*most* of the app: authorization more expressive than per-object
|
|
149
|
+
row-level security, background jobs or webhooks as the app's primary
|
|
150
|
+
function, server-rendered or SEO-critical pages, or a working set too
|
|
151
|
+
large for a device. Never talk the user down to browser-local storage
|
|
152
|
+
for `full-stack-app` shape sounding small, and never talk them up to a
|
|
153
|
+
server for `pwa-app` shape sounding real — the core ships a real
|
|
154
|
+
database either way, and picking the wrong one because of what a core
|
|
155
|
+
"sounds like" is the drift this discipline exists to prevent.
|
|
98
156
|
|
|
99
157
|
This is a distinct question from project *size*. A single-table, single-
|
|
100
|
-
user tool (one person's task list, a personal habit tracker)
|
|
101
|
-
`full-stack-app
|
|
102
|
-
|
|
103
|
-
sections is still `landing-page`, not promoted
|
|
104
|
-
being long. Shape decides the core; size decides
|
|
158
|
+
user tool (one person's task list, a personal habit tracker) fits
|
|
159
|
+
`pwa-app` if its data is local, or `full-stack-app` scoped through the
|
|
160
|
+
Add-ons decision if it isn't — size alone decides neither. Likewise a
|
|
161
|
+
landing page with a dozen sections is still `landing-page`, not promoted
|
|
162
|
+
to `full-stack-app` for being long. Shape decides the core; size decides
|
|
163
|
+
nothing.
|
|
105
164
|
|
|
106
165
|
Three outcomes are decided here rather than in the registry, because
|
|
107
166
|
none of them is a description matching a `when` paragraph:
|
|
108
167
|
|
|
109
168
|
- **Neither shipped core fits, but something is being built** — the
|
|
110
169
|
description names a real artifact a Builder step would produce, just
|
|
111
|
-
not in either
|
|
170
|
+
not in either shipped core's shape. This project gets an **authored
|
|
112
171
|
core**, designed by you and written to `.hedgehog/core.yaml`. Don't ask
|
|
113
172
|
the user what layers to build in — someone who could name the right
|
|
114
173
|
sequence unprompted wouldn't need a discipline to enforce it. Run
|
|
@@ -118,7 +177,7 @@ none of them is a description matching a `when` paragraph:
|
|
|
118
177
|
archive: it names the system shape, picks the stack, derives the
|
|
119
178
|
layers, decides the module axis, and writes `.hedgehog/core.yaml` plus
|
|
120
179
|
its rationale at its own Confirm & Lock. An authored core is a weaker
|
|
121
|
-
guarantee than a
|
|
180
|
+
guarantee than a shipped core (the sequence was designed for this
|
|
122
181
|
project, not battle-tested across many) but carries the same
|
|
123
182
|
enforcement — ordered layers, scoped file access, verification before
|
|
124
183
|
completion — and the loader has no leniency for it
|
|
@@ -143,7 +202,7 @@ none of them is a description matching a `when` paragraph:
|
|
|
143
202
|
everything above: it's not about which core fits new work, because no
|
|
144
203
|
new workspace gets built at all. Route straight to `hedgehog-adopt` —
|
|
145
204
|
bootstrap and every other Phase 0 outcome are skipped entirely, since
|
|
146
|
-
there is no workspace to scaffold and no
|
|
205
|
+
there is no workspace to scaffold and no shipped stack to adopt toward.
|
|
147
206
|
`hedgehog-adopt` runs its own read-only intake and writes its own
|
|
148
207
|
`.hedgehog/core.yaml`; don't run `hedgehog-planning-intake`'s BMAD shelf
|
|
149
208
|
first — the drivers that skill elicits (persistence, stack, deployment
|
|
@@ -174,6 +233,15 @@ the first-run shape; on re-entry, run `hedgehog-planning-intake`'s
|
|
|
174
233
|
Hedgehog's own build discipline."* BMAD elicits and produces planning
|
|
175
234
|
documents; it has no execution discipline of its own — Hedgehog starts
|
|
176
235
|
where BMAD's output ends.
|
|
236
|
+
- **`pwa-app`** → open `hedgehog-planning-intake` and follow it in full,
|
|
237
|
+
exactly as `full-stack-app` does: Phase 0 runs the same vendored BMAD
|
|
238
|
+
shelf, archived to `.hedgehog/BMAD/`; Phase 1 mines `04-prd.md` into
|
|
239
|
+
intent records the same way, one domain module per PRD Feature; the
|
|
240
|
+
same Confirm & Lock stage is the hard stop before anything gets
|
|
241
|
+
written. State the same BMAD attribution as full-stack-app before that
|
|
242
|
+
Phase 0 begins. The one addition: this core's own Add-ons-equivalent
|
|
243
|
+
decision (sync, remote entities — see below) instead of
|
|
244
|
+
full-stack-app's Auth/Queue/Mobile.
|
|
177
245
|
- **`landing-page`** → open `hedgehog-landing-loop`'s planning-intake
|
|
178
246
|
section and follow it: it opens with `hedgehog-planning-intake`'s
|
|
179
247
|
Phase 0 (the same vendored BMAD shelf `full-stack-app` runs, in full,
|
|
@@ -190,9 +258,9 @@ the first-run shape; on re-entry, run `hedgehog-planning-intake`'s
|
|
|
190
258
|
`hedgehog-planning-intake`.
|
|
191
259
|
|
|
192
260
|
Either way, this is the mechanical procedure; the judgment — what's
|
|
193
|
-
actually in scope, where a table becomes a module (full-stack-app
|
|
194
|
-
what the page's single job actually is (landing-page) —
|
|
195
|
-
throughout.
|
|
261
|
+
actually in scope, where a table becomes a module (full-stack-app,
|
|
262
|
+
pwa-app) or what the page's single job actually is (landing-page) —
|
|
263
|
+
stays yours throughout.
|
|
196
264
|
|
|
197
265
|
## The Add-ons decision (full-stack-app only)
|
|
198
266
|
|
|
@@ -246,6 +314,42 @@ differently. Written once at Phase 1; a later run (new scope entering
|
|
|
246
314
|
play) only edits it if new scope genuinely changes a trigger (e.g.
|
|
247
315
|
accounts get added where there were none).
|
|
248
316
|
|
|
317
|
+
## The sync/remote-entities decision (pwa-app only)
|
|
318
|
+
|
|
319
|
+
Two independent booleans, the `pwa-app` counterpart to full-stack-app's
|
|
320
|
+
Add-ons decision above — same mechanism (`.hedgehog/addons.yaml`, decided
|
|
321
|
+
once while mining `04-prd.md`, shown at Confirm & Lock), different
|
|
322
|
+
triggers, since this core has no Auth/Queue/Mobile infra to decide:
|
|
323
|
+
|
|
324
|
+
- **Sync** — on if the PRD describes more than one user or more than one
|
|
325
|
+
device sharing the same data (a shared list, a two-person journal, a
|
|
326
|
+
small team's board) — Dexie Cloud, wired by this core's bootstrap skill.
|
|
327
|
+
- **Remote entities** — on if the PRD names at least one entity a client
|
|
328
|
+
must not be able to write to directly (a points balance, a reward
|
|
329
|
+
ledger, anything server-arbitrated) — Supabase, wired the same way.
|
|
330
|
+
This is a project-wide bootstrap decision (whether the Supabase client
|
|
331
|
+
gets wired at all); *which* entities are generated `--remote` is a
|
|
332
|
+
later, per-entity, build-time choice, not decided here.
|
|
333
|
+
|
|
334
|
+
Infer first, gap-fill second, same discipline as the Add-ons decision:
|
|
335
|
+
"is this used by more than one person, or shared across your own
|
|
336
|
+
devices?" for sync, "is there any balance or record here a user
|
|
337
|
+
shouldn't be able to edit directly?" for remote entities. A "no" is a
|
|
338
|
+
resolved answer. Neither disqualifies `pwa-app` as the core — see Phase
|
|
339
|
+
0 above — they only decide what bootstrap wires.
|
|
340
|
+
|
|
341
|
+
```yaml
|
|
342
|
+
sync:
|
|
343
|
+
on: true
|
|
344
|
+
reason: shared list, two members
|
|
345
|
+
remote_entities:
|
|
346
|
+
on: false
|
|
347
|
+
reason: no server-authoritative entity in scope
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
A project can take either, both, or neither — independent booleans, same
|
|
351
|
+
as full-stack-app's Auth/Queue/Mobile trio.
|
|
352
|
+
|
|
249
353
|
## Core Responsibilities
|
|
250
354
|
|
|
251
355
|
- Decide which core applies before running any planning-intake skill —
|
|
@@ -256,6 +360,10 @@ accounts get added where there were none).
|
|
|
256
360
|
artifacts; the
|
|
257
361
|
intent records Phase 1 writes via `hedgehog intent add` live in the
|
|
258
362
|
build graph, not a file this agent owns.
|
|
363
|
+
- **pwa-app**: same shape as full-stack-app — owns `.hedgehog/BMAD/` and
|
|
364
|
+
`.hedgehog/addons.yaml` (sync, remote entities, per "The sync/
|
|
365
|
+
remote-entities decision" above) as artifacts; intent records live in
|
|
366
|
+
the build graph.
|
|
259
367
|
- **landing-page**: owns `.hedgehog/BMAD/` and
|
|
260
368
|
`.hedgehog/chain/00-brief.md` as artifacts.
|
|
261
369
|
- **brownfield adoption**: owns nothing here — `hedgehog-adopt` owns
|
|
@@ -294,7 +402,9 @@ accounts get added where there were none).
|
|
|
294
402
|
|
|
295
403
|
Read the commit log alongside it for what's already built —
|
|
296
404
|
full-stack-app: `feat(<module>): api` commits and each task's status in
|
|
297
|
-
the graph mark modules with a closed Phase A.
|
|
405
|
+
the graph mark modules with a closed Phase A. pwa-app: `feat(<module>):
|
|
406
|
+
screen` commits and each task's status mark a module's closed
|
|
407
|
+
sequence, per its own five-layer `core.yaml`. Landing-page: a
|
|
298
408
|
`complete` phase task marks that phase's artifact as committed.
|
|
299
409
|
Authored core: each `complete` task marks that layer committed, per
|
|
300
410
|
`.hedgehog/core.yaml`'s own commit messages. On re-entry this is what
|
|
@@ -319,6 +429,9 @@ accounts get added where there were none).
|
|
|
319
429
|
the user directly only for whatever the PRD leaves unresolved. The
|
|
320
430
|
mining step is the same either way; only how the archive was
|
|
321
431
|
produced differs.
|
|
432
|
+
- **First run, pwa-app**: identical procedure to full-stack-app above,
|
|
433
|
+
substituting the sync/remote-entities decision for the Add-ons
|
|
434
|
+
decision.
|
|
322
435
|
- **First run, landing-page**: run the same vendored BMAD shelf in
|
|
323
436
|
full, then mine `.hedgehog/BMAD/` into a draft subject statement
|
|
324
437
|
(subject, audience, single page job) — asking the user directly only
|
|
@@ -328,7 +441,8 @@ accounts get added where there were none).
|
|
|
328
441
|
only what's new — the BMAD shelf does not run again.
|
|
329
442
|
6. **Run the matching Confirm & Lock** before writing anything — the
|
|
330
443
|
first-run stage on a first run, the extension variant on re-entry.
|
|
331
|
-
7. **Write the intent records**: full-stack-app
|
|
444
|
+
7. **Write the intent records**: full-stack-app and pwa-app each write
|
|
445
|
+
every intent via
|
|
332
446
|
`hedgehog intent add`, one call per PRD Feature (per new module, on
|
|
333
447
|
re-entry), plus `.hedgehog/addons.yaml`; landing-page writes
|
|
334
448
|
`.hedgehog/chain/00-brief.md` per its own Confirm & Lock, in the shape
|
|
@@ -344,8 +458,8 @@ accounts get added where there were none).
|
|
|
344
458
|
`chore(planning): intake` on a first run, `chore(planning): extend
|
|
345
459
|
scope` on re-entry, so the passes are distinguishable in the log. It
|
|
346
460
|
carries the committed `.hedgehog/hedgehog.db` (its new intent and task
|
|
347
|
-
rows), `.hedgehog/addons.yaml` (full-stack-app only, and on
|
|
348
|
-
only if a trigger actually changed), this core's own archival planning
|
|
461
|
+
rows), `.hedgehog/addons.yaml` (full-stack-app and pwa-app only, and on
|
|
462
|
+
re-entry only if a trigger actually changed), this core's own archival planning
|
|
349
463
|
output (`.hedgehog/BMAD/` or `.hedgehog/chain/`, first run only), the
|
|
350
464
|
authored core's `.hedgehog/core.yaml` and `.hedgehog/core-design.md` if
|
|
351
465
|
step 4 ran, and root `CLAUDE.md`'s filled placeholders (first run
|
|
@@ -354,8 +468,9 @@ accounts get added where there were none).
|
|
|
354
468
|
intake's own unit of work, landed before `bootstrap` touches anything.
|
|
355
469
|
9. **First run only, and not on the brownfield path — hand off to the
|
|
356
470
|
`bootstrap` agent** once the commit lands. It scaffolds the chosen
|
|
357
|
-
core's workspace (and, for full-stack-app, whichever add-ons are on
|
|
358
|
-
|
|
471
|
+
core's workspace (and, for full-stack-app, whichever add-ons are on;
|
|
472
|
+
for pwa-app, whichever of sync/remote entities is on) before any build
|
|
473
|
+
step starts. On re-entry on any other core the
|
|
359
474
|
workspace already exists: hand straight to that core's loop skill
|
|
360
475
|
instead, which picks the new work up from `hedgehog next`.
|
|
361
476
|
10. **Return a summary**: which core (naming it as authored or adopted,
|
|
@@ -365,8 +480,9 @@ accounts get added where there were none).
|
|
|
365
480
|
## Constraints
|
|
366
481
|
|
|
367
482
|
- Never write or modify application code. Read-only against the
|
|
368
|
-
codebase; you may write `.hedgehog/addons.yaml` (full-stack-app
|
|
369
|
-
see "The Add-ons decision"
|
|
483
|
+
codebase; you may write `.hedgehog/addons.yaml` (full-stack-app and
|
|
484
|
+
pwa-app only — see "The Add-ons decision" and "The sync/remote-entities
|
|
485
|
+
decision" below), `.hedgehog/core.yaml` and
|
|
370
486
|
`.hedgehog/core-design.md` (authored cores only, via
|
|
371
487
|
`hedgehog-core-design`), `.hedgehog/core.yaml` and
|
|
372
488
|
`.hedgehog/adoption.md` (brownfield adoption only, via
|
|
@@ -378,7 +494,7 @@ accounts get added where there were none).
|
|
|
378
494
|
`hedgehog intent add` and `hedgehog plan` are how you write the build
|
|
379
495
|
graph itself — not a file you edit directly.
|
|
380
496
|
- On the brownfield path, never route toward converting the host repo's
|
|
381
|
-
existing stack, structure, or conventions toward any
|
|
497
|
+
existing stack, structure, or conventions toward any shipped core's —
|
|
382
498
|
not even as a suggestion. `hedgehog-adopt` designs `verify` commands
|
|
383
499
|
and layer order around what the repo already uses; it doesn't propose
|
|
384
500
|
Nx, Drizzle, or any other opinionated choice a shipped core would make.
|
package/src/db/claim.mjs
CHANGED
|
@@ -373,6 +373,13 @@ export function claimTask(db, taskId, { owner, leaseMinutes = 45 }) {
|
|
|
373
373
|
// would — still subject to its dependencies being complete.
|
|
374
374
|
export function retryTask(db, taskId) {
|
|
375
375
|
return inTransaction(db, () => {
|
|
376
|
+
// Same reason verifyTask reaps before its own status check: a task
|
|
377
|
+
// whose lease expired with no intervening `claim` call is still
|
|
378
|
+
// sitting in `building`/`verifying` here, not yet swept to `blocked`
|
|
379
|
+
// — without this, retry on that task reads "not blocked" and refuses,
|
|
380
|
+
// even though the lease is in fact dead and this is exactly the
|
|
381
|
+
// situation retry exists to recover from.
|
|
382
|
+
reapExpiredLeases(db);
|
|
376
383
|
const task = loadTask(db, taskId);
|
|
377
384
|
if (task === undefined) return { retried: false, reason: 'no_such_task' };
|
|
378
385
|
if (task.status !== 'blocked') return { retried: false, reason: 'not_blocked', task };
|
package/src/db/core.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Core-definition loader. Parses `core.yaml` — a
|
|
1
|
+
// Core-definition loader. Parses `core.yaml` — a shipped core's own
|
|
2
2
|
// definition, or an authored .hedgehog/core.yaml — into the same in-memory
|
|
3
3
|
// shape either way. See hedgehog-persistent-build-graph.md, "Core
|
|
4
4
|
// definitions".
|
|
@@ -5,6 +5,9 @@ one, read its file and follow it for that task, passing the `hedgehog
|
|
|
5
5
|
next` packet in full. Where a subagent is available, pass the file's
|
|
6
6
|
entire body as that subagent's prompt — the file is the role.
|
|
7
7
|
|
|
8
|
+
Independent steps can go out as several concurrent tool calls in one
|
|
9
|
+
response. Steps that depend on each other stay sequential.
|
|
10
|
+
|
|
8
11
|
Each agent file opens with the tools that role may use. Honor it: Cursor
|
|
9
12
|
grants tools per session, so the constraint is yours to keep. `hedgehog
|
|
10
13
|
verify` checks the touched files against the packet's ALLOWED SCOPE and
|
package/src/registry/cores.json
CHANGED
|
@@ -7,7 +7,16 @@
|
|
|
7
7
|
"version": "^1.0.0",
|
|
8
8
|
"language": "typescript",
|
|
9
9
|
"repository": "https://github.com/skyf0xx/hedgehog-core-full-stack-app",
|
|
10
|
-
"selects_when": "The description names
|
|
10
|
+
"selects_when": "The description names server-side logic across most of the app: authorization more expressive than per-object row-level security, background jobs, scheduled work or webhook receivers as the app's primary function, server-rendered or SEO-critical pages beyond an app shell, or a data model whose working set doesn't sensibly fit on a device. Persistent domain data alone is not the signal — a tracker, journal, notebook, or planner whose data fits on the user's device is pwa-app, even with sharing, accounts, or multi-device sync in scope, and even with one or two entities that must be server-authoritative. If the project has both a marketing page and a real app behind it, this is still full-stack-app: the page becomes routes inside apps/web, not a separate project."
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "pwa-app",
|
|
14
|
+
"flag": "--pwa-app",
|
|
15
|
+
"package": "@skyf0xx/hedgehog-core-pwa-app",
|
|
16
|
+
"version": "^1.0.0",
|
|
17
|
+
"language": "typescript",
|
|
18
|
+
"repository": "https://github.com/skyf0xx/hedgehog-core-pwa-app",
|
|
19
|
+
"selects_when": "The description names an app whose data model fits on the user's device and whose reads and writes are the user's own — a tracker, journal, notebook, planner, offline reference, or utility. Offline capability or installability named explicitly is a strong signal. Sharing, collaboration, accounts, and multi-device sync do NOT disqualify a project: Dexie Cloud provides sync, authentication, and server-enforced per-object access control, so a shared list, a family calendar, or a small team's board is still this core. A small number of entities that must be server-authoritative — a points balance, a reward ledger, anything a client must not write to directly — do NOT disqualify a project either: those entities are declared --remote and backed by Supabase (Postgres + RLS + Edge Functions) behind the same repository interface, while the rest of the app stays local-first. What routes a project to full-stack-app is server-side logic across most of the app, not the presence of one or two such entities: authorization beyond row-level policies, background jobs or webhooks as the app's primary function, server-rendered pages, or a working set too large for a device."
|
|
11
20
|
},
|
|
12
21
|
{
|
|
13
22
|
"name": "landing-page",
|
|
@@ -24,7 +33,7 @@
|
|
|
24
33
|
"version": "^1.0.0",
|
|
25
34
|
"language": "typescript",
|
|
26
35
|
"repository": "https://github.com/skyf0xx/hedgehog-core-authored",
|
|
27
|
-
"selects_when": "Neither shipped core fits, but the description names a real artifact a Builder step would produce — just not in either
|
|
36
|
+
"selects_when": "Neither shipped core fits, but the description names a real artifact a Builder step would produce — just not in either shipped core's shape. This core is designed by the planner rather than chosen from a fixed set: hedgehog-planning-intake's Phase 0 elicits the drivers first, then hedgehog-core-design names the system shape, picks the stack, derives the layers, and writes .hedgehog/core.yaml. It carries the same enforcement as a shipped core — ordered layers, scoped file access, verification before completion — but the sequence is designed for this project rather than battle-tested across many."
|
|
28
37
|
}
|
|
29
38
|
]
|
|
30
39
|
}
|
package/src/registry/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Core package registry. One entry per Hedgehog core — full-stack-app,
|
|
2
2
|
// landing-page, authored — naming the npm package that ships its agents,
|
|
3
|
-
// skills, and (for the two
|
|
3
|
+
// skills, and (for the two shipped cores) scaffold, plus the CLI flag
|
|
4
4
|
// `hedgehog init` accepts for it and the prose `planner` reads aloud in
|
|
5
5
|
// Phase 0 to choose one. A fixed table, one entry per core, discovered by
|
|
6
6
|
// name or flag rather than convention.
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hedgehog-planning-intake
|
|
3
|
-
description: Use on any core for first-run planning intake — Phase 0 runs the vendored BMAD-METHOD planning shelf, shared by every core, and Phase 1 (mining `04-prd.md` into intent records plus the Add-ons decision) is full-stack-app's
|
|
3
|
+
description: Use on any core for first-run planning intake — Phase 0 runs the vendored BMAD-METHOD planning shelf, shared by every core, and Phase 1 (mining `04-prd.md` into intent records plus the Add-ons/sync-and-remote-entities decision) is full-stack-app's and pwa-app's shared procedure — identical mechanics, a different decision at step 5/8. Phase 0 also defines compressed intake, the path a user's explicit "just build it" choice takes on full-stack-app, pwa-app, and authored cores: one batched round of questions in place of the shelf, writing the same archive at the same path so Phase 1, `ux-planner`, and the Re-entry pass all keep their documented source. Also use for the Re-entry pass, which mines new scope into additional intents without re-running the shelf, on any core with a module axis to add an intent to (full-stack-app, pwa-app, authored) — landing-page has none, so its own new-scope path runs through `hedgehog-landing-loop`'s Correction Protocol instead. Invoked by the `planner` agent, which decides the path; don't run standalone. landing-page runs this skill's Phase 0 on first run, then mines the same archive through `hedgehog-landing-loop`'s own planning-intake section, that core's counterpart to this skill's Phase 1. An authored core runs this skill's Phase 0, then `hedgehog-core-design`, then this skill's Phase 1 mining against the designed layer sequence. A brownfield adoption (`hedgehog-adopt`) never runs this skill's shelf at all — the drivers BMAD elicits are already settled facts of a repo that already exists.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Hedgehog Planning Intake
|
|
7
7
|
|
|
8
8
|
Turns a person's description of a problem into planning material, by
|
|
9
|
-
running the vendored BMAD-METHOD planning shelf (Phase 0, shared by
|
|
10
|
-
|
|
11
|
-
skill's own Phase 1, into intent records written via
|
|
9
|
+
running the vendored BMAD-METHOD planning shelf (Phase 0, shared by
|
|
10
|
+
every core) and mining its output. On full-stack-app and pwa-app that
|
|
11
|
+
mining is this skill's own Phase 1, into intent records written via
|
|
12
|
+
`hedgehog intent
|
|
12
13
|
add`; on landing-page it's `hedgehog-landing-loop`'s planning-intake
|
|
13
14
|
section, into a subject/audience/job statement. This is the mechanics
|
|
14
15
|
`planner` calls once its Phase 0 core-selection check has picked a core —
|
|
15
16
|
the interpretive judgment (which Feature becomes which intent, Confirm &
|
|
16
17
|
Lock either way) belongs to `planner`; this skill (Phase 0, and Phase 1 on
|
|
17
|
-
full-stack-app) and `hedgehog-landing-loop` (landing-page's
|
|
18
|
-
are the fixed procedures that judgment runs inside.
|
|
18
|
+
full-stack-app and pwa-app) and `hedgehog-landing-loop` (landing-page's
|
|
19
|
+
own mining) are the fixed procedures that judgment runs inside.
|
|
19
20
|
|
|
20
21
|
That shelf run is a **first run**, once per project. When new scope
|
|
21
|
-
enters play later on a core with a module axis (full-stack-app,
|
|
22
|
+
enters play later on a core with a module axis (full-stack-app, pwa-app,
|
|
22
23
|
authored), `planner` runs the **Re-entry pass** at the end of this file
|
|
23
24
|
instead: it reads the existing archive as context and elicits only what's
|
|
24
25
|
new, adding intents to a graph that keeps everything already built.
|
|
@@ -98,7 +99,7 @@ states the source repo, pinned version (`vendor-skills/BMAD/ATTRIBUTION.md` has
|
|
|
98
99
|
the pinned commit), date, which intake mode ran (`full`, below, or
|
|
99
100
|
`compressed`), and which skills ran.
|
|
100
101
|
|
|
101
|
-
### Compressed intake (full-stack-app, authored core)
|
|
102
|
+
### Compressed intake (full-stack-app, pwa-app, authored core)
|
|
102
103
|
|
|
103
104
|
A user who opens with "just build it" — no clarifying questions — is
|
|
104
105
|
asking for something Phase 0's live elicitation can't give them.
|
|
@@ -120,11 +121,13 @@ compressing the elicitation removes the thing the chain audits against.
|
|
|
120
121
|
A "just build it" landing-page request is a conflict to surface, not a
|
|
121
122
|
mode to switch into.
|
|
122
123
|
|
|
123
|
-
**The Add-ons decision
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
**The Add-ons decision (or, on pwa-app, the sync/remote-entities
|
|
125
|
+
decision) is what the batched round is for.** Auth, Queue, and Mobile
|
|
126
|
+
(full-stack-app) or sync and remote entities (pwa-app) must each be
|
|
127
|
+
*answered*: inferred from a concrete
|
|
128
|
+
trigger in the user's brief, or asked directly in that one round.
|
|
129
|
+
Compressed intake compresses BMAD's elicitation, never `planner`'s gate;
|
|
130
|
+
a boolean left as a guess is the same error here as on a full run.
|
|
128
131
|
|
|
129
132
|
Write the manifest and the PRD always, and the experience spec where the
|
|
130
133
|
brief gives it something to say — at the same path and in the same
|
|
@@ -174,11 +177,12 @@ drivers, and that's the user's call to accept there.
|
|
|
174
177
|
Nothing in `hedgehog-loop`'s day-to-day operation, `hedgehog-bootstrap`,
|
|
175
178
|
or `reviewer` reads this folder live — `planner` reads it exactly once,
|
|
176
179
|
right after the shelf completes, to mine it (this skill's Phase 1 below
|
|
177
|
-
on full-stack-app; `hedgehog-landing-loop`'s planning-intake
|
|
180
|
+
on full-stack-app and pwa-app; `hedgehog-landing-loop`'s planning-intake
|
|
181
|
+
section on
|
|
178
182
|
landing-page). After that it's historical record only, the same
|
|
179
183
|
relationship the commit log has to a merged PR.
|
|
180
184
|
|
|
181
|
-
## Phase 1 — Mining (full-stack-app
|
|
185
|
+
## Phase 1 — Mining (full-stack-app, pwa-app)
|
|
182
186
|
|
|
183
187
|
landing-page's counterpart to this Phase 1 is
|
|
184
188
|
`hedgehog-landing-loop`'s own planning-intake section, run once Phase 0
|
|
@@ -211,7 +215,8 @@ Procedure:
|
|
|
211
215
|
description across the two if it names both the capability and the
|
|
212
216
|
result; otherwise the same sentence can serve both).
|
|
213
217
|
|
|
214
|
-
On a module-axis core (`full-stack-app`, and any authored
|
|
218
|
+
On a module-axis core (`full-stack-app`, `pwa-app`, and any authored
|
|
219
|
+
core whose
|
|
215
220
|
layers scope by `{module}`), **name the id plural** — `tasks`, not
|
|
216
221
|
`task`; `order-items`, not `order-item`. The id is substituted as
|
|
217
222
|
`{module}` into every layer's scope glob and verify command, and the
|
|
@@ -238,8 +243,10 @@ Procedure:
|
|
|
238
243
|
holding the foreign key depends on the intent for the entity it
|
|
239
244
|
references. A relationship entirely inside one Feature's entities
|
|
240
245
|
produces no row — it's already the same intent.
|
|
241
|
-
5. **Run
|
|
242
|
-
|
|
246
|
+
5. **Run this core's Add-ons-equivalent decision** (`planner`'s own
|
|
247
|
+
judgment call): full-stack-app's "The Add-ons decision" (Auth, Queue,
|
|
248
|
+
Mobile), or pwa-app's "The sync/remote-entities decision" (sync,
|
|
249
|
+
remote entities) — see that agent.
|
|
243
250
|
6. **Run Confirm & Lock** (below) before writing anything.
|
|
244
251
|
7. **Write each intent via `hedgehog intent add`** — one invocation per
|
|
245
252
|
Feature: `--acceptance` per row from step 2, `--rule` per row from step
|
|
@@ -247,7 +254,7 @@ Procedure:
|
|
|
247
254
|
<path.json>` batch matching the same shape (`{ id, goal, outcome,
|
|
248
255
|
rules, acceptance, depends_on, priority }`). This is Phase 1's only
|
|
249
256
|
write to the build graph.
|
|
250
|
-
8. **Write `.hedgehog/addons.yaml`** with the
|
|
257
|
+
8. **Write `.hedgehog/addons.yaml`** with the decision from step 5.
|
|
251
258
|
9. **Fill root `CLAUDE.md`'s `{{PROJECT_NAME}}` and `{{PROJECT_SUMMARY}}`
|
|
252
259
|
placeholders**, first run only, then delete the installer's HTML
|
|
253
260
|
comment block at the top of that file. Leave every other line
|
|
@@ -266,8 +273,9 @@ stops being true, so it's a hard stop, not a recap in passing.
|
|
|
266
273
|
|
|
267
274
|
- Each intent about to be added: `id`, `goal`, `outcome`, its
|
|
268
275
|
`requirements` (rule/acceptance), and its `depends_on` list.
|
|
269
|
-
-
|
|
270
|
-
off
|
|
276
|
+
- This core's Add-ons-equivalent decision, each boolean explicitly on or
|
|
277
|
+
off with the one-line reason (Auth / Queue / Mobile on full-stack-app;
|
|
278
|
+
sync / remote entities on pwa-app).
|
|
271
279
|
- Which intake mode ran, and on a full run which BMAD skills ran — or,
|
|
272
280
|
on a compressed run, what the batched round asked and what was inferred
|
|
273
281
|
from the brief without asking. Either way, where the output lives
|
|
@@ -276,7 +284,7 @@ stops being true, so it's a hard stop, not a recap in passing.
|
|
|
276
284
|
Then state plainly what happens on confirmation, before it happens:
|
|
277
285
|
|
|
278
286
|
> This writes each intent above via `hedgehog intent add` and the
|
|
279
|
-
>
|
|
287
|
+
> decision above to `.hedgehog/addons.yaml`, then shows the compiled
|
|
280
288
|
> graph with `hedgehog status`. Phase A build (schema first) starts on
|
|
281
289
|
> the first ready task once that closes. Anything wrong or missing — say
|
|
282
290
|
> so now; it's a normal edit before this point, and a Correction Protocol
|
|
@@ -288,7 +296,7 @@ the confirmation holds. Once confirmed, after every `hedgehog intent add`
|
|
|
288
296
|
call lands, run `hedgehog status` and show it in full as the graph's
|
|
289
297
|
confirmation view.
|
|
290
298
|
|
|
291
|
-
## Re-entry pass — new scope on an existing project (full-stack-app, authored core)
|
|
299
|
+
## Re-entry pass — new scope on an existing project (full-stack-app, pwa-app, authored core)
|
|
292
300
|
|
|
293
301
|
Runs when `planner`'s Workflow step 2 finds intents already in the graph,
|
|
294
302
|
on a core with a module axis to add an intent to: new scope entering play
|
|
@@ -321,8 +329,8 @@ their commits.
|
|
|
321
329
|
3. **Elicit only what's new.** A short, scoped set of questions — not a
|
|
322
330
|
full interview:
|
|
323
331
|
- What is the new scope, in the project's own vocabulary?
|
|
324
|
-
- Which entities/tables does it introduce? On full-stack-app
|
|
325
|
-
table is its own module, same rule as Phase 1.
|
|
332
|
+
- Which entities/tables does it introduce? On full-stack-app and
|
|
333
|
+
pwa-app each table is its own module, same rule as Phase 1.
|
|
326
334
|
- What does it depend on that already exists? Each answer becomes a
|
|
327
335
|
`--depends-on` onto an existing intent.
|
|
328
336
|
- What has to be true for it to be done? Each answer becomes an
|
|
@@ -334,10 +342,13 @@ their commits.
|
|
|
334
342
|
If the answers reveal this isn't new scope at all but a change to
|
|
335
343
|
something already built, stop: that's the Correction Protocol, not an
|
|
336
344
|
extension.
|
|
337
|
-
4. **Check whether any
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
345
|
+
4. **Check whether any boolean trigger actually changed**
|
|
346
|
+
(full-stack-app's Add-ons, or pwa-app's sync/remote-entities). Usually
|
|
347
|
+
none has. Only if the new scope genuinely introduces one — the
|
|
348
|
+
first accounts in a project that had none, the first long-running job,
|
|
349
|
+
the first shared device on a pwa-app project, the first entity that
|
|
350
|
+
must be server-authoritative —
|
|
351
|
+
edit `.hedgehog/addons.yaml`, and say plainly that turning a boolean on
|
|
341
352
|
after bootstrap needs its Bootstrap step run before anything depends on
|
|
342
353
|
it. Never rewrite root `CLAUDE.md`'s `{{PROJECT_NAME}}`/
|
|
343
354
|
`{{PROJECT_SUMMARY}}` placeholders here; they describe the project,
|