@skyf0xx/hedgehog 6.0.5 → 6.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/bin/cli.mjs +30 -28
- package/package.json +1 -1
- package/src/agents/planner.md +11 -10
- package/src/agents/reviewer.md +3 -2
- package/src/agents/tweaker.md +4 -4
- package/src/hosts/claude-md-merge.mjs +1 -1
- package/src/hosts/gemini/gemini-extension.json +1 -1
- package/src/registry/cores.json +10 -2
- package/src/registry/installed.mjs +23 -29
- package/src/registry/manifest.mjs +0 -1
package/bin/cli.mjs
CHANGED
|
@@ -281,19 +281,6 @@ function corePayload(core, h, { hostOnly = false } = {}) {
|
|
|
281
281
|
// than generating it live. A core that scaffolds nothing (its
|
|
282
282
|
// workspace is designed during planning) declares no `workspace`.
|
|
283
283
|
...(manifest.workspace ? [{ type: 'dir', root, from: manifest.workspace, to: '.' }] : []),
|
|
284
|
-
// A second CLAUDE.md section for cores whose path fills
|
|
285
|
-
// {{CORE_SECTION}} after install rather than at it — adoption reads
|
|
286
|
-
// it from the project instead of the package it ships in.
|
|
287
|
-
...(manifest.template_adopted
|
|
288
|
-
? [
|
|
289
|
-
{
|
|
290
|
-
type: 'file',
|
|
291
|
-
root,
|
|
292
|
-
from: manifest.template_adopted,
|
|
293
|
-
to: `.hedgehog/${manifest.template_adopted}`,
|
|
294
|
-
},
|
|
295
|
-
]
|
|
296
|
-
: []),
|
|
297
284
|
];
|
|
298
285
|
}
|
|
299
286
|
|
|
@@ -526,7 +513,7 @@ ${bold('Usage')}
|
|
|
526
513
|
npx @skyf0xx/hedgehog init --pwa-app scaffold the pwa-app core now
|
|
527
514
|
npx @skyf0xx/hedgehog init --landing-page scaffold the landing-page core now
|
|
528
515
|
npx @skyf0xx/hedgehog cores list every core this release can install
|
|
529
|
-
npx @skyf0xx/hedgehog core record-adopted land the
|
|
516
|
+
npx @skyf0xx/hedgehog core record-adopted land the adopted core's agents/skills and record
|
|
530
517
|
this project as adopted (hedgehog-adopt calls this
|
|
531
518
|
after writing .hedgehog/core.yaml; not for other cores)
|
|
532
519
|
npx @skyf0xx/hedgehog init --cursor install for Cursor (default: Claude Code)
|
|
@@ -1046,10 +1033,10 @@ async function resolveInstalledCore() {
|
|
|
1046
1033
|
}
|
|
1047
1034
|
|
|
1048
1035
|
// `hedgehog core record-adopted` — the record path for `hedgehog-adopt`
|
|
1049
|
-
// (shipped in @skyf0xx/hedgehog-core-
|
|
1036
|
+
// (shipped in @skyf0xx/hedgehog-core-adopted), which brings the
|
|
1050
1037
|
// discipline to an existing repo by writing `.hedgehog/core.yaml` and
|
|
1051
1038
|
// `.hedgehog/adoption.md` directly. That path has no `init` step and so
|
|
1052
|
-
// never fetches the `
|
|
1039
|
+
// never fetches the `adopted` package or calls `recordCore` — a no-flag
|
|
1053
1040
|
// `init` (what the offer skill actually runs before adoption) installs
|
|
1054
1041
|
// only the shared engine payload, never a core's own agents/skills, and
|
|
1055
1042
|
// `bootstrap` (the only other place a core package gets fetched) is
|
|
@@ -1061,24 +1048,27 @@ async function resolveInstalledCore() {
|
|
|
1061
1048
|
// `core.yaml` (the shipped-core workspace marker) and finds nothing for
|
|
1062
1049
|
// an adopted repo's `.hedgehog/core.yaml`, so it would read as "no core
|
|
1063
1050
|
// yet" and update would silently rewrite `.claude/agents`/`.claude/skills`
|
|
1064
|
-
// down to just the shared payload, deleting the
|
|
1051
|
+
// down to just the shared payload, deleting the adopted package's files
|
|
1065
1052
|
// with nothing put back.
|
|
1066
1053
|
//
|
|
1067
|
-
// This command is both fixes at once: it fetches the `
|
|
1054
|
+
// This command is both fixes at once: it fetches the `adopted` package
|
|
1068
1055
|
// and lands its agents/skills for every host this project already has
|
|
1069
|
-
// installed (never its workspace
|
|
1070
|
-
//
|
|
1071
|
-
//
|
|
1072
|
-
//
|
|
1073
|
-
//
|
|
1074
|
-
//
|
|
1075
|
-
//
|
|
1056
|
+
// installed (never its workspace or vendor_skills — root workspace is
|
|
1057
|
+
// the one thing adoption must never touch), plus a local copy of its
|
|
1058
|
+
// `CLAUDE.core.md` at `.hedgehog/CLAUDE.core.md` — `hedgehog-adopt`'s own
|
|
1059
|
+
// Confirm & Lock step reads that file from there to merge into root
|
|
1060
|
+
// `CLAUDE.md`, since a no-flag `init` never ran the normal
|
|
1061
|
+
// `{{CORE_SECTION}}` merge this project's core would otherwise get — then
|
|
1062
|
+
// records the core the same as any other, naming `adopted`, so `update`
|
|
1063
|
+
// refreshes it correctly from here on. Idempotent and safe to re-run —
|
|
1064
|
+
// e.g. from a later `hedgehog-adopt` pass adding new change-work — since
|
|
1065
|
+
// it always overwrites from the current package rather than merging.
|
|
1076
1066
|
async function recordAdoptedCommand() {
|
|
1077
1067
|
const entry = await resolveCore(ADOPTED_CORE_NAME);
|
|
1078
1068
|
if (!entry) {
|
|
1079
1069
|
console.error(
|
|
1080
|
-
`${red('
|
|
1081
|
-
`entry named "
|
|
1070
|
+
`${red('adopted core not in this release.')} This Hedgehog release's registry has no\n` +
|
|
1071
|
+
`entry named "adopted" — nothing to install. Update Hedgehog and retry.\n`,
|
|
1082
1072
|
);
|
|
1083
1073
|
process.exitCode = 1;
|
|
1084
1074
|
return;
|
|
@@ -1106,7 +1096,19 @@ async function recordAdoptedCommand() {
|
|
|
1106
1096
|
}
|
|
1107
1097
|
}
|
|
1108
1098
|
|
|
1109
|
-
|
|
1099
|
+
const templateFile = (
|
|
1100
|
+
await plannedFiles({
|
|
1101
|
+
type: 'file',
|
|
1102
|
+
root: core.root,
|
|
1103
|
+
from: core.manifest.template,
|
|
1104
|
+
to: '.hedgehog/CLAUDE.core.md',
|
|
1105
|
+
})
|
|
1106
|
+
)[0];
|
|
1107
|
+
await writePlannedFile(templateFile);
|
|
1108
|
+
written++;
|
|
1109
|
+
console.log(` ${green('install')} ${relative(DEST_ROOT, templateFile.dest)}`);
|
|
1110
|
+
|
|
1111
|
+
await recordCore(DEST_ROOT, { name: core.manifest.name, version: core.version });
|
|
1110
1112
|
|
|
1111
1113
|
console.log(
|
|
1112
1114
|
`\n${green(bold('Adopted core recorded.'))} ${dim(
|
package/package.json
CHANGED
package/src/agents/planner.md
CHANGED
|
@@ -31,7 +31,8 @@ You run on two paths, and Workflow step 2 decides which:
|
|
|
31
31
|
scope into additional intents without re-running the BMAD shelf.
|
|
32
32
|
Landing-page has no module axis, so this path doesn't apply to it — see
|
|
33
33
|
the landing-page constraint below for where its new scope actually
|
|
34
|
-
goes.
|
|
34
|
+
goes. New change-work on an **adopted** core is a separate case again —
|
|
35
|
+
see "An existing repo, ongoing adoption" below.
|
|
35
36
|
|
|
36
37
|
Either path is entered when the user says "plan", "scope", "break down",
|
|
37
38
|
asks for something that's new scope rather than a tweak (routed here by
|
|
@@ -200,14 +201,14 @@ none of them is a description matching a `when` paragraph:
|
|
|
200
201
|
repo", "add Hedgehog to my existing project", "I want scope/verify
|
|
201
202
|
enforcement on my changes here"). This is a distinct question from
|
|
202
203
|
everything above: it's not about which core fits new work, because no
|
|
203
|
-
new workspace gets built at all.
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
`.hedgehog/core.yaml`;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
decisions.
|
|
204
|
+
new workspace gets built at all. This project gets the **adopted
|
|
205
|
+
core**. Route straight to `hedgehog-adopt` — bootstrap and every other
|
|
206
|
+
Phase 0 outcome are skipped entirely, since there is no workspace to
|
|
207
|
+
scaffold and no shipped stack to adopt toward. `hedgehog-adopt` runs
|
|
208
|
+
its own read-only intake and writes its own `.hedgehog/core.yaml`;
|
|
209
|
+
don't run `hedgehog-planning-intake`'s BMAD shelf first — the drivers
|
|
210
|
+
that skill elicits (persistence, stack, deployment target) are already
|
|
211
|
+
settled facts of the existing repo, not open decisions.
|
|
211
212
|
|
|
212
213
|
State the decision plainly before Phase 1 begins, with the one-line
|
|
213
214
|
reason it landed there — this is cheap to correct now and expensive once
|
|
@@ -375,7 +376,7 @@ as full-stack-app's Auth/Queue/Mobile trio.
|
|
|
375
376
|
the build graph.
|
|
376
377
|
- **landing-page**: owns `.hedgehog/BMAD/` and
|
|
377
378
|
`.hedgehog/chain/00-brief.md` as artifacts.
|
|
378
|
-
- **
|
|
379
|
+
- **adopted**: owns nothing here — `hedgehog-adopt` owns
|
|
379
380
|
`.hedgehog/core.yaml` and `.hedgehog/adoption.md`, the same way an
|
|
380
381
|
authored core's design is `hedgehog-core-design`'s.
|
|
381
382
|
|
package/src/agents/reviewer.md
CHANGED
|
@@ -30,7 +30,8 @@ Everything the commit gate already enforces — the layer's own `verify`
|
|
|
30
30
|
command, and whatever typecheck/lint/test it runs — is out of scope;
|
|
31
31
|
don't re-report a green gate. Read the core's own design first: its loop
|
|
32
32
|
skill for a shipped core, `.hedgehog/core.yaml` and
|
|
33
|
-
`.hedgehog/core-design.md` for an authored one.
|
|
33
|
+
`.hedgehog/core-design.md` for an authored one, `.hedgehog/core.yaml` and
|
|
34
|
+
`.hedgehog/adoption.md` for an adopted one. That is where the layer
|
|
34
35
|
boundaries, the interface between them, and this core's own conventions
|
|
35
36
|
are stated. Your checklist is derived from it, not from a stack you
|
|
36
37
|
recognize.
|
|
@@ -96,7 +97,7 @@ Check what the gate structurally cannot:
|
|
|
96
97
|
- Don't nitpick style. Focus on structural correctness relative to the
|
|
97
98
|
stack and build order the core's own design fixed — its loop and
|
|
98
99
|
bootstrap skills on a shipped core, `.hedgehog/core-design.md` on an
|
|
99
|
-
authored one.
|
|
100
|
+
authored one, `.hedgehog/adoption.md` on an adopted one.
|
|
100
101
|
- 3 real findings beats 20 suggestions. This review sits at a phase or
|
|
101
102
|
layer boundary, not mid-Loop — don't slow the Loop down for anything
|
|
102
103
|
that isn't load-bearing for the work that comes next.
|
package/src/agents/tweaker.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tweaker
|
|
3
|
-
description: Use once a core's build is complete (every task in the build graph `complete`) and the user is offered a fresh-context session to iterate. Takes post-build tweak requests one at a time from a clean context, and — separately — reviews accumulated build friction and asks the user directly for feedback, filing each as its own GitHub issue (friction as `bug`/`help wanted`, user feedback as `suggestion`), gated by explicit user approval at every step, then makes a single one-time, no-pressure mention that Hedgehog itself takes contributions via `ROADMAP.md`. Shared by every core with a Stop Condition — not
|
|
3
|
+
description: Use once a core's build is complete (every task in the build graph `complete`) and the user is offered a fresh-context session to iterate. Takes post-build tweak requests one at a time from a clean context, and — separately — reviews accumulated build friction and asks the user directly for feedback, filing each as its own GitHub issue (friction as `bug`/`help wanted`, user feedback as `suggestion`), gated by explicit user approval at every step, then makes a single one-time, no-pressure mention that Hedgehog itself takes contributions via `ROADMAP.md`. Shared by every core with a Stop Condition — not the `adopted` core, which has none; there, new change-work goes straight through `hedgehog-adopt` and `hedgehog-authored-loop` instead.
|
|
4
4
|
model: sonnet
|
|
5
5
|
color: green
|
|
6
6
|
tools: Read, Glob, Grep, Edit, Write, Bash
|
|
@@ -15,7 +15,7 @@ conversation. You start from a cleared context on purpose. Re-read the
|
|
|
15
15
|
friction log (`hedgehog friction list`) and the commit log rather than
|
|
16
16
|
expecting anything to be remembered.
|
|
17
17
|
|
|
18
|
-
**Not for
|
|
18
|
+
**Not for the `adopted` core (`.hedgehog/core.yaml` written by
|
|
19
19
|
`hedgehog-adopt`).** That core has no Stop Condition and no "build
|
|
20
20
|
finished" moment for you to follow — adoption is the permanent way
|
|
21
21
|
change lands, not a project with an end. A request there is just the
|
|
@@ -44,8 +44,8 @@ straight to job 1.
|
|
|
44
44
|
|
|
45
45
|
None of its own — you work inside whichever core's stack is already
|
|
46
46
|
installed (a shipped core's, or the stack an authored core's
|
|
47
|
-
`.hedgehog/core-design.md` names —
|
|
48
|
-
the note above), editing the same files the core's own build agents
|
|
47
|
+
`.hedgehog/core-design.md` names — the `adopted` core never reaches you,
|
|
48
|
+
per the note above), editing the same files the core's own build agents
|
|
49
49
|
would. `gh` (GitHub CLI) for issue creation only, and only against
|
|
50
50
|
`skyf0xx/hedgehog`, never the project's own remote.
|
|
51
51
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// instead of substituting into one.
|
|
14
14
|
//
|
|
15
15
|
// Referenced by name (not substance) from hedgehog-adopt's own SKILL.md
|
|
16
|
-
// in the @skyf0xx/hedgehog-core-
|
|
16
|
+
// in the @skyf0xx/hedgehog-core-adopted package — that skill invokes
|
|
17
17
|
// `appendCoreSection` the same way it already invokes `loadCore` from
|
|
18
18
|
// src/db/core.mjs, via `node -e "import('<path-to-hedgehog-install>/
|
|
19
19
|
// src/hosts/claude-md-merge.mjs')..."`.
|
package/src/registry/cores.json
CHANGED
|
@@ -39,10 +39,18 @@
|
|
|
39
39
|
{
|
|
40
40
|
"name": "authored",
|
|
41
41
|
"package": "@skyf0xx/hedgehog-core-authored",
|
|
42
|
-
"version": "^1.0
|
|
42
|
+
"version": "^1.1.0",
|
|
43
43
|
"language": "typescript",
|
|
44
44
|
"repository": "https://github.com/skyf0xx/hedgehog-core-authored",
|
|
45
|
-
"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."
|
|
45
|
+
"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. This is the core most often confused with adopted: authored designs a workspace from scratch for a project being built new, while adopted brings Hedgehog's discipline to a repo that already exists — route here only when there is no existing codebase this work is being added to."
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "adopted",
|
|
49
|
+
"package": "@skyf0xx/hedgehog-core-adopted",
|
|
50
|
+
"version": "^1.0.0",
|
|
51
|
+
"language": "typescript",
|
|
52
|
+
"repository": "https://github.com/skyf0xx/hedgehog-core-adopted",
|
|
53
|
+
"selects_when": "The description is about bringing Hedgehog's discipline to a codebase that already exists, rather than building something new — the repo already has real source files, or the user says so explicitly: \"adopt this repo\", \"add Hedgehog to my existing project\", \"I want scope/verify enforcement on my changes here\". Not chosen by matching a `when` paragraph the way a shipped core is: hedgehog-adopt reads the repo read-only, proposes a linear-chain .hedgehog/core.yaml whose verify commands are the repo's own, and writes only .hedgehog/ — never a workspace, never a stack migration. This is the core most often confused with authored: adopted brings discipline to an existing repo, while authored designs and scaffolds a workspace from scratch for something being built new — route here only when the work is landing on a codebase that already exists."
|
|
46
54
|
}
|
|
47
55
|
]
|
|
48
56
|
}
|
|
@@ -7,21 +7,19 @@
|
|
|
7
7
|
// the core — `installedCore` returns null until then, and `update` limits
|
|
8
8
|
// itself to the shared payload.
|
|
9
9
|
//
|
|
10
|
-
// `
|
|
11
|
-
//
|
|
12
|
-
// writing `.hedgehog/core.yaml` itself, directly, and
|
|
13
|
-
// `recordCore`
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
// any other (same package, same agents/skills, kept current) but must
|
|
24
|
-
// never treat `record.name` changing upstream, or the record going
|
|
10
|
+
// `adopted` has no `init` step at all: `hedgehog-adopt` (shipped in
|
|
11
|
+
// @skyf0xx/hedgehog-core-adopted) brings the discipline to a repo that
|
|
12
|
+
// already exists by writing `.hedgehog/core.yaml` itself, directly, and
|
|
13
|
+
// never calls `recordCore`. `hedgehog core record-adopted` (bin/cli.mjs)
|
|
14
|
+
// is the record path for that case instead: it fetches the `adopted`
|
|
15
|
+
// package and lands its agents/skills — otherwise never installed, since
|
|
16
|
+
// adoption's `init` runs with no `--core` flag and `bootstrap` is skipped
|
|
17
|
+
// entirely for adoption — and calls `recordCore` the same as any other
|
|
18
|
+
// core, naming `adopted`. That name is the one thing distinguishing an
|
|
19
|
+
// adopted record from a normal one: `update`'s resolveInstalledCore
|
|
20
|
+
// refreshes an adopted project's payload the same as any other (same
|
|
21
|
+
// package, same agents/skills, kept current) but must never treat
|
|
22
|
+
// `record.name === 'adopted'` changing upstream, or the record going
|
|
25
23
|
// missing, as license to fetch and install a *different* core the way it
|
|
26
24
|
// would for a project that chose one at `init` — adoption's core is a
|
|
27
25
|
// fixed fact of the repo (its `.hedgehog/core.yaml`), not a choice
|
|
@@ -30,38 +28,34 @@
|
|
|
30
28
|
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
31
29
|
import { dirname, join } from 'node:path';
|
|
32
30
|
|
|
33
|
-
export const ADOPTED_CORE_NAME = '
|
|
31
|
+
export const ADOPTED_CORE_NAME = 'adopted';
|
|
34
32
|
|
|
35
33
|
const CORE_PATH = '.hedgehog/core.json';
|
|
36
34
|
|
|
37
35
|
/**
|
|
38
36
|
* Record the core a project installed and the exact version resolved for
|
|
39
37
|
* it. Written after the core's files land, so the record describes what
|
|
40
|
-
* is on disk.
|
|
41
|
-
* record-adopted` rather than by `init` — see the module comment above.
|
|
38
|
+
* is on disk.
|
|
42
39
|
*/
|
|
43
|
-
export async function recordCore(root, { name, version
|
|
40
|
+
export async function recordCore(root, { name, version }) {
|
|
44
41
|
const path = join(root, CORE_PATH);
|
|
45
42
|
await mkdir(dirname(path), { recursive: true });
|
|
46
43
|
await writeFile(
|
|
47
44
|
path,
|
|
48
|
-
`${JSON.stringify(
|
|
49
|
-
{ core: name, version, installedAt: new Date().toISOString(), ...(adopted ? { adopted: true } : {}) },
|
|
50
|
-
null,
|
|
51
|
-
2,
|
|
52
|
-
)}\n`,
|
|
45
|
+
`${JSON.stringify({ core: name, version, installedAt: new Date().toISOString() }, null, 2)}\n`,
|
|
53
46
|
);
|
|
54
47
|
}
|
|
55
48
|
|
|
56
49
|
/**
|
|
57
|
-
* The core `update` should refresh — `{ name, version
|
|
58
|
-
*
|
|
59
|
-
*
|
|
50
|
+
* The core `update` should refresh — `{ name, version }` — or null when
|
|
51
|
+
* this project has no core installed yet. `name === 'adopted'` marks a
|
|
52
|
+
* record written by `hedgehog core record-adopted` rather than by `init`
|
|
53
|
+
* — see the module comment above.
|
|
60
54
|
*/
|
|
61
55
|
export async function installedCore(root) {
|
|
62
56
|
try {
|
|
63
|
-
const { core, version
|
|
64
|
-
return core ? { name: core, version
|
|
57
|
+
const { core, version } = JSON.parse(await readFile(join(root, CORE_PATH), 'utf8'));
|
|
58
|
+
return core ? { name: core, version } : null;
|
|
65
59
|
} catch {
|
|
66
60
|
return null;
|
|
67
61
|
}
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
// engine: "^<major>.<minor>.<patch>" which CLI versions can install it
|
|
12
12
|
// workspace: workspace/ omitted by a core that scaffolds nothing
|
|
13
13
|
// template: CLAUDE.core.md fills the CLAUDE.md shell's core section
|
|
14
|
-
// template_adopted: <path> optional second section, for adoption
|
|
15
14
|
// agents: [<name>, ...] agents/<name>.md in the package
|
|
16
15
|
// skills: [<name>, ...] skills/<name>/ in the package
|
|
17
16
|
// vendor_skills: [<name>, ...] vendor-skills/<name>/ in the package
|