@skyf0xx/hedgehog 6.1.2 → 6.1.3

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 CHANGED
@@ -41,7 +41,7 @@ import {
41
41
  reapExpiredLeases,
42
42
  } from '../src/db/claim.mjs';
43
43
  import { readyTasks, formatReady } from '../src/db/ready.mjs';
44
- import { graphStatus, formatStatus } from '../src/db/status.mjs';
44
+ import { graphStatus, formatStatus, inFlightTasks, formatBrief } from '../src/db/status.mjs';
45
45
  import { boundaryState, formatBoundary, formatPosition, formatHandoff } from '../src/db/boundary.mjs';
46
46
  import { commitGateStatus, formatCommitGate } from '../src/db/gate.mjs';
47
47
  import { detectDrift, recompileTasks, formatRecompile } from '../src/db/drift.mjs';
@@ -559,6 +559,7 @@ ${bold('Usage')}
559
559
  npx @skyf0xx/hedgehog verify <task-id> --owner <owner> run scope + verify checks, commit on pass
560
560
  npx @skyf0xx/hedgehog status graph overview: counts by status, ready list, in flight,
561
561
  and any drift from core.yaml
562
+ npx @skyf0xx/hedgehog status --brief one line: what is in flight, and nothing else
562
563
  npx @skyf0xx/hedgehog ready preview which ready tasks are claimable now vs held back
563
564
  npx @skyf0xx/hedgehog quiesce report whether anything is still in flight
564
565
  npx @skyf0xx/hedgehog boundary is this a moment to clear context? exits 0 only if it is,
@@ -2529,7 +2530,18 @@ async function coreWarningLines() {
2529
2530
  ];
2530
2531
  }
2531
2532
 
