@skyf0xx/hedgehog 3.0.6 → 3.0.7
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/skills/hedgehog-core-design/SKILL.md +80 -15
- package/src/skills/hedgehog-core-design/blueprints/bot-agent.md +35 -0
- package/src/skills/hedgehog-core-design/blueprints/browser-extension.md +26 -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/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,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
|
|
@@ -178,6 +235,12 @@ if missed:
|
|
|
178
235
|
belongs in `.hedgehog/core-design.md`.
|
|
179
236
|
- **`depends_on` names one layer**, and the chain must be acyclic. The
|
|
180
237
|
compiler walks it directly into `dependencies` rows.
|
|
238
|
+
- **`verify` must prove the layer's own claim, not just exit clean.** A
|
|
239
|
+
command that runs but asserts nothing (`tsc --noEmit` alone on a layer
|
|
240
|
+
whose job is behavior, a `test -s` on a file nothing checks the content
|
|
241
|
+
of) passes on an empty implementation. Pair typecheck/build commands
|
|
242
|
+
with a test command that exercises the layer's actual output whenever
|
|
243
|
+
the layer produces behavior, not just types.
|
|
181
244
|
|
|
182
245
|
Verify the file loads before showing it back, by calling the loader
|
|
183
246
|
directly:
|
|
@@ -196,12 +259,14 @@ forward.
|
|
|
196
259
|
|
|
197
260
|
The rationale the engine doesn't read but the project needs: the system
|
|
198
261
|
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
|
-
|
|
262
|
+
constraint that justified a substitution), the composition/error/config/
|
|
263
|
+
entrypoint decisions from Step 2, the layer blueprint used and what
|
|
264
|
+
changed from it (or, off-table, that layers were derived directly and
|
|
265
|
+
why), the layers with a line each on what they own and why they sit where
|
|
266
|
+
they do, the module-axis decision, and anything left unresolved. Written
|
|
267
|
+
once, archival, never edited after — the same stance `.hedgehog/BMAD/`
|
|
268
|
+
takes. Later changes to the architecture are Correction Protocol entries
|
|
269
|
+
in the commit log, not edits here.
|
|
205
270
|
|
|
206
271
|
## Confirm & Lock
|
|
207
272
|
|
|
@@ -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,26 @@
|
|
|
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
|
+
|
|
21
|
+
## Boundary that must hold
|
|
22
|
+
|
|
23
|
+
`popup` never imports from `background` or `content` directly — every
|
|
24
|
+
cross-context call goes through `messaging`, because a WebExtension's
|
|
25
|
+
contexts are separate JS runtimes and a direct import silently fails at
|
|
26
|
+
runtime rather than at build time.
|
|
@@ -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.
|