@skyf0xx/hedgehog 3.0.6 → 3.0.8
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 +1 -1
- package/package.json +1 -1
- package/src/agents/landing-headline-writer.md +2 -2
- package/src/agents/landing-sequencer.md +2 -1
- package/src/agents/landing-strategist.md +7 -2
- package/src/agents/landing-systems.md +2 -1
- package/src/agents/tweaker.md +4 -0
- package/src/skills/hedgehog-core-design/SKILL.md +100 -16
- package/src/skills/hedgehog-core-design/blueprints/bot-agent.md +35 -0
- package/src/skills/hedgehog-core-design/blueprints/browser-extension.md +62 -0
- package/src/skills/hedgehog-core-design/blueprints/cli.md +26 -0
- package/src/skills/hedgehog-core-design/blueprints/compiler-language-tool.md +36 -0
- package/src/skills/hedgehog-core-design/blueprints/data-pipeline.md +36 -0
- package/src/skills/hedgehog-core-design/blueprints/desktop-app.md +34 -0
- package/src/skills/hedgehog-core-design/blueprints/game.md +35 -0
- package/src/skills/hedgehog-core-design/blueprints/infra-deploy-tool.md +34 -0
- package/src/skills/hedgehog-core-design/blueprints/library-sdk.md +31 -0
- package/src/skills/hedgehog-landing-loop/SKILL.md +22 -2
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ Artifact
|
|
|
88
88
|
|
|
89
89
|
### Anything else
|
|
90
90
|
|
|
91
|
-
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.
|
|
91
|
+
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](src/skills/hedgehog-core-design/blueprints) for the system's shape where one exists.
|
|
92
92
|
|
|
93
93
|
Run `init` with no core flag: planning intake names the system shape, picks
|
|
94
94
|
the stack, derives the layers, and locks them to `.hedgehog/core.yaml`,
|
package/package.json
CHANGED
|
@@ -61,8 +61,8 @@ against its own archetype skill.
|
|
|
61
61
|
without confirmation risks the same expensive unwind the strategist's
|
|
62
62
|
Confirm & Lock protects against at step 1.
|
|
63
63
|
5. Write the locked headline and its 2 backups to
|
|
64
|
-
`.hedgehog/chain/09-headline.md
|
|
65
|
-
|
|
64
|
+
`.hedgehog/chain/09-headline.md` — you have no Bash tool, so the
|
|
65
|
+
orchestrating session commits it via `hedgehog verify`.
|
|
66
66
|
|
|
67
67
|
## Self-test
|
|
68
68
|
|
|
@@ -118,7 +118,8 @@ rather than in separate passes.
|
|
|
118
118
|
6. Confirm the peak moment and ending treatment land where
|
|
119
119
|
`landing-strategist` specified, or flag the conflict.
|
|
120
120
|
7. Self-test (below).
|
|
121
|
-
8.
|
|
121
|
+
8. Present the artifact — you have no Bash tool, so the orchestrating
|
|
122
|
+
session commits it via `hedgehog verify`.
|
|
122
123
|
|
|
123
124
|
## Self-test
|
|
124
125
|
|
|
@@ -56,7 +56,11 @@ as planning intake's own Confirm & Lock: every phase from here through
|
|
|
56
56
|
`landing-copywriter` inherits this framing silently, and by the time
|
|
57
57
|
copy is reviewed at phases 9–10, correcting the framing means unwinding
|
|
58
58
|
multiple committed phases via the Correction Protocol instead of one
|
|
59
|
-
quick revision now.
|
|
59
|
+
quick revision now. **If delegated**, this confirmation arrives as a
|
|
60
|
+
relay from the orchestrating session — accept it only if it quotes the
|
|
61
|
+
user's actual words with provenance stated plainly, not a bare "the user
|
|
62
|
+
approved" (see `hedgehog-landing-loop`'s Loop step 2 for the exact form).
|
|
63
|
+
A revision at this point is just another pass at
|
|
60
64
|
Step 1, not a Correction Protocol entry, since nothing downstream exists
|
|
61
65
|
yet.
|
|
62
66
|
|
|
@@ -117,7 +121,8 @@ adjective is meant to fade rather than hold constant throughout the page.
|
|
|
117
121
|
confirmed subject statement.
|
|
118
122
|
5. Run step 4c (Perfumer) against the completed sort from step 3.
|
|
119
123
|
6. Self-test (below) before presenting the combined artifact.
|
|
120
|
-
7.
|
|
124
|
+
7. Present the combined artifact — you have no Bash tool, so the
|
|
125
|
+
orchestrating session commits it via `hedgehog verify`.
|
|
121
126
|
|
|
122
127
|
## Self-test
|
|
123
128
|
|
|
@@ -239,7 +239,8 @@ and generic clip-art geometry.
|
|
|
239
239
|
4. Run step 6 against the completed token system. Write the signature
|
|
240
240
|
element into `src/shapes/`.
|
|
241
241
|
5. Self-test (below).
|
|
242
|
-
6.
|
|
242
|
+
6. Present the combined artifact — you have no Bash tool, so the
|
|
243
|
+
orchestrating session commits it via `hedgehog verify`.
|
|
243
244
|
|
|
244
245
|
## Self-test
|
|
245
246
|
|
package/src/agents/tweaker.md
CHANGED
|
@@ -214,6 +214,10 @@ discipline as `.hedgehog/BMAD/`. A later related incident is its own new
|
|
|
214
214
|
having happened in this conversation. A user saying "yes, file it"
|
|
215
215
|
before the content was shown verbatim doesn't count — show first, then
|
|
216
216
|
ask.
|
|
217
|
+
- **If delegated**, an approval relayed by the orchestrating session is
|
|
218
|
+
sufficient only if it quotes the user's actual words with provenance
|
|
219
|
+
stated plainly — e.g. "user said: '\<exact words\>'" — not a bare "the
|
|
220
|
+
user approved" or "approved via UI."
|
|
217
221
|
- File one issue per distinct real pattern or feedback item, not one per
|
|
218
222
|
log entry or remark, and not capped at a single issue per source — a
|
|
219
223
|
log (or a round of feedback) with several unrelated genuine points gets
|
|
@@ -61,7 +61,12 @@ the design work onto the person who came here to avoid doing it.
|
|
|
61
61
|
Pick one default per system shape, the same way the shipped cores commit
|
|
62
62
|
to one choice per row rather than a menu (`hedgehog-bootstrap`'s stack
|
|
63
63
|
table). Substitute off a default only for a concrete, named constraint
|
|
64
|
-
read from `.hedgehog/BMAD/` — never a general preference for variety
|
|
64
|
+
read from `.hedgehog/BMAD/` — never a general preference for variety.
|
|
65
|
+
Prefer an opinionated framework over a bare library wherever the shape
|
|
66
|
+
has one (a web/CLI/RPC framework that fixes where things live, the way
|
|
67
|
+
NestJS does for `full-stack-app`) — an opinionated default is a guardrail
|
|
68
|
+
this discipline doesn't have to write down, and is worth more than the
|
|
69
|
+
popular thin alternative:
|
|
65
70
|
|
|
66
71
|
| System shape | Default stack | Substitute when |
|
|
67
72
|
|---|---|---|
|
|
@@ -72,7 +77,7 @@ read from `.hedgehog/BMAD/` — never a general preference for variety:
|
|
|
72
77
|
| Desktop app | TypeScript + Electron, Vitest + Playwright, pnpm | native platform integration is a stated hard requirement (macOS/Windows-only, deep OS API use) → Swift/AppKit or C#/WinUI, per platform, named explicitly |
|
|
73
78
|
| Compiler / language tool | Rust, `cargo test`, Cargo | the brief is explicitly about fast iteration over raw performance, or targets a JS/TS-only toolchain (a Babel/ESLint plugin) → TypeScript, Vitest, pnpm |
|
|
74
79
|
| Bot / agent | TypeScript, Vitest, pnpm | the brief calls for heavy ML/data-science library use → Python, pytest, uv |
|
|
75
|
-
| Game | TypeScript +
|
|
80
|
+
| Game | TypeScript + PixiJS (2D) or Three.js (3D), Vitest, pnpm — read the dimensionality off the brief; an engine the brief names outright wins over both | a native/console target is explicit → the engine the brief names, per that engine's own language (see the caveat below) |
|
|
76
81
|
| Infra / deploy tool | Go, `go test`, Go modules | the tool is a thin wrapper generating config/manifests with no systems-level need → TypeScript, Vitest, pnpm |
|
|
77
82
|
|
|
78
83
|
A shape not on this table is rare enough that no default has been
|
|
@@ -82,20 +87,72 @@ target, the language the brief's own examples or comparables are
|
|
|
82
87
|
written in) and name the result as a judgment call, not a table lookup,
|
|
83
88
|
in `core-design.md`'s rationale.
|
|
84
89
|
|
|
90
|
+
Where a substitution lands on a stack whose primary artifacts are binary
|
|
91
|
+
(engine scenes and prefabs, visual-editor projects, compiled design
|
|
92
|
+
files), say so at Confirm & Lock. Scope globs and `verify` commands still
|
|
93
|
+
hold on that stack's text sources, but a layer whose real output is a
|
|
94
|
+
binary file can't be diffed or meaningfully gated, so the enforcement is
|
|
95
|
+
partial in a way the text-source defaults aren't. That's a reason to
|
|
96
|
+
prefer a text-source stack where the brief leaves it open, and a fact the
|
|
97
|
+
user should have before confirming where it doesn't.
|
|
98
|
+
|
|
85
99
|
Record the choice as one line — language, package manager, the named
|
|
86
|
-
framework(s), test runner — before moving to Step 3
|
|
87
|
-
|
|
100
|
+
framework(s), test runner — before moving to Step 3. Alongside it, record
|
|
101
|
+
a one-line decision for each of these concerns, whichever apply to the
|
|
102
|
+
shape (a browser extension has no DI story; a data pipeline has no
|
|
103
|
+
routing layer) — each is a place an authored core silently forks into
|
|
104
|
+
per-project convention if left unstated, the way `full-stack-app` never
|
|
105
|
+
has to think about because NestJS already decided:
|
|
106
|
+
|
|
107
|
+
- **Composition** — how one part of the system gets a dependency it
|
|
108
|
+
doesn't construct itself (a DI container, explicit constructor passing,
|
|
109
|
+
a module registry).
|
|
110
|
+
- **Error model** — how a failure crosses a layer boundary (typed
|
|
111
|
+
exceptions, a `Result`/`Either` return, error codes).
|
|
112
|
+
- **Config and secrets** — where runtime configuration is read from and
|
|
113
|
+
validated (env vars through a typed schema, a config file, flags).
|
|
114
|
+
- **Entrypoint layout** — what file the runtime starts from and how it
|
|
115
|
+
wires the layers together.
|
|
116
|
+
|
|
117
|
+
Every layer's `scope` and `verify` in Step 3 draws from this record.
|
|
88
118
|
|
|
89
119
|
## Step 3 — derive the layers
|
|
90
120
|
|
|
91
121
|
Read `.hedgehog/BMAD/` for what the system actually does, then decide the
|
|
92
122
|
layers it builds in. A layer earns its place by owning a distinct
|
|
93
123
|
artifact that can be verified on its own. Order by dependency first (a
|
|
94
|
-
layer that another layer imports comes first)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
124
|
+
layer that another layer imports comes first), by contract second (a
|
|
125
|
+
layer that pins an external interface — a schema, a wire format, a public
|
|
126
|
+
API surface — comes before the layers that build against it, the way
|
|
127
|
+
`full-stack-app` puts `schema` before `contract` before everything else),
|
|
128
|
+
and by risk third (where two layers are still tied, build the one that
|
|
129
|
+
would invalidate the other if it went wrong first).
|
|
130
|
+
|
|
131
|
+
Start from the blueprint for the chosen system shape — a starting
|
|
132
|
+
sequence, not a fixed one. Each blueprint names where it's safe to add,
|
|
133
|
+
merge, or drop a layer for the project at hand, and the one boundary that
|
|
134
|
+
has to hold whatever else changes; treat those adaptation points as
|
|
135
|
+
expected, not as exceptions. Record which blueprint was used and what
|
|
136
|
+
changed from it in `core-design.md`'s rationale (Step 6).
|
|
137
|
+
|
|
138
|
+
| System shape | Blueprint |
|
|
139
|
+
|---|---|
|
|
140
|
+
| CLI | [blueprints/cli.md](blueprints/cli.md) |
|
|
141
|
+
| Library / SDK | [blueprints/library-sdk.md](blueprints/library-sdk.md) |
|
|
142
|
+
| Data pipeline | [blueprints/data-pipeline.md](blueprints/data-pipeline.md) |
|
|
143
|
+
| Browser extension | [blueprints/browser-extension.md](blueprints/browser-extension.md) |
|
|
144
|
+
| Desktop app | [blueprints/desktop-app.md](blueprints/desktop-app.md) |
|
|
145
|
+
| Compiler / language tool | [blueprints/compiler-language-tool.md](blueprints/compiler-language-tool.md) |
|
|
146
|
+
| Bot / agent | [blueprints/bot-agent.md](blueprints/bot-agent.md) |
|
|
147
|
+
| Game | [blueprints/game.md](blueprints/game.md) |
|
|
148
|
+
| Infra / deploy tool | [blueprints/infra-deploy-tool.md](blueprints/infra-deploy-tool.md) |
|
|
149
|
+
|
|
150
|
+
A shape off this table gets no starting sequence — derive layers directly
|
|
151
|
+
from this step's rules and the BMAD brief, and name that in
|
|
152
|
+
`core-design.md` as a judgment call, the same as an off-table stack.
|
|
153
|
+
|
|
154
|
+
Three rules with teeth, on every blueprint and every derived sequence
|
|
155
|
+
alike:
|
|
99
156
|
|
|
100
157
|
- **A layer with no executable verification is not a layer.** Fold it
|
|
101
158
|
into its neighbour or drop it. `verify: manually inspect` is not a
|
|
@@ -110,7 +167,9 @@ Three rules with teeth:
|
|
|
110
167
|
|
|
111
168
|
Four to seven layers is the usual range. Fewer than three means the
|
|
112
169
|
project probably wanted a shipped core or no core at all; more than eight
|
|
113
|
-
means several layers are one layer with internal steps.
|
|
170
|
+
means several layers are one layer with internal steps. This list isn't
|
|
171
|
+
final until Step 4 — a module axis can still add a cross-cutting layer to
|
|
172
|
+
it.
|
|
114
173
|
|
|
115
174
|
## Step 4 — decide the module axis
|
|
116
175
|
|
|
@@ -136,6 +195,23 @@ intent A's task may write intent B's files and the scope enforcement that
|
|
|
136
195
|
justifies authoring a core at all disappears. Check every glob before
|
|
137
196
|
writing the file.
|
|
138
197
|
|
|
198
|
+
On a module axis, also **ask explicitly whether the stack implies
|
|
199
|
+
cross-cutting infrastructure no single module should own** — a shared
|
|
200
|
+
background script coordinating state across every module's tabs (a
|
|
201
|
+
browser extension), a shared event bus, global app state. Every layer in
|
|
202
|
+
Step 3 instantiates once per intent; this is the thing that doesn't fit
|
|
203
|
+
that shape, and left undesigned it either gets deferred with no owner or
|
|
204
|
+
bolted onto whichever module's layer needs it first, quietly widening
|
|
205
|
+
that layer's scope past what it was designed to own.
|
|
206
|
+
|
|
207
|
+
If yes, add it to Step 3's layer sequence as its own layer, before the
|
|
208
|
+
file is written — a layer whose `scope` is a fixed path with no
|
|
209
|
+
`{module}` placeholder, the same way `full-stack-app`'s own `schema` and
|
|
210
|
+
`contract` layers run once against a fixed scope on an otherwise
|
|
211
|
+
module-axis core. Name it for what it owns (e.g. `background-infra`),
|
|
212
|
+
give it its own `verify` command, and record in `core-design.md` why no
|
|
213
|
+
single module was made to own it.
|
|
214
|
+
|
|
139
215
|
## Step 5 — write `.hedgehog/core.yaml`
|
|
140
216
|
|
|
141
217
|
The loader parses `id` plus a `layers` list of flat maps. Every layer
|
|
@@ -178,6 +254,12 @@ if missed:
|
|
|
178
254
|
belongs in `.hedgehog/core-design.md`.
|
|
179
255
|
- **`depends_on` names one layer**, and the chain must be acyclic. The
|
|
180
256
|
compiler walks it directly into `dependencies` rows.
|
|
257
|
+
- **`verify` must prove the layer's own claim, not just exit clean.** A
|
|
258
|
+
command that runs but asserts nothing (`tsc --noEmit` alone on a layer
|
|
259
|
+
whose job is behavior, a `test -s` on a file nothing checks the content
|
|
260
|
+
of) passes on an empty implementation. Pair typecheck/build commands
|
|
261
|
+
with a test command that exercises the layer's actual output whenever
|
|
262
|
+
the layer produces behavior, not just types.
|
|
181
263
|
|
|
182
264
|
Verify the file loads before showing it back, by calling the loader
|
|
183
265
|
directly:
|
|
@@ -196,12 +278,14 @@ forward.
|
|
|
196
278
|
|
|
197
279
|
The rationale the engine doesn't read but the project needs: the system
|
|
198
280
|
shape and why, the stack and why (the default it came from, or the named
|
|
199
|
-
constraint that justified a substitution), the
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
281
|
+
constraint that justified a substitution), the composition/error/config/
|
|
282
|
+
entrypoint decisions from Step 2, the layer blueprint used and what
|
|
283
|
+
changed from it (or, off-table, that layers were derived directly and
|
|
284
|
+
why), the layers with a line each on what they own and why they sit where
|
|
285
|
+
they do, the module-axis decision, and anything left unresolved. Written
|
|
286
|
+
once, archival, never edited after — the same stance `.hedgehog/BMAD/`
|
|
287
|
+
takes. Later changes to the architecture are Correction Protocol entries
|
|
288
|
+
in the commit log, not edits here.
|
|
205
289
|
|
|
206
290
|
## Confirm & Lock
|
|
207
291
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Bot / agent blueprint
|
|
2
|
+
|
|
3
|
+
A starting layer sequence for `hedgehog-core-design` Step 3 on the
|
|
4
|
+
bot/agent system shape. Adapt it for the project at hand — the
|
|
5
|
+
adaptation points below are expected, not exceptions — and record what
|
|
6
|
+
changed in `core-design.md`'s rationale.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
contract — the typed input/output shape of every capability, and the intent type policy decides over
|
|
10
|
+
tools — each capability's implementation, independently callable and testable with no model in the loop
|
|
11
|
+
policy — the decision logic: which tool a given input calls, knowing nothing about the delivery surface
|
|
12
|
+
transport — the platform integration (webhook, socket, polling loop) carrying input in and results back out
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Adaptation points
|
|
16
|
+
|
|
17
|
+
- Merge `transport` into `policy` when the agent runs as a single-process
|
|
18
|
+
script with no external trigger surface (a CLI-invoked agent, a batch
|
|
19
|
+
job) — there's no separate integration to isolate.
|
|
20
|
+
- Split `tools` per capability (`tools/{module}`) when the agent's
|
|
21
|
+
capabilities hit independent external systems with their own auth and
|
|
22
|
+
failure modes; keep one layer when they share a backend.
|
|
23
|
+
- Add a `memory` layer between `tools` and `policy`, depending on
|
|
24
|
+
`contract`, when the agent persists state across runs (conversation
|
|
25
|
+
history, a vector store) — keep it out of `policy` so the decision logic
|
|
26
|
+
stays testable against a fake memory.
|
|
27
|
+
|
|
28
|
+
## Boundary that must hold
|
|
29
|
+
|
|
30
|
+
`policy` calls tools only through the types `contract` defines — never by
|
|
31
|
+
constructing a provider-specific call inline — and never imports
|
|
32
|
+
`transport`. This is what makes the decision logic testable without
|
|
33
|
+
standing up the real delivery surface or a live model: a policy layer
|
|
34
|
+
that reaches into a specific SDK can only be tested against that SDK, and
|
|
35
|
+
that is the layer whose behavior most needs cheap tests.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Browser extension blueprint
|
|
2
|
+
|
|
3
|
+
A starting layer sequence for `hedgehog-core-design` Step 3 on the
|
|
4
|
+
browser extension system shape. Adapt it for the project at hand — the
|
|
5
|
+
adaptation points below are expected, not exceptions — and record what
|
|
6
|
+
changed in `core-design.md`'s rationale.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
messaging — the typed message contract between background/content-script/popup
|
|
10
|
+
background — the service-worker-side logic (state, alarms, cross-tab coordination)
|
|
11
|
+
content — page-context logic (DOM reads/writes, page-side event listeners)
|
|
12
|
+
popup — the extension UI, consumes background/content only through messaging
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Adaptation points
|
|
16
|
+
|
|
17
|
+
- Drop `popup` entirely for an extension with no browser action UI.
|
|
18
|
+
- Merge `content` into `background` when the extension never injects into
|
|
19
|
+
page context (a pure background-worker extension).
|
|
20
|
+
- On a module axis, `background` is often shared rather than
|
|
21
|
+
one-per-module (a single service worker coordinating state across every
|
|
22
|
+
module's tabs) — the cross-cutting infrastructure Step 4 asks about.
|
|
23
|
+
Give it its own fixed-scope layer there.
|
|
24
|
+
|
|
25
|
+
## Boundary that must hold
|
|
26
|
+
|
|
27
|
+
`popup` never imports from `background` or `content` directly — every
|
|
28
|
+
cross-context call goes through `messaging`, because a WebExtension's
|
|
29
|
+
contexts are separate JS runtimes and a direct import silently fails at
|
|
30
|
+
runtime rather than at build time.
|
|
31
|
+
|
|
32
|
+
## WXT entrypoint naming (must decide up front, not discover mid-build)
|
|
33
|
+
|
|
34
|
+
WXT derives an entrypoint's manifest name by splitting its `entrypoints/`
|
|
35
|
+
folder or file name at the **first** `.`. Two entrypoints that derive the
|
|
36
|
+
same name collide — observed failure modes include a build-time error
|
|
37
|
+
("Multiple entrypoints with the same name detected") and, in at least one
|
|
38
|
+
case, a colliding entrypoint silently missing from the built manifest
|
|
39
|
+
(`.output/*/manifest.json`) with no error at all. Don't assume which one
|
|
40
|
+
fires for a given WXT version or collision shape; treat any collision as
|
|
41
|
+
unsafe rather than relying on the build to always catch it.
|
|
42
|
+
|
|
43
|
+
Decide the naming convention in this step, per module, before any layer
|
|
44
|
+
is built against it — not after the first collision is hit:
|
|
45
|
+
|
|
46
|
+
- **Every entrypoint with more than one surface lives in its own folder**,
|
|
47
|
+
`entrypoints/{module}/index.ts`, never a flat `entrypoints/{module}.ts`
|
|
48
|
+
— a folder has no `.`-split ambiguity to collide on.
|
|
49
|
+
- **Colocated tests go inside that same folder** as a sibling
|
|
50
|
+
(`entrypoints/{module}/index.test.ts`), never as a flat
|
|
51
|
+
`entrypoints/{module}.test.ts` next to a flat entrypoint file — that's
|
|
52
|
+
the same name-collision shape described above.
|
|
53
|
+
- **A module with two entrypoint surfaces** (e.g. popup and content) gets
|
|
54
|
+
two folder names that don't share a prefix before the first `.` —
|
|
55
|
+
`entrypoints/{module}-popup/` and `entrypoints/{module}-content/`, never
|
|
56
|
+
a dotted variant like `entrypoints/{module}.content/`.
|
|
57
|
+
|
|
58
|
+
Add a cheap, generic guard to the entrypoint layer's `verify` command
|
|
59
|
+
regardless of the convention chosen: after `pnpm wxt build`, check the
|
|
60
|
+
built manifest's entrypoint count against the expected count (e.g. `node
|
|
61
|
+
-e "..."` reading `.output/*/manifest.json`) so a silent drop fails
|
|
62
|
+
`verify` instead of surfacing later as a missing feature.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# CLI blueprint
|
|
2
|
+
|
|
3
|
+
A starting layer sequence for `hedgehog-core-design` Step 3 on the CLI
|
|
4
|
+
system shape. Adapt it for the project at hand — the adaptation points
|
|
5
|
+
below are expected, not exceptions — and record what changed in
|
|
6
|
+
`core-design.md`'s rationale.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
command — argument/flag parsing and dispatch only, one file per subcommand
|
|
10
|
+
domain — the logic the command triggers, no knowledge of argv or stdout
|
|
11
|
+
io-adapter — anything crossing a real boundary: filesystem, network, a wrapped subprocess
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Adaptation points
|
|
15
|
+
|
|
16
|
+
- Merge `io-adapter` into `domain` when the tool touches only the local
|
|
17
|
+
filesystem through the language's standard library — no separate
|
|
18
|
+
adapter earns its place.
|
|
19
|
+
- Add a `config` layer before `command` when the tool reads a
|
|
20
|
+
project-level config file in addition to flags.
|
|
21
|
+
|
|
22
|
+
## Boundary that must hold
|
|
23
|
+
|
|
24
|
+
Never let `command` reach past `domain` into `io-adapter` directly — that
|
|
25
|
+
collapses the one boundary that makes `domain` testable without a real
|
|
26
|
+
filesystem or network.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Compiler / language tool blueprint
|
|
2
|
+
|
|
3
|
+
A starting layer sequence for `hedgehog-core-design` Step 3 on the
|
|
4
|
+
compiler/language tool system shape. Adapt it for the project at hand —
|
|
5
|
+
the adaptation points below are expected, not exceptions — and record
|
|
6
|
+
what changed in `core-design.md`'s rationale.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
ast — the node types, spans, and the diagnostic type every later layer reports through
|
|
10
|
+
lexer — source text to tokens
|
|
11
|
+
parser — tokens to ast, recovering from errors rather than aborting on the first one
|
|
12
|
+
analysis — name resolution, type checking, lints: ast in, diagnostics out
|
|
13
|
+
emit — the output artifact: generated code, a formatted document, a transformed ast
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Adaptation points
|
|
17
|
+
|
|
18
|
+
- Merge `lexer` into `parser` when the grammar is simple enough that the
|
|
19
|
+
tokenizer is a handful of functions (a config language, a template
|
|
20
|
+
syntax) — a separate layer buys nothing.
|
|
21
|
+
- Drop `emit` for a pure analysis tool (a linter, a type checker) whose
|
|
22
|
+
output is diagnostics rather than an artifact.
|
|
23
|
+
- Drop `analysis` for a pure syntactic tool (a formatter, a
|
|
24
|
+
syntax-highlighter grammar) that never resolves names or types.
|
|
25
|
+
- Add a `driver` layer after `emit` when the tool has a real CLI or
|
|
26
|
+
watch-mode surface — it owns argv, file discovery, and diagnostic
|
|
27
|
+
rendering, keeping the pipeline layers free of both.
|
|
28
|
+
|
|
29
|
+
## Boundary that must hold
|
|
30
|
+
|
|
31
|
+
`ast` comes first and everything depends on it, because the node types
|
|
32
|
+
and the span/diagnostic representation are the contract every other layer
|
|
33
|
+
speaks. Layers report errors as diagnostics carrying spans — never by
|
|
34
|
+
printing, and never by aborting on the first failure. A tool that stops
|
|
35
|
+
at the first error can't be used in an editor, and retrofitting error
|
|
36
|
+
recovery after `parser` is written is a rewrite of `parser`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Data pipeline blueprint
|
|
2
|
+
|
|
3
|
+
A starting layer sequence for `hedgehog-core-design` Step 3 on the data
|
|
4
|
+
pipeline system shape. Adapt it for the project at hand — the adaptation
|
|
5
|
+
points below are expected, not exceptions — and record what changed in
|
|
6
|
+
`core-design.md`'s rationale.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
schema — the typed shape of every record crossing a stage boundary, and the validation that enforces it
|
|
10
|
+
extract — pulling raw records from each source, with no reshaping beyond what the source forces
|
|
11
|
+
transform — the business logic: cleaning, joining, deriving, aggregating, all pure and source-agnostic
|
|
12
|
+
load — writing results to the destination, plus whatever idempotency/upsert key the destination needs
|
|
13
|
+
schedule — the orchestration wiring: what runs when, retries, backfill entry points
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Adaptation points
|
|
17
|
+
|
|
18
|
+
- Merge `schedule` into `load` when the pipeline is invoked externally
|
|
19
|
+
(cron calling a script, an orchestrator defined outside this repo) —
|
|
20
|
+
there's no orchestration surface here to build.
|
|
21
|
+
- Split `extract` per source (`extract/{module}`) when the pipeline pulls
|
|
22
|
+
from several genuinely different systems with independent failure modes
|
|
23
|
+
and auth; keep one `extract` layer for a single source.
|
|
24
|
+
- Merge `schema` into `extract` when there is one source and one
|
|
25
|
+
destination and the record shape is small enough to declare in a single
|
|
26
|
+
file — the types still exist and are still validated, they just don't
|
|
27
|
+
need a layer of their own.
|
|
28
|
+
|
|
29
|
+
## Boundary that must hold
|
|
30
|
+
|
|
31
|
+
`transform` never reads from a source or writes to a destination — it
|
|
32
|
+
takes validated records in and returns records out. This is what lets the
|
|
33
|
+
business logic be tested on fixtures without network, credentials, or a
|
|
34
|
+
warehouse, and it's the boundary that decays first under deadline
|
|
35
|
+
pressure. A transform that "just needs one lookup" from the source is the
|
|
36
|
+
signal to widen `extract`'s output, not to reach across.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Desktop app blueprint
|
|
2
|
+
|
|
3
|
+
A starting layer sequence for `hedgehog-core-design` Step 3 on the
|
|
4
|
+
desktop app system shape. Adapt it for the project at hand — the
|
|
5
|
+
adaptation points below are expected, not exceptions — and record what
|
|
6
|
+
changed in `core-design.md`'s rationale.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
ipc — the typed contract between the privileged process and the UI process
|
|
10
|
+
main — privileged-process logic: filesystem, OS integration, windows, auto-update, native menus
|
|
11
|
+
domain — the app's own logic, running in whichever process owns it, with no window or IPC knowledge
|
|
12
|
+
renderer — the UI, reaching the privileged process only through ipc
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Adaptation points
|
|
16
|
+
|
|
17
|
+
- Merge `domain` into `main` for an app whose logic is mostly OS
|
|
18
|
+
orchestration (a launcher, a sync daemon with a thin window) — there's
|
|
19
|
+
no separable domain to isolate.
|
|
20
|
+
- Add a `persistence` layer between `domain` and `main`, depending on
|
|
21
|
+
`domain`, when the app owns a real local store (SQLite, a document
|
|
22
|
+
format) rather than plain preference files.
|
|
23
|
+
- On a native stack (Swift/AppKit, C#/WinUI) the `ipc` layer disappears —
|
|
24
|
+
there's one process. Keep `domain` separate from `renderer` regardless;
|
|
25
|
+
that boundary is what survives a platform's UI framework changing.
|
|
26
|
+
|
|
27
|
+
## Boundary that must hold
|
|
28
|
+
|
|
29
|
+
`renderer` never touches the filesystem, spawns processes, or reads
|
|
30
|
+
secrets directly — every privileged operation crosses `ipc` to `main`.
|
|
31
|
+
This is a security boundary before it's an architectural one: a renderer
|
|
32
|
+
running remote or user-supplied content with direct privileged access is
|
|
33
|
+
the standard desktop-app vulnerability, and the layer split is what keeps
|
|
34
|
+
the privileged surface small enough to audit.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Game blueprint
|
|
2
|
+
|
|
3
|
+
A starting layer sequence for `hedgehog-core-design` Step 3 on the game
|
|
4
|
+
system shape. Adapt it for the project at hand — the adaptation points
|
|
5
|
+
below are expected, not exceptions — and record what changed in
|
|
6
|
+
`core-design.md`'s rationale.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
state — the world model and the rules that mutate it: pure, deterministic, no rendering or input
|
|
10
|
+
systems — the per-tick logic (movement, collision, ai, scoring) operating on state
|
|
11
|
+
input — device events to intents, so state never reads a keyboard or gamepad directly
|
|
12
|
+
render — drawing current state to the canvas/scene graph, reading state and never writing it
|
|
13
|
+
loop — the tick/frame driver wiring input, systems, and render together
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Adaptation points
|
|
17
|
+
|
|
18
|
+
- Merge `systems` into `state` for a game whose rules are small enough to
|
|
19
|
+
live with the model (a puzzle game, a turn-based prototype).
|
|
20
|
+
- Add an `assets` layer before `render`, depending on nothing, when the
|
|
21
|
+
game has a real content pipeline (sprite atlases, audio banks, level
|
|
22
|
+
data) rather than a handful of inline files.
|
|
23
|
+
- On an engine that owns the frame loop, `loop` disappears into the
|
|
24
|
+
engine — keep the other four, mapped onto the engine's own lifecycle
|
|
25
|
+
hooks, and scope them to the engine's text sources (scripts), since
|
|
26
|
+
scenes and prefabs are binary and can't be gated.
|
|
27
|
+
|
|
28
|
+
## Boundary that must hold
|
|
29
|
+
|
|
30
|
+
`render` reads `state` and never writes it, and `state` never reads input
|
|
31
|
+
devices or draws. A deterministic state layer is what makes a game
|
|
32
|
+
testable at all — you can tick it through a scripted sequence of intents
|
|
33
|
+
and assert the outcome with no window open. It's also what makes replays,
|
|
34
|
+
save files, and any future networking possible; a game whose rules mutate
|
|
35
|
+
during rendering can never get those without a rewrite.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Infra / deploy tool blueprint
|
|
2
|
+
|
|
3
|
+
A starting layer sequence for `hedgehog-core-design` Step 3 on the
|
|
4
|
+
infra/deploy tool system shape. Adapt it for the project at hand — the
|
|
5
|
+
adaptation points below are expected, not exceptions — and record what
|
|
6
|
+
changed in `core-design.md`'s rationale.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
model — the typed desired-state the tool works against, parsed and validated from config
|
|
10
|
+
provider — the typed operations against each target system (cloud api, kubernetes, ssh), one per target
|
|
11
|
+
plan — diffing desired state against observed state into an ordered list of changes, pure and printable
|
|
12
|
+
apply — executing a plan through providers, with the failure/rollback behavior the tool promises
|
|
13
|
+
cli — argv, output rendering, and the confirmation gate in front of apply
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Adaptation points
|
|
17
|
+
|
|
18
|
+
- Merge `plan` into `apply` only for a tool that is genuinely fire-and-forget
|
|
19
|
+
(a one-shot bootstrap script) — and note that this gives up the dry-run
|
|
20
|
+
surface, which is the main reason to reach for this shape.
|
|
21
|
+
- Split `provider` per target (`provider/{module}`) when the tool spans
|
|
22
|
+
several systems with independent auth and failure modes; keep one layer
|
|
23
|
+
for a single target.
|
|
24
|
+
- Drop `model` as its own layer when desired state comes entirely from
|
|
25
|
+
flags rather than a config file.
|
|
26
|
+
|
|
27
|
+
## Boundary that must hold
|
|
28
|
+
|
|
29
|
+
`plan` computes changes without performing any, and `apply` performs only
|
|
30
|
+
what a plan named. A tool that mutates during planning can't offer a
|
|
31
|
+
trustworthy dry run, and dry run is the safety property this shape exists
|
|
32
|
+
to provide — an infra tool without it is a script that edits production
|
|
33
|
+
with no preview. `plan` must be printable and diffable on its own, with
|
|
34
|
+
no credentials required beyond reading observed state.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Library / SDK blueprint
|
|
2
|
+
|
|
3
|
+
A starting layer sequence for `hedgehog-core-design` Step 3 on the
|
|
4
|
+
library/SDK system shape. Adapt it for the project at hand — the
|
|
5
|
+
adaptation points below are expected, not exceptions — and record what
|
|
6
|
+
changed in `core-design.md`'s rationale.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
core — the implementation, importable and testable with no knowledge of how it's packaged
|
|
10
|
+
public — the exported surface: what `index.ts` re-exports, typed and versioned independently of internals
|
|
11
|
+
examples — runnable usage samples that exercise the public surface only, doubling as integration tests
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Adaptation points
|
|
15
|
+
|
|
16
|
+
- Drop `examples` as its own layer when the consuming ecosystem's
|
|
17
|
+
convention folds them into the test suite (pytest doctests, Rust
|
|
18
|
+
`examples/` compiled by `cargo test`) — fold its verify command into
|
|
19
|
+
`public`'s instead.
|
|
20
|
+
- Split `core` into per-domain sub-layers (`core/{module}`) only when the
|
|
21
|
+
library has genuinely independent domains a consumer might import
|
|
22
|
+
separately (a multi-package SDK) — a single-purpose library keeps one
|
|
23
|
+
`core` layer.
|
|
24
|
+
|
|
25
|
+
## Boundary that must hold
|
|
26
|
+
|
|
27
|
+
`public` re-exports from `core`; nothing outside `public` is a supported
|
|
28
|
+
import path. A consumer reaching into `core` directly is the signal this
|
|
29
|
+
boundary was drawn in the wrong place, not a usage error to document
|
|
30
|
+
around — the layer sequence exists so `core` can change shape without
|
|
31
|
+
breaking every consumer, and an internal import defeats that.
|
|
@@ -150,10 +150,27 @@ paragraph algorithm, and their self-tests.
|
|
|
150
150
|
section, in `landing-sequencer`'s order, every section reviewed and
|
|
151
151
|
locked before the next starts, all still inside the one `sequence`
|
|
152
152
|
task.
|
|
153
|
+
|
|
154
|
+
**Relaying a live user-confirmation checkpoint to a delegated
|
|
155
|
+
subagent.** Phase 1 (Strategist) carries a hard-stop checkpoint per
|
|
156
|
+
Phase Transition Checks below, and a delegated subagent instance has no
|
|
157
|
+
channel for the user to address it directly. The orchestrating session
|
|
158
|
+
relays the confirmation instead, and the relay is sufficient only if it
|
|
159
|
+
quotes the user's actual words with its provenance stated plainly
|
|
160
|
+
(*"Relaying the user's own confirmation, verbatim — user said:
|
|
161
|
+
'\<exact words\>'"*) rather than asserting the outcome ("the user
|
|
162
|
+
approved"). This trusts the orchestrator's honesty about provenance,
|
|
163
|
+
the same trust the rest of this discipline already places in it for
|
|
164
|
+
relaying artifacts and task packets.
|
|
153
165
|
3. Each agent **runs its own self-test** (see that agent's own file for
|
|
154
166
|
what it checks) before presenting its artifact — necessary, not
|
|
155
167
|
sufficient. This is a sanity check the agent does for itself; it does
|
|
156
|
-
not move the task and the agent does not commit its own work
|
|
168
|
+
not move the task and the agent does not commit its own work, whether
|
|
169
|
+
run directly or delegated to a subagent instance. `landing-strategist`,
|
|
170
|
+
`landing-systems`, `landing-sequencer`, and `landing-headline-writer`
|
|
171
|
+
carry no Bash tool at all (`capabilities.mjs`), so the commit is always
|
|
172
|
+
the orchestrating session's act via `hedgehog verify`, never the phase
|
|
173
|
+
agent's own.
|
|
157
174
|
4. Once every phase inside the packet's layer has been presented and
|
|
158
175
|
locked by the user, **run `hedgehog verify <task-id>`.** It checks the
|
|
159
176
|
touched files against the packet's ALLOWED SCOPE, runs the layer's
|
|
@@ -216,7 +233,10 @@ the whole chain to correct the core framing (nothing downstream exists
|
|
|
216
233
|
yet); every phase after it inherits that framing silently, and by the
|
|
217
234
|
time copy is reviewed at phases 9–10, a wrong framing means unwinding
|
|
218
235
|
several committed phases via the Correction Protocol instead of one free
|
|
219
|
-
revision here.
|
|
236
|
+
revision here. If step 1 was run by a delegated `landing-strategist`
|
|
237
|
+
subagent instance, the confirmation reaches it as a relay from the
|
|
238
|
+
orchestrating session — see The Loop above for the provenance statement
|
|
239
|
+
that relay must carry.
|
|
220
240
|
|
|
221
241
|
Before `landing-copywriter` starts (phase 10), confirm
|
|
222
242
|
`landing-headline-writer`'s headline has been presented to and locked by
|