@skyf0xx/hedgehog 5.3.0 → 5.3.2

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
@@ -1302,9 +1302,10 @@ async function warnSingularModuleId(intent) {
1302
1302
 
1303
1303
  console.log(
1304
1304
  `\n${yellow(bold('Module id looks singular.'))} On this core the intent id is ${bold('{module}')} in\n` +
1305
- `every layer's scope, and the generators take it plural — so ${bold(intent.id)} compiles\n` +
1306
- `scope for ${bold(`${intent.id}/`)} while the scaffold command writes ${bold(`${intent.id}s/`)}.\n` +
1307
- `If ${bold(`${intent.id}s`)} is the name you meant, fix it now, before ${bold('hedgehog plan')}:\n` +
1305
+ `every layer's scope. On some cores the generator pluralizes it, so ${bold(intent.id)} would\n` +
1306
+ `compile scope for ${bold(`${intent.id}/`)} while the scaffold command writes ${bold(`${intent.id}s/`)} — worth\n` +
1307
+ `checking this core's own generator before ${bold('hedgehog plan')}. If ${bold(`${intent.id}s`)} is the name you\n` +
1308
+ `meant, it's still cheap to fix now:\n` +
1308
1309
  ` ${dim(`git mv ${INTENTS_DIR}/${intent.id}.json ${INTENTS_DIR}/${intent.id}s.json`)}\n` +
1309
1310
  ` ${dim(`# edit "id" and every ${intent.id.toUpperCase()}-* requirement id, then:`)}\n` +
1310
1311
  ` ${dim('hedgehog db rebuild')}\n`,
@@ -1352,11 +1353,12 @@ function warnSingularModuleIdsAtPlan(core, db) {
1352
1353
  console.log(
1353
1354
  `${yellow(bold(many ? `${singular.length} module ids look singular.` : 'Module id looks singular.'))} ` +
1354
1355
  `On this core an intent id is ${bold('{module}')} in\n` +
1355
- `every layer's scope, and the generators take it plural — so ${many ? 'each of these compiles' : 'this compiles'}\n` +
1356
- `scope for a directory the scaffold command will never write:\n` +
1357
- singular.map((id) => ` ${bold(id)} ${dim(`— scope ${id}/, scaffold writes ${id}s/`)}`).join('\n') +
1356
+ `every layer's scope. On some cores the generator pluralizes it, so ${many ? 'each of these would compile' : 'this would compile'}\n` +
1357
+ `scope for a directory the scaffold command might never write:\n` +
1358
+ singular.map((id) => ` ${bold(id)} ${dim(`— scope ${id}/, generator may instead write ${id}s/`)}`).join('\n') +
1358
1359
  `\n\nThis is a naming convention, not a rule — ${bold('billing')} and ${bold('search')} are ` +
1359
- `legitimately\nsingular. If the plural is what you meant, it is still cheap to fix:\n` +
1360
+ `legitimately\nsingular, and not every core's generator pluralizes at all check this core's own\n` +
1361
+ `generator before assuming it does. If the plural is what you meant, it is still cheap to fix:\n` +
1360
1362
  singular
1361
1363
  .map(
1362
1364
  (id) =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyf0xx/hedgehog",
3
- "version": "5.3.0",
3
+ "version": "5.3.2",
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": {
package/src/db/next.mjs CHANGED
@@ -394,14 +394,29 @@ export function scopePackageRoot(glob, module) {
394
394
  // `exists` is injected so this module keeps no filesystem dependency of
395
395
  // its own; the CLI passes a real one and the packet degrades to no
396
396
  // section when a caller supplies none.
397
+ //
398
+ // A layer can carry more than one glob into the same real package — e.g.
399
+ // `plugins/{module}/package.json` and `plugins/{module}/lib/**` both
400
+ // belong to one package, but the second glob's own literal prefix ends
401
+ // at `lib`, a build-output directory that never holds a `package.json`
402
+ // of its own. Naively treating every such root as first-arrival would
403
+ // flag `lib/` as a second package needing its own scaffold. A root
404
+ // nested under another of this task's own roots is never a package
405
+ // boundary — only the shallowest root in each chain is.
397
406
  export function firstArrivalPackages(task, exists) {
398
407
  if (!exists) return [];
399
- const roots = new Set();
408
+ const allRoots = new Set();
409
+ const missing = new Set();
400
410
  for (const glob of JSON.parse(task.scope_globs)) {
401
411
  const root = scopePackageRoot(glob, task.module);
402
- if (root && !exists(`${root}/package.json`)) roots.add(root);
412
+ if (!root) continue;
413
+ allRoots.add(root);
414
+ if (!exists(`${root}/package.json`)) missing.add(root);
403
415
  }
404
- return [...roots].sort();
416
+ const outermost = [...missing].filter(
417
+ (root) => ![...allRoots].some((other) => other !== root && root.startsWith(`${other}/`)),
418
+ );
419
+ return outermost.sort();
405
420
  }
406
421
 
407
422
  function firstArrivalLines(task, roots) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgehog",
3
- "version": "5.3.0",
3
+ "version": "5.3.2",
4
4
  "description": "Hedgehog build discipline: ordered, tested, verified build steps.",
5
5
  "contextFileName": "GEMINI.md"
6
6
  }
@@ -31,7 +31,7 @@
31
31
  "name": "deepseek-harness",
32
32
  "flag": "--deepseek-harness",
33
33
  "package": "@skyf0xx/hedgehog-core-deepseek-harness",
34
- "version": "^0.1.0",
34
+ "version": ">=0.1.0 <1.0.0",
35
35
  "language": "typescript",
36
36
  "repository": "https://github.com/skyf0xx/hedgehog-core-deepseek-harness",
37
37
  "selects_when": "The description names building a plugin, tool, hook, or extension for DeepSeek Harness (DSH) — a Cordis-based agent framework — or otherwise extending an existing DSH installation with new capabilities via its plugin/bundle system. Concrete signals: DSH, DeepSeek Harness, Cordis, `defineTool`, `ctx.tools.register`, a `cordis.patch.yml` manifest, or a request to add a tool that a DSH agent can call. This is the core most often confused with authored: authored fits when no shipped core matches and the planner must design a system shape from scratch, but a DSH plugin already has a fixed, battle-tested shape (the six-layer scaffold → logic → wiring → smoke → bundle → join sequence, one plugin per intent) that authored's from-scratch design would only reinvent worse. Route here whenever the target of the work is a DSH plugin, not a general \"no other core fits\" fallback."