@shrkcrft/inspector 0.1.0-alpha.25 → 0.1.0-alpha.26

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.
@@ -23,6 +23,14 @@ export declare enum ChangeArea {
23
23
  Tests = "tests",
24
24
  Examples = "examples",
25
25
  Scripts = "scripts",
26
+ /**
27
+ * Build / CI / tooling directories (`.github/`, `.husky/`, `ci/`, `tooling/`,
28
+ * `build/`). A generic, project-agnostic bucket so tooling paths stop
29
+ * falling through to {@link ChangeArea.Unknown}. Distinct from
30
+ * {@link ChangeArea.Config} (which is for manifest/config *files*) and from
31
+ * {@link ChangeArea.Scripts} (the dedicated `scripts/` area).
32
+ */
33
+ Tooling = "tooling",
26
34
  E2E = "e2e",
27
35
  Sharkcraft = "sharkcraft-self-config",
28
36
  Reports = "reports",
@@ -1 +1 @@
1
- {"version":3,"file":"changes-summary.d.ts","sourceRoot":"","sources":["../src/changes-summary.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"changes-summary.d.ts","sourceRoot":"","sources":["../src/changes-summary.ts"],"names":[],"mappings":"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"}
@@ -39,6 +39,14 @@ export var ChangeArea;
39
39
  ChangeArea["Tests"] = "tests";
40
40
  ChangeArea["Examples"] = "examples";
41
41
  ChangeArea["Scripts"] = "scripts";
42
+ /**
43
+ * Build / CI / tooling directories (`.github/`, `.husky/`, `ci/`, `tooling/`,
44
+ * `build/`). A generic, project-agnostic bucket so tooling paths stop
45
+ * falling through to {@link ChangeArea.Unknown}. Distinct from
46
+ * {@link ChangeArea.Config} (which is for manifest/config *files*) and from
47
+ * {@link ChangeArea.Scripts} (the dedicated `scripts/` area).
48
+ */
49
+ ChangeArea["Tooling"] = "tooling";
42
50
  ChangeArea["E2E"] = "e2e";
43
51
  ChangeArea["Sharkcraft"] = "sharkcraft-self-config";
44
52
  ChangeArea["Reports"] = "reports";
@@ -97,8 +105,59 @@ function classifyArea(file) {
97
105
  // doc as `unknown`.
98
106
  if (/\.mdx?$/i.test(file))
99
107
  return ChangeArea.Docs;
108
+ // NOTE: generic config / tooling / manifest paths are NOT resolved here. They
109
+ // are a FALLBACK layer applied by `buildAreaResolver` *after* the declared
110
+ // taxonomy (see `classifyConfigTooling`), so a project's own area declaration
111
+ // still wins for config paths it explicitly claims.
100
112
  return ChangeArea.Unknown;
101
113
  }
114
+ /**
115
+ * Built-in, project-AGNOSTIC config / tooling / manifest classifier.
116
+ *
117
+ * This is a FALLBACK layer: `buildAreaResolver` consults it only *after* the
118
+ * declared taxonomy (boundary `from` globs + monorepo package roots), so a
119
+ * project that explicitly claims a config path keeps its own area. It exists so
120
+ * the large slice of a typical changeset that is build / CI / tooling /
121
+ * manifest / config stops falling through to {@link ChangeArea.Unknown} — which
122
+ * (with its loud `unknown = taxonomy gap` diagnostic) is now reserved for
123
+ * *genuinely* unclassifiable paths.
124
+ *
125
+ * Ordering is deterministic and most-specific-wins: a recognized manifest /
126
+ * config *filename* (→ {@link ChangeArea.Config}) is matched before a generic
127
+ * tooling *directory* (→ {@link ChangeArea.Tooling}). Returns `undefined` when
128
+ * nothing matches so the caller can fall through to `unknown`.
129
+ */
130
+ function classifyConfigTooling(file) {
131
+ const base = file.slice(file.lastIndexOf('/') + 1).toLowerCase();
132
+ // Manifests / config files (matched by basename, at repo root or anywhere) →
133
+ // config. Covers: package.json, tsconfig*.json, *.config.{ts,js,mjs,cjs,json},
134
+ // nx.json, biome.json, .eslintrc*, .prettierrc*, bunfig.toml, lockfiles,
135
+ // .npmrc, .editorconfig.
136
+ if (base === 'package.json' ||
137
+ base === 'nx.json' ||
138
+ base === 'biome.json' ||
139
+ base === 'bunfig.toml' ||
140
+ base === '.npmrc' ||
141
+ base === '.editorconfig' ||
142
+ base === 'package-lock.json' ||
143
+ /^tsconfig(?:\..+)?\.json$/.test(base) ||
144
+ /\.config\.(?:ts|js|mjs|cjs|json)$/.test(base) ||
145
+ /^\.eslintrc(?:\..+)?$/.test(base) ||
146
+ /^\.prettierrc(?:\..+)?$/.test(base) ||
147
+ // Lockfiles: yarn.lock, pnpm-lock.yaml, bun.lock(b), *.lock / *.lockb.
148
+ base === 'pnpm-lock.yaml' ||
149
+ /\.lockb?$/.test(base)) {
150
+ return ChangeArea.Config;
151
+ }
152
+ // CI / build / tooling directories → tooling. (`scripts/` is intentionally
153
+ // handled earlier by `classifyArea` as its own dedicated area.) `build/` is
154
+ // treated as build *scripts*; genuine build *output* dirs (e.g. `dist/`) are
155
+ // not claimed here.
156
+ if (/(?:^|\/)(?:\.github|\.husky|ci|tooling|build)\//.test(file)) {
157
+ return ChangeArea.Tooling;
158
+ }
159
+ return undefined;
160
+ }
102
161
  /** Generic monorepo package/app root → area name. */
103
162
  const PACKAGE_ROOT_RE = /^(?:packages|apps|libs|modules|services)\/([^/]+)\//;
104
163
  /**
@@ -107,7 +166,11 @@ const PACKAGE_ROOT_RE = /^(?:packages|apps|libs|modules|services)\/([^/]+)\//;
107
166
  * 1. the built-in {@link classifyArea} slugs (nice names for this repo);
108
167
  * 2. the boundary gate's own `from` globs — the declared layer/area taxonomy;
109
168
  * 3. a generic monorepo package/app root (`packages/<name>/…` → `<name>`), so
110
- * a foreign monorepo's packages resolve instead of bucketing to `unknown`.
169
+ * a foreign monorepo's packages resolve instead of bucketing to `unknown`;
170
+ * 4. built-in, project-agnostic config / tooling / manifest patterns
171
+ * ({@link classifyConfigTooling}) — the FALLBACK layer that runs after the
172
+ * declared taxonomy so config paths (manifests, lockfiles, CI/build dirs)
173
+ * resolve to `config` / `tooling` instead of `unknown`.
111
174
  * A file only stays `unknown` when NONE of these match — and a high unknown rate
112
175
  * is surfaced as a self-diagnostic (`unknownRate`), not a low-risk diff.
113
176
  */
@@ -138,6 +201,11 @@ function buildAreaResolver(inspection) {
138
201
  const pkg = PACKAGE_ROOT_RE.exec(file);
139
202
  if (pkg?.[1])
140
203
  return pkg[1];
204
+ // Built-in config / tooling fallback — runs last, before `unknown`, so the
205
+ // declared taxonomy (steps 2–3) still wins where it applies.
206
+ const configTooling = classifyConfigTooling(file);
207
+ if (configTooling)
208
+ return configTooling;
141
209
  return ChangeArea.Unknown;
142
210
  };
143
211
  }
@@ -1 +1 @@
1
- {"version":3,"file":"registry-lifecycle.d.ts","sourceRoot":"","sources":["../src/registry-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,kCAAkC,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,EAAE,OAAO,CAAC;IACnB,gFAAgF;IAChF,QAAQ,EAAE,OAAO,CAAC;IAClB,gFAAgF;IAChF,WAAW,EAAE,OAAO,CAAC;IACrB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC3C,eAAe,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAC;IACxD;;;;OAIG;IACH,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAClD,OAAO,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACzC,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACxC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oCAAoC,EAAE,SAAS,MAAM,EAiBhE,CAAC;AA2NH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,GAAG,wBAAwB,CAyH3B;AAED,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAiD1F"}
1
+ {"version":3,"file":"registry-lifecycle.d.ts","sourceRoot":"","sources":["../src/registry-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,kCAAkC,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,EAAE,OAAO,CAAC;IACnB,gFAAgF;IAChF,QAAQ,EAAE,OAAO,CAAC;IAClB,gFAAgF;IAChF,WAAW,EAAE,OAAO,CAAC;IACrB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC3C,eAAe,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAC;IACxD;;;;OAIG;IACH,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAClD,OAAO,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACzC,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACxC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oCAAoC,EAAE,SAAS,MAAM,EAiBhE,CAAC;AAuOH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,GAAG,wBAAwB,CA6H3B;AAED,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAwD1F"}
@@ -50,7 +50,13 @@ function isGeneratedFile(file, content) {
50
50
  return true;
51
51
  return false;
52
52
  }
53
- function walk(dir, projectRoot, out, skipDirs) {
53
+ function walk(dir, projectRoot, out, skipDirs, deadline) {
54
+ // The wall-clock budget must bound the TREE WALK too, not only the per-file
55
+ // scan loop — a pathological tree could otherwise eat the whole budget before
56
+ // the loop's deadline check ever runs (a25 §2.5). Bail the walk on expiry;
57
+ // partial candidates flow through and the caller flags timedOut.
58
+ if (deadline !== undefined && Date.now() > deadline)
59
+ return;
54
60
  let entries;
55
61
  try {
56
62
  entries = readdirSync(dir, { withFileTypes: true });
@@ -59,6 +65,8 @@ function walk(dir, projectRoot, out, skipDirs) {
59
65
  return;
60
66
  }
61
67
  for (const e of entries) {
68
+ if (deadline !== undefined && Date.now() > deadline)
69
+ return;
62
70
  if (skipDirs.has(e.name))
63
71
  continue;
64
72
  if (e.name.startsWith('.') && e.name !== '.sharkcraft') {
@@ -68,7 +76,7 @@ function walk(dir, projectRoot, out, skipDirs) {
68
76
  }
69
77
  const abs = join(dir, e.name);
70
78
  if (e.isDirectory()) {
71
- walk(abs, projectRoot, out, skipDirs);
79
+ walk(abs, projectRoot, out, skipDirs, deadline);
72
80
  }
73
81
  else if (e.isFile() && SCAN_EXTENSIONS.has(extname(e.name))) {
74
82
  out.push(abs);
@@ -295,7 +303,7 @@ export function buildRegistryLifecycleReport(input) {
295
303
  else {
296
304
  const walkRoot = scope ? join(projectRoot, scope) : projectRoot;
297
305
  files = [];
298
- walk(walkRoot, projectRoot, files, skipDirs);
306
+ walk(walkRoot, projectRoot, files, skipDirs, deadline);
299
307
  }
300
308
  const scanFiles = files.slice(0, limit);
301
309
  const matchedPairs = [];
@@ -303,7 +311,11 @@ export function buildRegistryLifecycleReport(input) {
303
311
  const oneShotBootstrap = [];
304
312
  const ignored = [];
305
313
  let registersFound = 0;
306
- let timedOut = false;
314
+ // The tree walk itself is now deadline-bounded (a25 §2.5), so an exhausted
315
+ // budget can leave `scanFiles` empty and the per-file loop below would never
316
+ // run to set the flag. Seed it from the deadline so a walk-level timeout is
317
+ // reported (NOT-verified `2`) rather than read as a clean zero-registration pass.
318
+ let timedOut = Date.now() > deadline;
307
319
  let filesScanned = 0;
308
320
  for (const file of scanFiles) {
309
321
  // Hard wall-clock budget checked between files — the scan is synchronous, so
@@ -427,6 +439,13 @@ export function renderRegistryLifecycleReportText(report) {
427
439
  lines.push(` missing removers ${report.missingRemovers.length}`);
428
440
  lines.push(` one-shot bootstrap ${report.oneShotBootstrap.length}`);
429
441
  lines.push(` ignored ${report.ignored.length}`);
442
+ // Zero registrations in scope means nothing was actually checked — say so
443
+ // loudly so it never reads as the green "all removers present" pass (the exit
444
+ // code is NOT-verified `2` to match; a25 §1 / §2.5).
445
+ if (report.registersFound === 0 && !report.timedOut) {
446
+ lines.push('');
447
+ lines.push(' ! 0 registrations found in scope — lifecycle NOT verified (this is not a pass).');
448
+ }
430
449
  lines.push('');
431
450
  if (report.missingRemovers.length > 0) {
432
451
  lines.push('Missing removers:');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shrkcrft/inspector",
3
- "version": "0.1.0-alpha.25",
3
+ "version": "0.1.0-alpha.26",
4
4
  "description": "SharkCraft inspector: project overview, doctor checks, AI-agent instructions.",
5
5
  "license": "MIT",
6
6
  "author": "SharkCraft contributors",
@@ -42,22 +42,22 @@
42
42
  "typecheck": "tsc --noEmit -p tsconfig.json"
43
43
  },
44
44
  "dependencies": {
45
- "@shrkcrft/core": "^0.1.0-alpha.25",
46
- "@shrkcrft/config": "^0.1.0-alpha.25",
47
- "@shrkcrft/workspace": "^0.1.0-alpha.25",
48
- "@shrkcrft/knowledge": "^0.1.0-alpha.25",
49
- "@shrkcrft/rules": "^0.1.0-alpha.25",
50
- "@shrkcrft/paths": "^0.1.0-alpha.25",
51
- "@shrkcrft/templates": "^0.1.0-alpha.25",
52
- "@shrkcrft/context": "^0.1.0-alpha.25",
53
- "@shrkcrft/pipelines": "^0.1.0-alpha.25",
54
- "@shrkcrft/packs": "^0.1.0-alpha.25",
55
- "@shrkcrft/presets": "^0.1.0-alpha.25",
56
- "@shrkcrft/boundaries": "^0.1.0-alpha.25",
57
- "@shrkcrft/generator": "^0.1.0-alpha.25",
58
- "@shrkcrft/importer": "^0.1.0-alpha.25",
59
- "@shrkcrft/plugin-api": "^0.1.0-alpha.25",
60
- "@shrkcrft/dashboard-api": "^0.1.0-alpha.25",
45
+ "@shrkcrft/core": "^0.1.0-alpha.26",
46
+ "@shrkcrft/config": "^0.1.0-alpha.26",
47
+ "@shrkcrft/workspace": "^0.1.0-alpha.26",
48
+ "@shrkcrft/knowledge": "^0.1.0-alpha.26",
49
+ "@shrkcrft/rules": "^0.1.0-alpha.26",
50
+ "@shrkcrft/paths": "^0.1.0-alpha.26",
51
+ "@shrkcrft/templates": "^0.1.0-alpha.26",
52
+ "@shrkcrft/context": "^0.1.0-alpha.26",
53
+ "@shrkcrft/pipelines": "^0.1.0-alpha.26",
54
+ "@shrkcrft/packs": "^0.1.0-alpha.26",
55
+ "@shrkcrft/presets": "^0.1.0-alpha.26",
56
+ "@shrkcrft/boundaries": "^0.1.0-alpha.26",
57
+ "@shrkcrft/generator": "^0.1.0-alpha.26",
58
+ "@shrkcrft/importer": "^0.1.0-alpha.26",
59
+ "@shrkcrft/plugin-api": "^0.1.0-alpha.26",
60
+ "@shrkcrft/dashboard-api": "^0.1.0-alpha.26",
61
61
  "typescript": "^5.6.0"
62
62
  },
63
63
  "publishConfig": {