@skyf0xx/hedgehog 3.0.8 → 3.0.11

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 CHANGED
@@ -48,6 +48,18 @@ The build order is encoded into the project. The AI does not have to remember wh
48
48
 
49
49
  ![Small steps, big leverage: small context loops, continuous verification, traceable evolution, sustainable velocity](https://raw.githubusercontent.com/skyf0xx/hedgehog/master/docs/images/small-steps.png)
50
50
 
51
+ ## Your build order is a graph
52
+
53
+ **Every task** Hedgehog generates **is a node** with explicit dependencies in sqlite.
54
+
55
+ Unlike stories and epics, **the graph locks build order** into an **signal-dense, context-light** path the agents can use.
56
+
57
+ ```bash
58
+ npx @skyf0xx/hedgehog graph
59
+ ```
60
+
61
+ ![The Hedgehog build graph](https://raw.githubusercontent.com/skyf0xx/hedgehog/master/docs/images/graph.png)
62
+
51
63
  ## What Hedgehog builds
52
64
 
53
65
  ### Full-stack applications
@@ -101,7 +113,7 @@ scoped file access and a verification command per layer.
101
113
 
102
114
  ## Install
103
115
 
104
- From an empty project folder, run:
116
+ From an empty project folder, ask Claude or your Agent to run:
105
117
 
106
118
  ``` bash
107
119
  # Full-stack app
@@ -156,15 +168,6 @@ from them. It never touches the instructions file, the build graph, the
156
168
  core workspace, or `skills/BMAD`, since those carry project-specific or
157
169
  write-once content.
158
170
 
159
- To see the build graph:
160
-
161
- ``` bash
162
- npx @skyf0xx/hedgehog graph
163
- ```
164
-
165
- Starts a small local server and opens a live, read-only diagram of every
166
- task, status and its dependencies.
167
-
168
171
  ## Why Hedgehog
169
172
 
170
173
  Most AI coding tools improve prompting.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyf0xx/hedgehog",
3
- "version": "3.0.8",
3
+ "version": "3.0.11",
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": {
@@ -14,6 +14,7 @@
14
14
  "hedgehog": "bin/cli.mjs"
15
15
  },
16
16
  "scripts": {
17
+ "check": "node scripts/check.mjs",
17
18
  "release": "npm version patch -m \"chore: bump version to %s\""
18
19
  },
19
20
  "files": [
@@ -15,6 +15,7 @@
15
15
 
16
16
  import { createServer } from 'node:http';
17
17
  import { readFile, writeFile, rm } from 'node:fs/promises';
18
+ import { dirname, join } from 'node:path';
18
19
  import { DatabaseSync } from 'node:sqlite';
19
20
  import { buildGraph } from './graph.mjs';
20
21
 
@@ -31,6 +32,15 @@ if (!dbPath || !templatePath || !pidfilePath) {
31
32
 
32
33
  const template = await readFile(templatePath, 'utf8');
33
34
 
35
+ // graph.html loads React/ReactFlow/dagre from here rather than a CDN, so
36
+ // `hedgehog graph` works with no internet connection — vendored files
37
+ // live alongside the template at src/templates/vendor/.
38
+ const VENDOR_DIR = join(dirname(templatePath), 'vendor');
39
+ const VENDOR_CONTENT_TYPES = {
40
+ '.js': 'application/javascript; charset=utf-8',
41
+ '.css': 'text/css; charset=utf-8',
42
+ };
43
+
34
44
  function loadGraphJson() {
35
45
  // Opened and closed per request rather than held open: DatabaseSync is
36
46
  // synchronous and local, so the cost is negligible, and it avoids ever
@@ -44,7 +54,33 @@ function loadGraphJson() {
44
54
  }
45
55
  }
46
56
 
47
- const server = createServer((req, res) => {
57
+ const server = createServer(async (req, res) => {
58
+ if (req.url.startsWith('/vendor/')) {
59
+ // Reject traversal/query strings before touching the filesystem —
60
+ // the vendor set is fixed and flat, so anything else is not a file
61
+ // this route is meant to serve.
62
+ const name = req.url.slice('/vendor/'.length);
63
+ const dotIndex = name.lastIndexOf('.');
64
+ const ext = dotIndex === -1 ? '' : name.slice(dotIndex);
65
+ if (!name || name.includes('/') || name.includes('..') || !(ext in VENDOR_CONTENT_TYPES)) {
66
+ res.writeHead(404);
67
+ res.end('Not found');
68
+ return;
69
+ }
70
+ try {
71
+ const body = await readFile(join(VENDOR_DIR, name));
72
+ res.writeHead(200, {
73
+ 'content-type': VENDOR_CONTENT_TYPES[ext],
74
+ 'cache-control': 'no-store',
75
+ });
76
+ res.end(body);
77
+ } catch {
78
+ res.writeHead(404);
79
+ res.end('Not found');
80
+ }
81
+ return;
82
+ }
83
+
48
84
  if (req.url === '/graph.json') {
49
85
  let body;
50
86
  try {
@@ -15,9 +15,16 @@ schedule — the orchestration wiring: what runs when, retries, backfill entry
15
15
 
16
16
  ## Adaptation points
17
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.
18
+ - On the Dagster stack, `schedule` is Dagster's own schedule/sensor
19
+ definitions plus the retry policy on each op real orchestration
20
+ surface that belongs in this repo and earns its own layer.
21
+ - On the stdlib/argparse stack, or when a pipeline is invoked externally
22
+ regardless of stack (cron calling a script, an orchestrator defined
23
+ outside this repo), there is no in-repo orchestrator to retry or
24
+ backfill through: merge `schedule` into `load` and scope it to
25
+ whatever the script itself can do (an idempotent upsert key, a
26
+ `--since`/`--backfill` flag `load` reads), and record retries/
27
+ scheduling as owned by the caller rather than as a gap in this layer.
21
28
  - Split `extract` per source (`extract/{module}`) when the pipeline pulls
22
29
  from several genuinely different systems with independent failure modes
23
30
  and auth; keep one `extract` layer for a single source.