2532
- async function statusCommand() {
2533
+ // `--brief` answers one question — is anything `building` or
2534
+ // `verifying` — and prints one line. It exists because `hedgehog-daily`
2535
+ // asks that question before every change request, including the ones
2536
+ // that end in a two-line edit, and the full report below costs a core
2537
+ // load, a drift comparison, a readiness simulation, an override scan,
2538
+ // a commit-gate probe and an update check to answer it. The default
2539
+ // report is unchanged: this adds a cheaper question, it does not
2540
+ // replace the existing one, and a "yes" here is the cue to read the
2541
+ // full report.
2542
+ async function statusCommand(args = []) {
2543
+ const brief = args.includes('--brief');
2544
+
2533
2545
  await ensureDb();
2534
2546
 
2535
2547
  if (!(await exists(DB_PATH))) {
@@ -2538,6 +2550,21 @@ async function statusCommand() {
2538
2550
  return;
2539
2551
  }
2540
2552
 
2553
+ if (brief) {
2554
+ const db = openDb();
2555
+ let inFlight;
2556
+ try {
2557
+ // Same reaping contract as the full report — a dead agent's
2558
+ // expired lease must not read as in-flight work on either path.
2559
+ reapExpiredLeases(db);
2560
+ inFlight = inFlightTasks(db);
2561
+ } finally {
2562
+ db.close();
2563
+ }
2564
+ console.log(formatBrief(inFlight));
2565
+ return;
2566
+ }
2567
+
2541
2568
  // Drift needs the core definition to compare against. A project
2542
2569
  // without one yet (deferred install, pre-bootstrap) simply gets the
2543
2570
  // status it always got; an unparseable one is reported but never
@@ -3514,7 +3541,7 @@ async function main() {
3514
3541
  }
3515
3542
 
3516
3543
  if (cmd === 'status') {
3517
- await statusCommand();
3544
+ await statusCommand(args.slice(1));
3518
3545
  return;
3519
3546
  }
3520
3547
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyf0xx/hedgehog",
3
- "version": "6.1.2",
3
+ "version": "6.1.3",
4
4
  "description": "Install the Hedgehog build discipline (agents + skills) into a repo, for Claude Code, Cursor, or Gemini CLI.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -18,7 +18,12 @@ commit — the gate already covers that.
18
18
  - **A transition check the core's loop skill defines** — the point where
19
19
  one phase or layer closes and the next opens. That skill names when it
20
20
  calls you and what it wants confirmed; read it rather than assuming a
21
- fixed boundary.
21
+ fixed boundary. Mechanically, that point is where a layer's
22
+ `verify_radius` is wider than its own `scope`, or the layer is
23
+ `exclusive: true` (`core.yaml`) — a join or integration point, where a
24
+ boundary violation would otherwise ship unreviewed. A layer whose
25
+ radius equals its scope needs no visit from you; the loop skill's own
26
+ phrasing of "where" is that fact stated in the core's own vocabulary.
22
27
  - **Correction Protocol**: when a downstream step reveals an upstream step
23
28
  was wrong. Review the patch and its fast-forwarded dependents together,
24
29
  as one unit.
@@ -59,29 +59,29 @@ style, a piece of behavior), the existing codebase, the commit log.
59
59
  discipline as the rest of the build (`fix(<scope>): <what>` or
60
60
  `style(<scope>): <what>`, whichever fits).
61
61
 
62
- A tweak is a small, targeted edit to something that already exists —
63
- not a new module, not a new phase, not scope growth. If a request turns
64
- out to be either of those, say so and route it onward a completed
65
- build is extendable, not sealed, and the user should not hear "no" where
66
- the answer is "that's a different session." Two destinations, and which
67
- one applies depends on whether the core has a module axis to hang new
68
- work on:
62
+ **Size every request with the `hedgehog-daily` skill.** That skill owns
63
+ the tweak / change-work / re-plan decision and its conditions, and it
64
+ reads them against the installed core's own `.hedgehog/core.yaml`run
65
+ it rather than judging the size here. A completed build is extendable,
66
+ not sealed, so a request above the tweak line gets routed, not refused.
69
67
 
70
- - **New scope on a module axis** routes to `planner`, which runs
71
- `hedgehog-planning-intake`'s **Re-entry pass**: it adds intents for the
72
- new work without re-running planning from scratch, and without
73
- disturbing anything already built.
74
- - **Everything else** routes to the **Correction Protocol's post-build
75
- entry**, in the core's own loop skill, which re-runs whichever phases
76
- the change reaches and rebuilds the artifact.
68
+ What each exit means for you:
77
69
 
78
- A core with no module axis has no intent for `planner` to add, so new
79
- work there is the second case, not the first — and the locked planning
80
- artifact that governs it (the brief, the design rationale, the layer
81
- sequence) is never rewritten to accommodate new scope. When that artifact
82
- genuinely no longer holds, the request is a different project and belongs
83
- in its own, not an edit to this one; say so rather than routing it. The
84
- core's own loop skill states which artifact governs and what the test is.
70
+ - **Tweak** make it here, per that skill's tweak exit and this file's
71
+ Workflow step 3.
72
+ - **Change-work** route it onward. On a module axis, that is `planner`
73
+ running `hedgehog-planning-intake`'s **Re-entry pass**, which adds
74
+ intents for the new work without re-running planning from scratch and
75
+ without disturbing anything already built. A core with no module axis
76
+ has no intent for `planner` to add, so it goes to the **Correction
77
+ Protocol's post-build entry** in the core's own loop skill instead,
78
+ which re-runs whichever phases the change reaches and rebuilds the
79
+ artifact.
80
+ - **Re-plan** — the locked planning artifact no longer holds. Route to
81
+ `planner`'s re-entry pass, or, where that artifact's failure means the
82
+ request is a different project rather than an extension of this one,
83
+ say so plainly instead of routing. Never rewrite that artifact to
84
+ accommodate new scope.
85
85
 
86
86
  ### Job 2 — Friction review, user feedback, and issue suggestion
87
87
 
@@ -211,11 +211,11 @@ discipline as `.hedgehog/BMAD/`. A later related incident is its own new
211
211
  drop it either way; a "no" or no response is not a prompt to explain
212
212
  further or ask again later in this session. If the user says yes,
213
213
  hand off to the `hedgehog-contributing` skill.
214
- 3. **Job 1, every run**: take the user's tweak request, read the actual
215
- code it touches (not a summary), make the change, verify it with the
216
- touched layer's own `verify` command from `.hedgehog/core.yaml`
217
- matching whatever the core's own loop skill already gates on — and
218
- commit it as its own small conventional commit.
214
+ 3. **Job 1, every run**: run the `hedgehog-daily` skill on the user's
215
+ request. On its tweak exit, make the change there read the actual
216
+ code it touches (not a summary), edit, verify with the touched layer's
217
+ own `verify` command from `.hedgehog/core.yaml`, commit as its own
218
+ small conventional commit. On either other exit, route as above.
219
219
  4. **Repeat step 3** for as many tweaks as the user has, one at a time —
220
220
  don't batch unrelated tweaks into one commit.
221
221
 
@@ -257,11 +257,11 @@ discipline as `.hedgehog/BMAD/`. A later related incident is its own new
257
257
  `reviewed:` row logged after every other row currently in the log?
258
258
  - Never edit or delete a prior row in the `friction` table — it's
259
259
  write-once per row, same as `.hedgehog/BMAD/`.
260
- - Don't expand a tweak into a rebuild. If a "tweak" actually requires
261
- redoing a phase (the artifact an upstream phase locked has to change,
262
- not just one line of what a later phase produced from it), that's the
263
- Correction Protocol say so and route it
264
- there rather than patching around it here. Use its **post-build entry**
260
+ - Don't expand a tweak into a rebuild. A request `hedgehog-daily` sizes
261
+ above the tweak line gets routed, never patched around here and a
262
+ tweak that turns out mid-edit to reach a second layer or need a file
263
+ that doesn't exist stops and re-enters that gate.
264
+ - When the route is the Correction Protocol, use its **post-build entry**
265
265
  (in this core's own loop skill): the build is already at its Stop
266
266
  Condition, so there's no task in flight to stop and no loop to resume,
267
267
  and the correction is fixed forward in new commits rather than by
package/src/db/status.mjs CHANGED
@@ -55,6 +55,27 @@ function loadInFlightTasks(db) {
55
55
  return db.prepare(IN_FLIGHT_TASKS_SQL).all();
56
56
  }
57
57
 
58
+ // The in-flight list on its own, without the rest of graphStatus. The
59
+ // full report costs a drift comparison against core.yaml, a readiness
60
+ // simulation, an override scan, and two side-channel reads — everything
61
+ // `hedgehog status` prints. `hedgehog-daily` asks only "is a build in
62
+ // flight" and asks it before every change request, so it must not pay
63
+ // for a report it discards. Same query and same reaping contract as the
64
+ // full path; only the other sections are skipped.
65
+ export function inFlightTasks(db) {
66
+ return loadInFlightTasks(db);
67
+ }
68
+
69
+ // One line for `hedgehog status --brief`: what is in flight, or that
70
+ // nothing is. Deliberately not a subset of formatStatus's sections — a
71
+ // caller reading this wants a verdict, and the full report stays the
72
+ // right thing to read once the verdict is "something is".
73
+ export function formatBrief(inFlight) {
74
+ if (inFlight.length === 0) return 'IN FLIGHT 0 — nothing building or verifying';
75
+ const ids = inFlight.map((task) => task.id).join(', ');
76
+ return `IN FLIGHT ${inFlight.length} — ${ids}`;
77
+ }
78
+
58
79
  function countTasksByStatus(db) {
59
80
  const rows = db
60
81
  .prepare('SELECT status, COUNT(*) AS n FROM tasks GROUP BY status')
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgehog",
3
- "version": "6.1.2",
3
+ "version": "6.1.3",
4
4
  "description": "Hedgehog build discipline: ordered, tested, verified build steps.",
5
5
  "contextFileName": "GEMINI.md"
6
6
  }
@@ -0,0 +1,87 @@
1
+ ---
2
+ name: filing-issues
3
+ description: Use when filing one or more GitHub issues for planned work — "file an issue for this", "turn this plan into issues", "open a tracking issue". Covers filing everything on skyf0xx/hedgehog regardless of which repo's code changes, whether to split a plan into a tracking issue plus sub-issues, which account files the issue, labels, and acceptance criteria. For how to word an issue, see the pr-writing skill.
4
+ ---
5
+
6
+ # Filing issues
7
+
8
+ The mechanics of getting planned work into GitHub. `pr-writing` owns how
9
+ an issue is worded — title shape, the Why/What structure, `<details>`
10
+ folding, and style. This skill owns everything before and around that.
11
+
12
+ ## Which repo
13
+
14
+ Every issue is filed on `skyf0xx/hedgehog`, never on a core's own repo
15
+ (e.g. the one shipping `full-stack-app` or `pwa-app`) — one issue queue
16
+ to track and review, regardless of which repo's code changes.
17
+
18
+ When the fix actually lands in a core repo, open the issue body with a
19
+ line naming that repo and linking it, so a contributor knows where the
20
+ PR belongs even though the issue itself doesn't live there.
21
+
22
+ ## One issue or several
23
+
24
+ Split when the parts have different reviewers, different repos, different
25
+ risk, or can be worked in parallel. Keep one issue when the work is a
26
+ single reviewable change, even a large one.
27
+
28
+ A split gets a tracking issue plus sub-issues:
29
+
30
+ - The tracking issue carries the Why, the scope boundary, and a numbered
31
+ list of sub-issues with a one-line description of each.
32
+ - Each sub-issue is self-contained — someone picking it up should not
33
+ have to read the tracker to know what to do.
34
+ - State the dependency edges explicitly, including their absence:
35
+ which can be picked up now, which blocks which, and which merely
36
+ prefer an order without blocking.
37
+ - File the tracker first so sub-issues can reference its number, then
38
+ patch the tracker with the real numbers once they exist.
39
+ - Comment `Part of #<tracker>` on each sub-issue.
40
+
41
+ ## Which account files it
42
+
43
+ Issues go out as the user's own `gh` session by default.
44
+
45
+ Some projects have a bot identity for maintainer actions. Use it only
46
+ when the user asks for it by name. A bot voice tuned for short notes
47
+ does not apply to a planned-work issue — write the issue at full length
48
+ and say that is what you are doing.
49
+
50
+ ## Labels
51
+
52
+ Read the target repo's labels before filing (`gh label list --repo
53
+ <owner/repo>`) — the engine repo and the core repos carry overlapping but
54
+ not identical sets.
55
+
56
+ Apply what is verifiable at filing time: a type label (`feature`, `bug`,
57
+ `documentation`) and any `risk:` label the change clearly earns.
58
+ `good-first-issue` fits an issue that is genuinely self-contained with an
59
+ obvious done state. Leave `size:` labels alone — they describe a diff
60
+ that does not exist yet.
61
+
62
+ ## Acceptance criteria
63
+
64
+ End every issue with a checkbox list a contributor ticks off and a
65
+ reviewer checks against. Each line is one observable outcome, not a
66
+ restatement of the task list.
67
+
68
+ - Testable by inspection or a command, not by judgment. "`pnpm nx test
69
+ mobile -- src/{module}/` passes on generated output" — not "the
70
+ generator works well."
71
+ - Include the things that must *not* change: the existing behavior that
72
+ still has to pass, the version that must not be bumped.
73
+ - Cover the whole change. A criterion nobody can check is noise; a
74
+ missing one is a gap a reviewer has to find themselves.
75
+
76
+ On a tracking issue, the criteria are the sub-issues plus the end-to-end
77
+ outcome that proves the whole set landed.
78
+
79
+ ## Before filing
80
+
81
+ Verify every claim the issue makes about existing behavior, and cite it
82
+ `file:line`. An issue is public and durable — a wrong claim in one sends
83
+ a contributor down a path that does not exist.
84
+
85
+ Confirm the split and the identity with the user before creating
86
+ anything — the repo is fixed, not a decision to make each time. Issue
87
+ creation is public and hard to reverse.
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: hedgehog-daily
3
+ description: Use when a change request lands on a project that already has `.hedgehog/` and no build in flight — a finished build being adjusted, or an adopted repo's next piece of work. Triggers on any "change this", "fix this", "add this" on such a project. Sizes the request against the installed core's own layers and routes it to one of three exits: a tweak made and committed here, change-work through `hedgehog intent add` and the core's loop, or a re-plan. Not for a build still in progress — that is the core's loop skill's own job.
4
+ ---
5
+
6
+ # Daily change-work
7
+
8
+ One gate, three exits, for every change request on a project whose build
9
+ graph already exists. It reads the installed core's layer sequence,
10
+ scope globs and verify commands out of `.hedgehog/core.yaml`, so it is
11
+ the same gate on every core.
12
+
13
+ The gate exists to stop pricing a two-line edit at the cost of the
14
+ largest change the discipline can handle. Routing up is a real decision
15
+ with a real cost, taken on stated conditions — not the safe default.
16
+
17
+ ## Entry
18
+
19
+ 1. **`.hedgehog/` exists.** Without it there is no core to read and no
20
+ graph to add to; this skill does not apply.
21
+ 2. **Nothing is in flight.** `hedgehog status --brief` — one line. If it
22
+ names any task, a build is mid-flight: this gate does not run. Read
23
+ the full `hedgehog status` and hand the request back to the core's own
24
+ loop skill, which owns work in progress.
25
+ 3. **Read `.hedgehog/core.yaml`.** The layer list is the input to every
26
+ decision below: each layer's `id`, `scope` globs, `verify` command,
27
+ `verify_radius` and `exclusive`. Read the file, not a memory of it.
28
+
29
+ ## The three exits
30
+
31
+ Decide by the conditions, in order. The first one that holds is the exit.
32
+
33
+ ### Re-plan
34
+
35
+ The locked planning artifact that governs this project no longer
36
+ describes what is being asked for. The core's own loop skill names which
37
+ artifact governs — the brief and layer sequence for a shipped core,
38
+ `.hedgehog/core-design.md` for an authored one, `.hedgehog/adoption.md`
39
+ for an adopted one.
40
+
41
+ Route to `planner`'s re-entry pass, which adds intents for new work
42
+ without re-running planning from scratch and without disturbing anything
43
+ already built.
44
+
45
+ Where the artifact's failure means the request is a different project
46
+ rather than an extension of this one, say so plainly instead of routing.
47
+ That artifact is never rewritten to accommodate new scope.
48
+
49
+ ### Change-work
50
+
51
+ Either condition puts the request here:
52
+
53
+ - It reaches more than one of the core's layers.
54
+ - It introduces a file, module, or capability that does not exist yet.
55
+
56
+ `hedgehog intent add`, then the installed core's own loop, unchanged.
57
+ Nothing about that path changes because this gate ran.
58
+
59
+ ### Tweak
60
+
61
+ Both conditions hold:
62
+
63
+ - Every file it touches is inside one layer's `scope` globs — one
64
+ layer, not two.
65
+ - Every file it touches already exists.
66
+
67
+ Then, in this session, with no subagent dispatched:
68
+
69
+ 1. Read the code it touches. Not a summary of it.
70
+ 2. Make the smallest correct edit.
71
+ 3. Run that layer's own `verify` command from `core.yaml`, at the depth
72
+ the next section states.
73
+ 4. Commit as one conventional commit, in the format the
74
+ `conventional-commits` skill states.
75
+
76
+ No `hedgehog intent add`, no `hedgehog plan`, no `hedgehog claim`, no
77
+ subagent. Nothing is written to the build graph.
78
+
79
+ ### Tweak is the default under ambiguity
80
+
81
+ When the conditions do not clearly place a request above the tweak line,
82
+ it takes the tweak exit. A gate that escalates when unsure prices every
83
+ change at its worst case, which is the failure this gate exists to
84
+ avoid.
85
+
86
+ An escalation the tweak reveals is cheap: a tweak that turns out to
87
+ touch a second layer or need a file that does not exist stops there and
88
+ re-enters this gate at the change-work exit, having cost one read.
89
+
90
+ ## Test and review depth on the tweak exit
91
+
92
+ A tweak inherits the test and review bar of the layer it lands in.
93
+
94
+ - A layer whose `verify_radius` equals its `scope`: run the layer's
95
+ `verify` command. No new tests, no `reviewer` pass.
96
+ - A layer with a wider `verify_radius`, or `exclusive: true`: the same
97
+ real test bar and `reviewer` pass that layer gets in the loop.
98
+
99
+ That is the loop's own rule — "Test depth follows verify radius. Review
100
+ follows exclusivity", stated in full in the core's loop skill — applied
101
+ to a layer instead of a compiled task. `verify_radius` and `exclusive`
102
+ are declared on the layer in `core.yaml`, so both are readable on a path
103
+ that compiles no task.
104
+
105
+ **A tweak landing in a wide-radius or exclusive layer is a signal.**
106
+ Integration layers are where behavior gets proven, so a change reaching
107
+ one is rarely as small as it looked when it was asked for. Re-check that
108
+ the tweak exit was the right exit. Do not bolt the loop's ceremony onto
109
+ the tweak path instead.
110
+
111
+ **The floor does not move.** A tweak to code with no tests does not get
112
+ to leave it that way where the layer's own bar says otherwise.
113
+
114
+ ## Hard rules
115
+
116
+ - Never take the tweak exit on a file that does not exist yet. A new
117
+ file is change-work by condition, whatever its size.
118
+ - Never widen a layer's `scope` to make a change fit the tweak exit.
119
+ A change that needs a wider scope is change-work.
120
+ - Never commit a tweak whose layer `verify` command fails. A failing
121
+ gate means the change is not done.
122
+ - Never batch two unrelated tweaks into one commit.
123
+ - Never rewrite the locked planning artifact to accommodate new scope —
124
+ that is the re-plan exit's decision, and its answer may be that this
125
+ is a different project.