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

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
  }
@@ -8,17 +8,34 @@
8
8
  * `shrk delegate explain` can show an author the fence is real before trusting
9
9
  * it. Pack-contributed recipes (Phase 4) will merge in here too.
10
10
  */
11
- import type { IDelegateRecipe, ISharkCraftConfig } from '@shrkcrft/config';
11
+ import { type DelegateRecipeMode, type IDelegateRecipe, type ISharkCraftConfig } from '@shrkcrft/config';
12
12
  export interface IResolvedDelegateRecipe extends IDelegateRecipe {
13
+ /**
14
+ * Recipe mode after defaulting (`'patch'` when unset). Explicit so downstream
15
+ * surfaces (doctor, list/explain, the analyze path) don't re-derive it.
16
+ */
17
+ mode: DelegateRecipeMode;
13
18
  /** Provider after applying the delegation-level default (never undefined). */
14
19
  resolvedProvider: 'auto' | 'ollama' | 'llamacpp';
15
20
  /** Model after applying the delegation-level default (undefined = provider default). */
16
21
  resolvedModel?: string;
17
- /** verificationIds that do NOT resolve to a `verificationCommands[].id`. */
22
+ /**
23
+ * (patch) The write-fence arrays, normalised to present (empty when unset) so
24
+ * patch consumers never juggle `undefined`. Analysis recipes leave them `[]`.
25
+ */
26
+ guardrailGlobs: readonly string[];
27
+ allowedOps: readonly string[];
28
+ verificationIds: readonly string[];
29
+ /** (patch) verificationIds that do NOT resolve to a `verificationCommands[].id`. */
18
30
  unboundVerificationIds: readonly string[];
19
- /** True when every verificationId resolves AND at least one is declared. */
31
+ /** (patch) True when every verificationId resolves AND at least one is declared. */
20
32
  verificationBound: boolean;
21
- /** True when the recipe is safe to delegate (verification fully bound). */
33
+ /** (analysis) True when `groundedOn` resolves to a known grounding report. */
34
+ groundingBound: boolean;
35
+ /**
36
+ * True when the recipe is safe to run — for a patch recipe, its verification is
37
+ * fully bound; for an analysis recipe, its grounding report is known.
38
+ */
22
39
  delegatable: boolean;
23
40
  /** Where the recipe came from. */
24
41
  source: 'config' | 'pack';
@@ -1 +1 @@
1
- {"version":3,"file":"delegate-catalog.d.ts","sourceRoot":"","sources":["../src/delegate-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC9D,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IACjD,wFAAwF;IACxF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4EAA4E;IAC5E,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,4EAA4E;IAC5E,iBAAiB,EAAE,OAAO,CAAC;IAC3B,2EAA2E;IAC3E,WAAW,EAAE,OAAO,CAAC;IACrB,kCAAkC;IAClC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,iBAAiB,EACzB,WAAW,GAAE,SAAS,gBAAgB,EAAO,GAC5C,SAAS,uBAAuB,EAAE,CAkCpC;AAED,gFAAgF;AAChF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,iBAAiB,EACzB,QAAQ,EAAE,MAAM,GACf,uBAAuB,GAAG,SAAS,CAErC"}
1
+ {"version":3,"file":"delegate-catalog.d.ts","sourceRoot":"","sources":["../src/delegate-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAA0B,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEjI,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC9D;;;OAGG;IACH,IAAI,EAAE,kBAAkB,CAAC;IACzB,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IACjD,wFAAwF;IACxF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,oFAAoF;IACpF,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,oFAAoF;IACpF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,8EAA8E;IAC9E,cAAc,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,kCAAkC;IAClC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,iBAAiB,EACzB,WAAW,GAAE,SAAS,gBAAgB,EAAO,GAC5C,SAAS,uBAAuB,EAAE,CAgDpC;AAED,gFAAgF;AAChF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,iBAAiB,EACzB,QAAQ,EAAE,MAAM,GACf,uBAAuB,GAAG,SAAS,CAErC"}
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Resolve the delegate-recipe catalog from a loaded config (read-only, NO model).
3
+ *
4
+ * Merges the delegation-level `provider`/`model` defaults into each recipe and
5
+ * checks every `verificationId` against the config's `verificationCommands[]`.
6
+ * A recipe is `delegatable` only when ALL its verification ids are bound — a
7
+ * recipe with an unbound (or empty) verification has no deterministic gate, so
8
+ * `shrk delegate explain` can show an author the fence is real before trusting
9
+ * it. Pack-contributed recipes (Phase 4) will merge in here too.
10
+ */
11
+ import { DELEGATE_GROUNDING_IDS } from '@shrkcrft/config';
1
12
  /**
2
13
  * Resolve the delegate catalog from config + pack-contributed recipes.
3
14
  *
@@ -29,15 +40,28 @@ export function resolveDelegateCatalog(config, packRecipes = []) {
29
40
  ...(ov?.verificationIds !== undefined ? { verificationIds: ov.verificationIds } : {}),
30
41
  ...(ov?.guardrailGlobs !== undefined ? { guardrailGlobs: ov.guardrailGlobs } : {}),
31
42
  };
43
+ const mode = merged.mode ?? 'patch';
32
44
  const unbound = (merged.verificationIds ?? []).filter((id) => !known.has(id));
33
45
  const verificationBound = unbound.length === 0 && (merged.verificationIds ?? []).length > 0;
46
+ const groundingBound = typeof merged.groundedOn === 'string' &&
47
+ DELEGATE_GROUNDING_IDS.includes(merged.groundedOn);
48
+ // A patch recipe is runnable when its verification binds; an analysis recipe
49
+ // when its grounding report is known. `delegatable` unifies "safe to run".
50
+ const delegatable = mode === 'analysis' ? groundingBound : verificationBound;
34
51
  out.push({
35
52
  ...merged,
53
+ mode,
54
+ // Normalise the write-fence arrays to present so patch consumers of the
55
+ // resolved recipe never juggle `undefined` (analysis recipes stay `[]`).
56
+ guardrailGlobs: merged.guardrailGlobs ?? [],
57
+ allowedOps: merged.allowedOps ?? [],
58
+ verificationIds: merged.verificationIds ?? [],
36
59
  resolvedProvider: merged.provider ?? delegation.provider ?? 'auto',
37
60
  ...(merged.model ?? delegation.model ? { resolvedModel: merged.model ?? delegation.model } : {}),
38
61
  unboundVerificationIds: unbound,
39
62
  verificationBound,
40
- delegatable: verificationBound,
63
+ groundingBound,
64
+ delegatable,
41
65
  source,
42
66
  ...(packageName ? { packageName } : {}),
43
67
  });
@@ -9,7 +9,7 @@
9
9
  * which can load pack files async); silent when the repo hasn't opted into
10
10
  * delegation.
11
11
  */
12
- import type { ISharkCraftConfig } from '@shrkcrft/config';
12
+ import { type ISharkCraftConfig } from '@shrkcrft/config';
13
13
  import { type IDoctorCheck } from './doctor-result.js';
14
14
  export declare function buildDelegateRecipeChecks(config: ISharkCraftConfig | null): IDoctorCheck[];
15
15
  //# sourceMappingURL=delegate-doctor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delegate-doctor.d.ts","sourceRoot":"","sources":["../src/delegate-doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,YAAY,EAAE,CAiC1F"}
1
+ {"version":3,"file":"delegate-doctor.d.ts","sourceRoot":"","sources":["../src/delegate-doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,GAAG,YAAY,EAAE,CAsE1F"}
@@ -1,3 +1,15 @@
1
+ /**
2
+ * `shrk doctor` checks for delegate-worker recipe health.
3
+ *
4
+ * Surfaces recipes that are NOT delegatable — a recipe whose `verificationIds`
5
+ * don't all resolve to `verificationCommands[]` (incl. after `recipeOverrides`)
6
+ * has no deterministic gate, so `shrk delegate run` would refuse it. `runDoctor`
7
+ * has no other surface for this (it doesn't run `validateConfig`), so this is the
8
+ * proactive catch. Sync + config-only (pack-recipe health is `delegate explain`,
9
+ * which can load pack files async); silent when the repo hasn't opted into
10
+ * delegation.
11
+ */
12
+ import { DELEGATE_QUERY_IDS } from '@shrkcrft/config';
1
13
  import { DoctorSeverity } from "./doctor-result.js";
2
14
  import { resolveDelegateCatalog } from "./delegate-catalog.js";
3
15
  export function buildDelegateRecipeChecks(config) {
@@ -9,26 +21,65 @@ export function buildDelegateRecipeChecks(config) {
9
21
  const out = [];
10
22
  const broken = catalog.filter((r) => !r.delegatable);
11
23
  for (const r of broken) {
12
- const reason = r.unboundVerificationIds.length > 0
13
- ? `verificationIds not in verificationCommands[]: ${r.unboundVerificationIds.join(', ')}`
14
- : 'no verificationIds declared';
24
+ const isAnalysis = r.mode === 'analysis';
25
+ const reason = isAnalysis
26
+ ? `groundedOn "${r.groundedOn ?? '(unset)'}" is not a known grounding report`
27
+ : r.unboundVerificationIds.length > 0
28
+ ? `verificationIds not in verificationCommands[]: ${r.unboundVerificationIds.join(', ')}`
29
+ : 'no verificationIds declared';
30
+ const consequence = isAnalysis
31
+ ? `\`shrk delegate analyze --recipe ${r.id}\` has no deterministic ground truth to check the model against.`
32
+ : `\`shrk delegate run --recipe ${r.id}\` would refuse to apply an unverified edit.`;
15
33
  out.push({
16
34
  id: `delegate-recipe-${r.id}`,
17
- title: `Delegate recipe "${r.id}" is not delegatable`,
35
+ title: `Delegate recipe "${r.id}" is not ${isAnalysis ? 'usable' : 'delegatable'}`,
18
36
  severity: DoctorSeverity.Warning,
19
- message: `${reason} — \`shrk delegate run --recipe ${r.id}\` would refuse to apply an unverified edit.`,
37
+ message: `${reason} — ${consequence}`,
20
38
  category: 'delegate',
21
- code: 'recipe-unverified',
39
+ code: isAnalysis ? 'recipe-ungrounded' : 'recipe-unverified',
22
40
  recommendedFix: `shrk delegate explain ${r.id}`,
23
- whyThisMatters: 'A recipe with an unbound verification has no deterministic gate; the worker can only run a VERIFIED edit, so the recipe is unusable until its verificationIds bind to a verificationCommands[] entry.',
41
+ whyThisMatters: isAnalysis
42
+ ? 'An analysis recipe grounds the model on a deterministic report; without a known groundedOn there is no ground truth to cross-check findings against, so the recipe is unusable.'
43
+ : 'A recipe with an unbound verification has no deterministic gate; the worker can only run a VERIFIED edit, so the recipe is unusable until its verificationIds bind to a verificationCommands[] entry.',
24
44
  });
25
45
  }
26
- if (broken.length === 0) {
46
+ // Analysis-recipe config health beyond grounding (validateConfig isn't run at
47
+ // load, so these would otherwise silently misbehave): unknown query ids and an
48
+ // escalateTo that doesn't resolve to a patch recipe.
49
+ const patchIds = new Set(catalog.filter((r) => r.mode !== 'analysis').map((r) => r.id));
50
+ for (const r of catalog) {
51
+ if (r.mode !== 'analysis')
52
+ continue;
53
+ const badQueries = (r.allowedQueries ?? []).filter((q) => !DELEGATE_QUERY_IDS.includes(q));
54
+ if (badQueries.length > 0) {
55
+ out.push({
56
+ id: `delegate-recipe-${r.id}-queries`,
57
+ title: `Delegate recipe "${r.id}" has unknown allowedQueries`,
58
+ severity: DoctorSeverity.Warning,
59
+ message: `${badQueries.join(', ')} — not in DELEGATE_QUERY_IDS (${DELEGATE_QUERY_IDS.join(', ')}); the model can never call them.`,
60
+ category: 'delegate',
61
+ code: 'recipe-unknown-query',
62
+ recommendedFix: `shrk delegate explain ${r.id}`,
63
+ });
64
+ }
65
+ if (r.escalateTo !== undefined && !patchIds.has(r.escalateTo)) {
66
+ out.push({
67
+ id: `delegate-recipe-${r.id}-escalate`,
68
+ title: `Delegate recipe "${r.id}" escalates to a non-patch recipe`,
69
+ severity: DoctorSeverity.Warning,
70
+ message: `escalateTo "${r.escalateTo}" is not an existing patch recipe — \`--escalate\` would be a no-op.`,
71
+ category: 'delegate',
72
+ code: 'recipe-bad-escalation',
73
+ recommendedFix: `shrk delegate explain ${r.id}`,
74
+ });
75
+ }
76
+ }
77
+ if (out.length === 0) {
27
78
  out.push({
28
79
  id: 'delegate-recipes',
29
80
  title: 'Delegate recipes',
30
81
  severity: DoctorSeverity.Ok,
31
- message: `${catalog.length} delegate recipe(s) configured, all delegatable.`,
82
+ message: `${catalog.length} delegate recipe(s) configured, all healthy.`,
32
83
  category: 'delegate',
33
84
  });
34
85
  }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Delegate ANALYSIS grounding (read-only, deterministic — NO model).
3
+ *
4
+ * An `analysis` delegate recipe grounds a local model's judgment on a
5
+ * deterministic report the engine runs FIRST. This module:
6
+ * 1. runs that report (`runGroundingReport`) and distils it to a compact
7
+ * summary + a set of known entities (files / constructs / reason codes);
8
+ * 2. cross-checks the model's findings against those entities
9
+ * (`crossCheckFindings`) — a finding that cites an entity absent from the
10
+ * ground truth is flagged `unverified` (or dropped, in strict mode), so the
11
+ * model can prioritise/explain but never fabricate a fact;
12
+ * 3. assembles the honest, advisory `IDelegateAnalysisReport`
13
+ * (`buildDelegateAnalysisReport`) — which NEVER writes.
14
+ *
15
+ * The model call itself happens in the cli orchestrator, not here (this layer is
16
+ * pure). MCP surfaces only the grounding, never the model — see the safety model.
17
+ */
18
+ import type { DelegateGroundingId } from '@shrkcrft/core';
19
+ import { type IBuildTaskRiskOptions } from './task-risk.js';
20
+ import { type IUncertaintyReport } from './uncertainty-report.js';
21
+ import type { ISharkcraftInspection } from './sharkcraft-inspector.js';
22
+ export declare const DELEGATE_ANALYSIS_SCHEMA = "sharkcraft.delegate-analysis/v1";
23
+ /** The deterministic ground truth an analysis recipe is checked against. */
24
+ export interface IGroundingFacts {
25
+ groundedOn: string;
26
+ /** Compact human-readable summary fed to the model as ground truth. */
27
+ summary: string;
28
+ /** Known entities (normalised references the model may legitimately cite). */
29
+ entities: readonly string[];
30
+ /** The underlying deterministic report (surfaced in `--json`). */
31
+ raw: unknown;
32
+ }
33
+ /** One model finding, tagged by the deterministic cross-check. */
34
+ export interface IAnalysisFinding {
35
+ id: string;
36
+ message: string;
37
+ /** Entities the model cited (explicit refs, or refs inferred from the message). */
38
+ refs: readonly string[];
39
+ /** True when the finding is anchored to ground truth (via refs or a message mention). */
40
+ grounded: boolean;
41
+ /** Cited refs NOT present in the ground truth. */
42
+ unverifiedRefs: readonly string[];
43
+ }
44
+ /** The read-only advisory report an `analysis` recipe produces. */
45
+ export interface IDelegateAnalysisReport {
46
+ schema: typeof DELEGATE_ANALYSIS_SCHEMA;
47
+ generatedAt: string;
48
+ recipeId: string;
49
+ mode: 'analysis';
50
+ groundedOn: string;
51
+ task: string;
52
+ /** Which provider produced the findings (`'none'` = deterministic-only). */
53
+ provider: string;
54
+ grounding: {
55
+ summary: string;
56
+ entityCount: number;
57
+ };
58
+ findings: readonly IAnalysisFinding[];
59
+ groundedCount: number;
60
+ unverifiedCount: number;
61
+ /** Optional free-form note from the model (informational, never grounded). */
62
+ modelNote?: string;
63
+ /** How many read-only query rounds the model ran (Phase 3 query loop). */
64
+ queriesRun?: number;
65
+ /** How many fan-out slices ran (Phase 4), when fan-out was used. */
66
+ fanOutSlices?: number;
67
+ /** Advisory escalation into a patch recipe, when the recipe declares escalateTo. */
68
+ escalation?: {
69
+ recipe: string;
70
+ task: string;
71
+ next: string;
72
+ };
73
+ markdown: string;
74
+ uncertainty: IUncertaintyReport;
75
+ }
76
+ /**
77
+ * A layer-neutral snapshot of a failed delegate PATCH attempt — the ground truth
78
+ * a `retry-analysis` recipe reasons over. Kept primitive (no dependency on the
79
+ * cli-layer `IExecuteDelegateRunResult`) so the cli maps its result onto this and
80
+ * the inspector grounds on it without an upward import.
81
+ */
82
+ export interface IDelegateFailureContext {
83
+ /** The failing status, e.g. `verify-failed` / `conflicts` / `guardrail-refused`. */
84
+ status: string;
85
+ message: string;
86
+ conflicts?: readonly string[];
87
+ commandsFailed?: readonly string[];
88
+ refused?: readonly string[];
89
+ droppedOps?: readonly {
90
+ kind: string;
91
+ targetPath: string;
92
+ }[];
93
+ guardrailGlobs?: readonly string[];
94
+ allowedOps?: readonly string[];
95
+ /** 1-based attempt number this failure occurred on. */
96
+ attempt?: number;
97
+ }
98
+ /** Options for `runGroundingReport` — task-risk knobs plus grounding payloads. */
99
+ export interface IRunGroundingOptions extends IBuildTaskRiskOptions {
100
+ /** Required when grounding on `delegate-failure`. */
101
+ failure?: IDelegateFailureContext;
102
+ /** Required when grounding on `plan-simulation` — path to a saved plan. */
103
+ planPath?: string;
104
+ }
105
+ /** Distil a delegate patch failure into ground truth for `retry-analysis`. */
106
+ export declare function buildDelegateFailureFacts(failure: IDelegateFailureContext): IGroundingFacts;
107
+ /**
108
+ * Run the deterministic report an analysis recipe grounds on, distilled to a
109
+ * compact summary + the entities a finding may legitimately cite. Read-only.
110
+ */
111
+ export declare function runGroundingReport(groundedOn: DelegateGroundingId | string, task: string, inspection: ISharkcraftInspection, options?: IRunGroundingOptions): Promise<IGroundingFacts>;
112
+ export interface ICrossCheckOptions {
113
+ /** Drop non-grounded findings instead of keeping+flagging them. */
114
+ strict?: boolean;
115
+ }
116
+ export interface ICrossCheckResult {
117
+ findings: IAnalysisFinding[];
118
+ groundedCount: number;
119
+ unverifiedCount: number;
120
+ }
121
+ /**
122
+ * Cross-check model findings against the deterministic ground truth. A finding is
123
+ * `grounded` when it cites ≥1 ref that all resolve to a report entity, OR — when
124
+ * it cites no explicit refs — when its MESSAGE mentions a ground-truth entity
125
+ * verbatim (models routinely state facts in prose without filling a refs array;
126
+ * the live smoke showed exactly this). A claim anchored to nothing in the ground
127
+ * truth stays unverified — judgment must ride on facts the model cannot fabricate.
128
+ */
129
+ export declare function crossCheckFindings(rawFindings: readonly {
130
+ id?: string;
131
+ message: string;
132
+ refs?: readonly string[];
133
+ }[], facts: IGroundingFacts, options?: ICrossCheckOptions): ICrossCheckResult;
134
+ export interface IBuildAnalysisReportInput {
135
+ recipeId: string;
136
+ groundedOn: string;
137
+ task: string;
138
+ provider: string;
139
+ facts: IGroundingFacts;
140
+ crossCheck: ICrossCheckResult;
141
+ modelNote?: string;
142
+ /** True when no local model ran — the report is deterministic grounding only. */
143
+ modelUnavailable?: boolean;
144
+ /** Read-only query rounds the model ran (Phase 3), when the query loop was used. */
145
+ queriesRun?: number;
146
+ /** Fan-out slices that ran (Phase 4), when fan-out was used. */
147
+ fanOutSlices?: number;
148
+ /** A patch recipe this analysis may escalate to (Phase 4, advisory). */
149
+ escalateTo?: string;
150
+ generatedAt: string;
151
+ }
152
+ /** Assemble the honest, advisory analysis report. Never writes. */
153
+ export declare function buildDelegateAnalysisReport(input: IBuildAnalysisReportInput): IDelegateAnalysisReport;
154
+ //# sourceMappingURL=delegate-grounding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate-grounding.d.ts","sourceRoot":"","sources":["../src/delegate-grounding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,427 @@
1
+ import { buildTaskRiskReport } from "./task-risk.js";
2
+ import { analyzeTestImpact } from "./test-impact.js";
3
+ import { simulatePlan } from "./plan-simulation.js";
4
+ import { buildAgentBrief } from "./agent-brief.js";
5
+ import * as nodePath from 'node:path';
6
+ import { buildUncertaintyReport } from "./uncertainty-report.js";
7
+ export const DELEGATE_ANALYSIS_SCHEMA = 'sharkcraft.delegate-analysis/v1';
8
+ function norm(s) {
9
+ // Strip surrounding delimiters/punctuation so a model that echoes a ground-truth
10
+ // display form (`[intent-migration]`, `` `src/foo.ts` ``) still matches the bare
11
+ // entity — otherwise a legitimate citation is falsely flagged `unverified`.
12
+ return s
13
+ .trim()
14
+ .toLowerCase()
15
+ .replace(/^[[\](){}`'"]+/, '')
16
+ .replace(/[[\](){}`'".,;:]+$/, '');
17
+ }
18
+ function basename(s) {
19
+ const n = norm(s);
20
+ const i = n.lastIndexOf('/');
21
+ return i >= 0 ? n.slice(i + 1) : n;
22
+ }
23
+ function looksLikePath(s) {
24
+ return /[\/.]/.test(s) && /\.(ts|tsx|js|jsx|mjs|cjs|md|json|ya?ml)$/i.test(s.trim());
25
+ }
26
+ /** Distil a task-risk report into the entities a finding may legitimately cite. */
27
+ function groundingEntitiesFromTaskRisk(r) {
28
+ const out = new Set();
29
+ const add = (xs) => {
30
+ for (const x of xs)
31
+ if (x && x.trim().length > 0)
32
+ out.add(x.trim());
33
+ };
34
+ add(r.affectedFiles);
35
+ add(r.highFanInFiles);
36
+ add(r.highFanOutFiles);
37
+ add(r.affectedConstructs);
38
+ add(r.reasons.map((x) => x.code));
39
+ add(r.ownershipGaps.filter(looksLikePath));
40
+ return [...out];
41
+ }
42
+ /** The path in a `"path: reason"` conflict string (the citable entity). */
43
+ function conflictPath(c) {
44
+ const i = c.indexOf(':');
45
+ return (i >= 0 ? c.slice(0, i) : c).trim();
46
+ }
47
+ /** Distil a delegate patch failure into ground truth for `retry-analysis`. */
48
+ export function buildDelegateFailureFacts(failure) {
49
+ const entities = new Set();
50
+ const add = (xs) => {
51
+ for (const x of xs ?? [])
52
+ if (x && x.trim().length > 0)
53
+ entities.add(x.trim());
54
+ };
55
+ add((failure.conflicts ?? []).map(conflictPath));
56
+ add(failure.refused);
57
+ add((failure.droppedOps ?? []).map((d) => d.targetPath));
58
+ add(failure.commandsFailed);
59
+ add(failure.allowedOps);
60
+ entities.add(failure.status);
61
+ const lines = [];
62
+ lines.push(`Delegate patch attempt failed: ${failure.status}${failure.attempt ? ` (attempt ${failure.attempt})` : ''}.`);
63
+ lines.push(`Message: ${failure.message}`);
64
+ if (failure.conflicts?.length)
65
+ lines.push(`Conflicts: ${failure.conflicts.join('; ')}.`);
66
+ if (failure.commandsFailed?.length)
67
+ lines.push(`Verification commands failed: ${failure.commandsFailed.join(', ')}.`);
68
+ if (failure.refused?.length)
69
+ lines.push(`Targets refused (outside guardrail globs): ${failure.refused.join(', ')}.`);
70
+ if (failure.droppedOps?.length) {
71
+ lines.push(`Ops dropped (kind not allowed): ${failure.droppedOps.map((d) => `${d.kind}→${d.targetPath}`).join(', ')}.`);
72
+ }
73
+ if (failure.allowedOps?.length)
74
+ lines.push(`Only these op kinds are allowed: ${failure.allowedOps.join(', ')}.`);
75
+ if (failure.guardrailGlobs?.length)
76
+ lines.push(`Only these globs may be touched: ${failure.guardrailGlobs.join(', ')}.`);
77
+ return { groundedOn: 'delegate-failure', summary: lines.join('\n'), entities: [...entities], raw: failure };
78
+ }
79
+ /** Entities + summary for grounding on the agent brief. */
80
+ function groundingFromAgentBrief(b) {
81
+ const entities = new Set();
82
+ if (b.taskRisk) {
83
+ for (const f of b.taskRisk.affectedFiles)
84
+ entities.add(f);
85
+ for (const c of b.taskRisk.affectedConstructs)
86
+ entities.add(c);
87
+ for (const f of b.taskRisk.highFanInFiles)
88
+ entities.add(f);
89
+ }
90
+ const risk = b.taskRisk ? `Risk: ${b.taskRisk.riskLevel} (score ${b.taskRisk.score}). ` : '';
91
+ const summary = `Agent brief for: ${b.task}\n${risk}\n${b.markdown.slice(0, 1400)}`;
92
+ return { summary, entities: [...entities].filter((x) => x.trim().length > 0) };
93
+ }
94
+ /** Entities a finding may cite when grounded on a test-impact report. */
95
+ function groundingEntitiesFromTestImpact(t) {
96
+ const out = new Set();
97
+ const add = (xs) => {
98
+ for (const x of xs)
99
+ if (x && x.trim().length > 0)
100
+ out.add(x.trim());
101
+ };
102
+ add(t.inputFiles);
103
+ add(t.likelyTestFiles);
104
+ add(t.missingTestFiles);
105
+ add(t.riskAreas);
106
+ return [...out];
107
+ }
108
+ /** Entities a finding may cite when grounded on a plan simulation. */
109
+ function groundingEntitiesFromPlanSim(p) {
110
+ const out = new Set();
111
+ const add = (xs) => {
112
+ for (const x of xs)
113
+ if (x && x.trim().length > 0)
114
+ out.add(x.trim());
115
+ };
116
+ add(p.files.map((f) => f.relativePath));
117
+ add(p.affectedAreas);
118
+ add(p.affectedConstructs);
119
+ add(p.ownershipReviewFiles);
120
+ add(p.likelyTests);
121
+ return [...out];
122
+ }
123
+ /** A compact ground-truth summary of a plan simulation for the model prompt. */
124
+ function compactPlanSimSummary(p) {
125
+ const lines = [];
126
+ lines.push(`Plan: ${p.source} (${p.templateId ?? 'no-template'}), signature ${p.signature}, readiness ${p.applyReadiness}.`);
127
+ if (p.files.length > 0)
128
+ lines.push(`Files: ${p.files.map((f) => `${f.changeType} ${f.relativePath}`).slice(0, 12).join(', ')}.`);
129
+ if (p.publicApiTouched)
130
+ lines.push('Touches a public API surface.');
131
+ if (p.ownershipReviewRequired)
132
+ lines.push(`Ownership review required: ${p.ownershipReviewFiles.slice(0, 6).join(', ')}.`);
133
+ if (p.potentialBoundaryConcerns.length > 0)
134
+ lines.push(`Boundary concerns: ${p.potentialBoundaryConcerns.length}.`);
135
+ if (p.policyConcerns.length > 0)
136
+ lines.push(`Policy concerns: ${p.policyConcerns.slice(0, 6).join('; ')}.`);
137
+ if (p.applyReadinessReasons.length > 0)
138
+ lines.push(`Readiness reasons: ${p.applyReadinessReasons.slice(0, 6).join('; ')}.`);
139
+ return lines.join('\n');
140
+ }
141
+ /** A compact ground-truth summary of a test-impact report for the model prompt. */
142
+ function compactTestImpactSummary(t) {
143
+ const lines = [];
144
+ lines.push(`Test impact for: ${t.task || '(repo)'} (confidence ${t.confidence}).`);
145
+ if (t.likelyTestFiles.length > 0)
146
+ lines.push(`Existing tests: ${t.likelyTestFiles.slice(0, 12).join(', ')}.`);
147
+ if (t.missingTestFiles.length > 0)
148
+ lines.push(`Missing tests (expected locations): ${t.missingTestFiles.slice(0, 12).join(', ')}.`);
149
+ if (t.riskAreas.length > 0)
150
+ lines.push(`Risk areas: ${t.riskAreas.slice(0, 8).join('; ')}.`);
151
+ if (t.minimalCommands.length > 0)
152
+ lines.push(`Minimal test command(s): ${t.minimalCommands.join(' ; ')}.`);
153
+ return lines.join('\n');
154
+ }
155
+ /** A compact ground-truth summary for the model prompt (not the full report). */
156
+ function compactTaskRiskSummary(r) {
157
+ const lines = [];
158
+ lines.push(`Task risk: ${r.riskLevel} (score ${r.score}), intent ${r.intent.kind}.`);
159
+ lines.push(`Human approval required: ${r.humanApprovalRequired ? 'yes' : 'no'}.`);
160
+ if (r.affectedFiles.length > 0)
161
+ lines.push(`Affected files: ${r.affectedFiles.slice(0, 12).join(', ')}.`);
162
+ if (r.highFanInFiles.length > 0)
163
+ lines.push(`High fan-in: ${r.highFanInFiles.join(', ')}.`);
164
+ if (r.boundaryConcerns.length > 0)
165
+ lines.push(`Boundary concerns: ${r.boundaryConcerns.slice(0, 6).join('; ')}.`);
166
+ if (r.policyConcerns.length > 0)
167
+ lines.push(`Policy concerns: ${r.policyConcerns.slice(0, 6).join('; ')}.`);
168
+ if (r.testGaps.length > 0)
169
+ lines.push(`Test gaps: ${r.testGaps.slice(0, 6).join('; ')}.`);
170
+ lines.push('Reasons:');
171
+ for (const reason of r.reasons.slice(0, 12))
172
+ lines.push(` - [${reason.code}] ${reason.message} (+${reason.weight})`);
173
+ return lines.join('\n');
174
+ }
175
+ /**
176
+ * Run the deterministic report an analysis recipe grounds on, distilled to a
177
+ * compact summary + the entities a finding may legitimately cite. Read-only.
178
+ */
179
+ export async function runGroundingReport(groundedOn, task, inspection, options = {}) {
180
+ switch (groundedOn) {
181
+ case 'task-risk': {
182
+ const r = await buildTaskRiskReport(task, inspection, options);
183
+ return {
184
+ groundedOn,
185
+ summary: compactTaskRiskSummary(r),
186
+ entities: groundingEntitiesFromTaskRisk(r),
187
+ raw: r,
188
+ };
189
+ }
190
+ case 'test-impact': {
191
+ const t = analyzeTestImpact(inspection, { task });
192
+ return {
193
+ groundedOn,
194
+ summary: compactTestImpactSummary(t),
195
+ entities: groundingEntitiesFromTestImpact(t),
196
+ raw: t,
197
+ };
198
+ }
199
+ case 'agent-brief': {
200
+ const b = await buildAgentBrief(inspection, { task });
201
+ const { summary, entities } = groundingFromAgentBrief(b);
202
+ return { groundedOn, summary, entities, raw: b };
203
+ }
204
+ case 'plan-simulation': {
205
+ // Grounded on a saved plan the cli supplies via `options.planPath`. Absent
206
+ // it (or on a read error) there is nothing to critique.
207
+ if (!options.planPath) {
208
+ return { groundedOn, summary: '(plan-simulation grounding needs a --plan <path>)', entities: [], raw: null };
209
+ }
210
+ try {
211
+ const abs = nodePath.isAbsolute(options.planPath)
212
+ ? options.planPath
213
+ : nodePath.resolve(inspection.projectRoot, options.planPath);
214
+ const p = await simulatePlan(inspection, abs, { includeBoundaries: true, includeImpact: true, includeOwnership: true });
215
+ return { groundedOn, summary: compactPlanSimSummary(p), entities: groundingEntitiesFromPlanSim(p), raw: p };
216
+ }
217
+ catch (e) {
218
+ return { groundedOn, summary: `(could not simulate plan: ${e.message})`, entities: [], raw: null };
219
+ }
220
+ }
221
+ case 'delegate-failure':
222
+ // Grounded on a failed patch attempt — the cli supplies the failure via
223
+ // `options.failure` (this grounding needs no inspection). Absent it, there
224
+ // is nothing to reason over (e.g. a standalone MCP/CLI call with no failure).
225
+ return options.failure
226
+ ? buildDelegateFailureFacts(options.failure)
227
+ : {
228
+ groundedOn,
229
+ summary: '(delegate-failure grounding needs a failure context — run it in the delegate retry loop)',
230
+ entities: [],
231
+ raw: null,
232
+ };
233
+ default:
234
+ // Config validation gates `groundedOn` to a known id, so this is a
235
+ // defensive fallback (empty ground truth ⇒ every claim is unverified).
236
+ return { groundedOn, summary: `(no grounding runner for "${groundedOn}")`, entities: [], raw: null };
237
+ }
238
+ }
239
+ /**
240
+ * Cross-check model findings against the deterministic ground truth. A finding is
241
+ * `grounded` when it cites ≥1 ref that all resolve to a report entity, OR — when
242
+ * it cites no explicit refs — when its MESSAGE mentions a ground-truth entity
243
+ * verbatim (models routinely state facts in prose without filling a refs array;
244
+ * the live smoke showed exactly this). A claim anchored to nothing in the ground
245
+ * truth stays unverified — judgment must ride on facts the model cannot fabricate.
246
+ */
247
+ export function crossCheckFindings(rawFindings, facts, options = {}) {
248
+ const entities = new Set(facts.entities.map(norm));
249
+ const basenames = new Set(facts.entities.map(basename));
250
+ const resolves = (ref) => entities.has(norm(ref)) || basenames.has(basename(ref));
251
+ // Entities long enough to match unambiguously inside prose (avoid noise from
252
+ // very short codes). Matched case-insensitively as a substring of the message.
253
+ const scannable = facts.entities.filter((e) => e.trim().length >= 4);
254
+ const mentionedIn = (message) => {
255
+ const m = message.toLowerCase();
256
+ const hits = [];
257
+ for (const e of scannable) {
258
+ const en = e.toLowerCase();
259
+ const bn = basename(e);
260
+ if (m.includes(en) || (bn.length >= 4 && m.includes(bn)))
261
+ hits.push(e);
262
+ }
263
+ return hits;
264
+ };
265
+ const findings = [];
266
+ let groundedCount = 0;
267
+ let unverifiedCount = 0;
268
+ for (let i = 0; i < rawFindings.length; i += 1) {
269
+ const rf = rawFindings[i];
270
+ const explicit = (rf.refs ?? []).map((r) => String(r));
271
+ let refs = explicit;
272
+ let unverifiedRefs = explicit.filter((r) => !resolves(r));
273
+ let grounded = explicit.length > 0 && unverifiedRefs.length === 0;
274
+ if (!grounded && explicit.length === 0) {
275
+ // Fallback: the model stated facts in prose. Infer refs from the message.
276
+ const inferred = mentionedIn(rf.message);
277
+ if (inferred.length > 0) {
278
+ refs = inferred;
279
+ unverifiedRefs = [];
280
+ grounded = true;
281
+ }
282
+ }
283
+ if (options.strict && !grounded) {
284
+ unverifiedCount += 1;
285
+ continue; // dropped
286
+ }
287
+ findings.push({
288
+ id: rf.id?.trim() || `finding-${i + 1}`,
289
+ message: rf.message,
290
+ refs,
291
+ grounded,
292
+ unverifiedRefs,
293
+ });
294
+ if (grounded)
295
+ groundedCount += 1;
296
+ else
297
+ unverifiedCount += 1;
298
+ }
299
+ return { findings, groundedCount, unverifiedCount };
300
+ }
301
+ function buildAnalysisUncertainty(input) {
302
+ const { crossCheck, modelUnavailable } = input;
303
+ let confidence = 'medium';
304
+ const reasons = [];
305
+ const missing = [];
306
+ if (modelUnavailable) {
307
+ confidence = 'unknown';
308
+ reasons.push('No local LLM reachable — deterministic grounding only, no judgment layer.');
309
+ missing.push({ id: 'no-model', message: 'No local model produced findings.' });
310
+ }
311
+ else if (crossCheck.findings.length === 0) {
312
+ confidence = 'low';
313
+ reasons.push('The model returned no findings.');
314
+ }
315
+ else if (crossCheck.unverifiedCount > crossCheck.groundedCount) {
316
+ confidence = 'low';
317
+ reasons.push(`${crossCheck.unverifiedCount} of ${crossCheck.findings.length} finding(s) are unverified (cite entities absent from the ground truth).`);
318
+ }
319
+ if (input.facts.entities.length === 0) {
320
+ missing.push({ id: 'empty-grounding', message: 'The grounding report yielded no entities to check against.' });
321
+ }
322
+ return buildUncertaintyReport({
323
+ confidence,
324
+ reasons,
325
+ missingSignals: missing,
326
+ suggestedCommands: [`shrk risk "${input.task || '<task>'}"`, `shrk delegate explain ${input.recipeId}`],
327
+ safeFallbackCommand: `shrk risk "${input.task || '<task>'}"`,
328
+ });
329
+ }
330
+ function renderAnalysisMarkdown(input) {
331
+ const { crossCheck, facts } = input;
332
+ const lines = [];
333
+ lines.push(`# Delegate analysis — ${input.recipeId}`);
334
+ lines.push('');
335
+ lines.push(`- task: ${input.task || '(none)'}`);
336
+ lines.push(`- grounded on: **${input.groundedOn}**`);
337
+ lines.push(`- provider: ${input.provider}`);
338
+ if (input.queriesRun !== undefined)
339
+ lines.push(`- query rounds: ${input.queriesRun} (read-only fact-fetch loop)`);
340
+ if (input.fanOutSlices !== undefined)
341
+ lines.push(`- fan-out slices: ${input.fanOutSlices} (per-slice passes, merged)`);
342
+ lines.push(`- findings: ${crossCheck.findings.length} (grounded ${crossCheck.groundedCount}, unverified ${crossCheck.unverifiedCount})`);
343
+ lines.push('');
344
+ lines.push('## Ground truth');
345
+ lines.push('');
346
+ lines.push(facts.summary);
347
+ lines.push('');
348
+ lines.push('## Findings');
349
+ lines.push('');
350
+ if (crossCheck.findings.length === 0) {
351
+ lines.push(input.modelUnavailable
352
+ ? '_No local LLM reachable — deterministic grounding only. Start Ollama / set LLAMACPP_MODEL_PATH to add the judgment layer._'
353
+ : '_(none)_');
354
+ }
355
+ else {
356
+ for (const f of crossCheck.findings) {
357
+ const tag = f.grounded ? '✓ grounded' : '⚠ unverified';
358
+ lines.push(`- **[${tag}]** ${f.message}`);
359
+ if (f.refs.length > 0)
360
+ lines.push(` - refs: ${f.refs.join(', ')}`);
361
+ if (f.unverifiedRefs.length > 0)
362
+ lines.push(` - not in ground truth: ${f.unverifiedRefs.join(', ')}`);
363
+ }
364
+ }
365
+ if (input.modelNote) {
366
+ lines.push('');
367
+ lines.push('## Model note (informational)');
368
+ lines.push('');
369
+ lines.push(input.modelNote);
370
+ }
371
+ const escalation = escalationHint(input);
372
+ if (escalation) {
373
+ lines.push('');
374
+ lines.push('## Suggested escalation (advisory — you run it)');
375
+ lines.push('');
376
+ lines.push(`This gap can be handed to the patch recipe \`${escalation.recipe}\`:`);
377
+ lines.push('```');
378
+ lines.push(escalation.next);
379
+ lines.push('```');
380
+ }
381
+ lines.push('');
382
+ lines.push('---');
383
+ lines.push('_Advisory, read-only — no write performed. Findings tagged `unverified` cite entities absent from the deterministic ground truth; treat them as hypotheses, not facts._');
384
+ return lines.join('\n');
385
+ }
386
+ /** Assemble the honest, advisory analysis report. Never writes. */
387
+ export function buildDelegateAnalysisReport(input) {
388
+ const report = {
389
+ schema: DELEGATE_ANALYSIS_SCHEMA,
390
+ generatedAt: input.generatedAt,
391
+ recipeId: input.recipeId,
392
+ mode: 'analysis',
393
+ groundedOn: input.groundedOn,
394
+ task: input.task,
395
+ provider: input.provider,
396
+ grounding: { summary: input.facts.summary, entityCount: input.facts.entities.length },
397
+ findings: input.crossCheck.findings,
398
+ groundedCount: input.crossCheck.groundedCount,
399
+ unverifiedCount: input.crossCheck.unverifiedCount,
400
+ markdown: renderAnalysisMarkdown(input),
401
+ uncertainty: buildAnalysisUncertainty(input),
402
+ };
403
+ if (input.modelNote)
404
+ report.modelNote = input.modelNote;
405
+ if (input.queriesRun !== undefined)
406
+ report.queriesRun = input.queriesRun;
407
+ if (input.fanOutSlices !== undefined)
408
+ report.fanOutSlices = input.fanOutSlices;
409
+ const escalation = escalationHint(input);
410
+ if (escalation)
411
+ report.escalation = escalation;
412
+ return report;
413
+ }
414
+ /** Advisory next-command into a patch recipe, when findings warrant escalation. */
415
+ function escalationHint(input) {
416
+ if (!input.escalateTo)
417
+ return undefined;
418
+ const anchor = input.crossCheck.findings.find((f) => f.grounded) ?? input.crossCheck.findings[0];
419
+ if (!anchor)
420
+ return undefined;
421
+ const task = anchor.message.slice(0, 120);
422
+ return {
423
+ recipe: input.escalateTo,
424
+ task,
425
+ next: `shrk delegate run "${task}" --recipe ${input.escalateTo} --apply`,
426
+ };
427
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"docs-check.d.ts","sourceRoot":"","sources":["../src/docs-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,eAAO,MAAM,iBAAiB,6BAA6B,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EACA,sBAAsB,GACtB,wBAAwB,GACxB,oBAAoB,GACpB,0BAA0B,GAC1B,gCAAgC,GAChC,yBAAyB,CAAC;IAC9B,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,iBAAiB,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACvC,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,EAAE,EAAE,OAAO,CAAC;CACb;AAwCD,MAAM,WAAW,sBAAsB;IACrC;2CACuC;IACvC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,sBAA2B,GACnC,gBAAgB,CA+IlB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAepE"}
1
+ {"version":3,"file":"docs-check.d.ts","sourceRoot":"","sources":["../src/docs-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,eAAO,MAAM,iBAAiB,6BAA6B,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EACA,sBAAsB,GACtB,wBAAwB,GACxB,oBAAoB,GACpB,0BAA0B,GAC1B,gCAAgC,GAChC,yBAAyB,CAAC;IAC9B,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,iBAAiB,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACvC,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,EAAE,EAAE,OAAO,CAAC;CACb;AAyCD,MAAM,WAAW,sBAAsB;IACrC;2CACuC;IACvC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,sBAA2B,GACnC,gBAAgB,CA+IlB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAepE"}
@@ -19,6 +19,7 @@ const REQUIRED_DOCS = [
19
19
  'philosophy.md',
20
20
  'safety-model.md',
21
21
  'testing.md',
22
+ 'exit-codes.md',
22
23
  ];
23
24
  const README_REQUIRED_KEYWORDS = ['quick demo', 'onboard', 'safety'];
24
25
  const README_SAFETY_KEYWORDS = ['mcp', 'read-only', 'never writes', 'safety'];
@@ -21,6 +21,22 @@ export declare function isGitRepo(cwd: string): boolean;
21
21
  export declare function getGitRoot(cwd: string): string | null;
22
22
  export declare function getGitBranch(cwd: string): string | null;
23
23
  export declare function getChangedFiles(cwd: string, opts?: IGitChangedOptions): string[];
24
+ /**
25
+ * True when `ref` resolves to a commit in `cwd`'s repo. Lets a caller tell a
26
+ * genuinely-empty diff apart from a bad ref — `getChangedFiles` returns `[]` for
27
+ * both (a failed `git diff <bad-ref>` yields no names), so a gate that scopes on
28
+ * `--base <ref>` must validate the ref first or it reports "nothing changed"
29
+ * (a false verified-nothing) over a typo'd ref.
30
+ */
31
+ export declare function refExists(cwd: string, ref: string): boolean;
32
+ /**
33
+ * The content of `relPath` at `ref` (e.g. `git show HEAD:src/x.ts`), or `null`
34
+ * when the path did not exist at that ref (a newly-added file) or git failed.
35
+ * `relPath` is repo-root-relative. Used to diff a file's PAST state against the
36
+ * working tree without a checkout — e.g. to see what a now-edited file used to
37
+ * provide/register.
38
+ */
39
+ export declare function gitShowFile(cwd: string, ref: string, relPath: string): string | null;
24
40
  export declare function getStatusSummary(cwd: string): IGitStatusSummary;
25
41
  export interface ICommitInfo {
26
42
  readonly hash: string;
@@ -1 +1 @@
1
- {"version":3,"file":"git-helpers.d.ts","sourceRoot":"","sources":["../src/git-helpers.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gEAAgE;IAChE,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CAChB;AAqBD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAI9C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKrD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKvD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,MAAM,EAAE,CAwBpF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAyC/D;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,EAAE,CA6BrF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAKjD"}
1
+ {"version":3,"file":"git-helpers.d.ts","sourceRoot":"","sources":["../src/git-helpers.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gEAAgE;IAChE,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CAChB;AAqBD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAI9C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKrD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKvD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,MAAM,EAAE,CAwBpF;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAI3D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGpF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAyC/D;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,EAAE,CA6BrF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAKjD"}
@@ -67,6 +67,30 @@ export function getChangedFiles(cwd, opts = {}) {
67
67
  }
68
68
  return [...set].sort();
69
69
  }
70
+ /**
71
+ * True when `ref` resolves to a commit in `cwd`'s repo. Lets a caller tell a
72
+ * genuinely-empty diff apart from a bad ref — `getChangedFiles` returns `[]` for
73
+ * both (a failed `git diff <bad-ref>` yields no names), so a gate that scopes on
74
+ * `--base <ref>` must validate the ref first or it reports "nothing changed"
75
+ * (a false verified-nothing) over a typo'd ref.
76
+ */
77
+ export function refExists(cwd, ref) {
78
+ if (!ref)
79
+ return false;
80
+ const r = runGit(cwd, ['rev-parse', '--verify', '--quiet', `${ref}^{commit}`]);
81
+ return r.ok && r.stdout.trim().length > 0;
82
+ }
83
+ /**
84
+ * The content of `relPath` at `ref` (e.g. `git show HEAD:src/x.ts`), or `null`
85
+ * when the path did not exist at that ref (a newly-added file) or git failed.
86
+ * `relPath` is repo-root-relative. Used to diff a file's PAST state against the
87
+ * working tree without a checkout — e.g. to see what a now-edited file used to
88
+ * provide/register.
89
+ */
90
+ export function gitShowFile(cwd, ref, relPath) {
91
+ const r = runGit(cwd, ['show', `${ref}:${relPath}`]);
92
+ return r.ok ? r.stdout : null;
93
+ }
70
94
  export function getStatusSummary(cwd) {
71
95
  const empty = {
72
96
  branch: null,
@@ -1 +1 @@
1
- {"version":3,"file":"import-hygiene.d.ts","sourceRoot":"","sources":["../src/import-hygiene.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"import-hygiene.d.ts","sourceRoot":"","sources":["../src/import-hygiene.ts"],"names":[],"mappings":"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"}
@@ -251,6 +251,15 @@ function stripCommentsPreservingOffsets(source) {
251
251
  }
252
252
  return buf.join('');
253
253
  }
254
+ /**
255
+ * Files import-hygiene never gates: test + fixture sources. Their whole PURPOSE
256
+ * is often to CONTAIN import-like text (`"const x = require('./y')"` as a string
257
+ * literal feeding a scanner test), so gating them produces false positives. The
258
+ * whole-tree scan has always excluded them; this constant makes the explicit
259
+ * `files` path (changed-only / `finish`) apply the SAME rule so the two can't
260
+ * drift — a change to a test file no longer spuriously fails an imports gate.
261
+ */
262
+ const EXCLUDED_FROM_HYGIENE = /__tests__|\/__fixtures__/;
254
263
  function defaultRoots(projectRoot) {
255
264
  const pkgsDir = nodePath.join(projectRoot, 'packages');
256
265
  if (!existsSync(pkgsDir))
@@ -272,10 +281,11 @@ export function buildImportHygieneReport(projectRoot, options = {}) {
272
281
  if (options.files && options.files.length > 0) {
273
282
  scanned = options.files
274
283
  .map((f) => (nodePath.isAbsolute(f) ? f : nodePath.join(projectRoot, f)))
275
- .filter((f) => existsSync(f) && /\.(ts|tsx)$/.test(f) && !/\.d\.ts$/.test(f));
284
+ .filter((f) => existsSync(f) && /\.(ts|tsx)$/.test(f) && !/\.d\.ts$/.test(f))
285
+ .filter((f) => !EXCLUDED_FROM_HYGIENE.test(f));
276
286
  }
277
287
  else {
278
- scanned = roots.flatMap(listSourceFiles).filter((f) => !/__tests__|\/__fixtures__/.test(f));
288
+ scanned = roots.flatMap(listSourceFiles).filter((f) => !EXCLUDED_FROM_HYGIENE.test(f));
279
289
  }
280
290
  const findings = [];
281
291
  const strictReasons = options.strictAllowlistReasons === true;
package/dist/index.d.ts CHANGED
@@ -146,6 +146,7 @@ export * from './migration-readiness.js';
146
146
  export * from './contract-file-rule.js';
147
147
  export * from './check-guardrail-globs.js';
148
148
  export * from './delegate-catalog.js';
149
+ export * from './delegate-grounding.js';
149
150
  export * from './delegate-pack-recipes.js';
150
151
  export * from './delegate-doctor.js';
151
152
  export * from './agent-contract.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -146,6 +146,7 @@ export * from "./migration-readiness.js";
146
146
  export * from "./contract-file-rule.js";
147
147
  export * from "./check-guardrail-globs.js";
148
148
  export * from "./delegate-catalog.js";
149
+ export * from "./delegate-grounding.js";
149
150
  export * from "./delegate-pack-recipes.js";
150
151
  export * from "./delegate-doctor.js";
151
152
  export * from "./agent-contract.js";
@@ -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.27",
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.27",
46
+ "@shrkcrft/config": "^0.1.0-alpha.27",
47
+ "@shrkcrft/workspace": "^0.1.0-alpha.27",
48
+ "@shrkcrft/knowledge": "^0.1.0-alpha.27",
49
+ "@shrkcrft/rules": "^0.1.0-alpha.27",
50
+ "@shrkcrft/paths": "^0.1.0-alpha.27",
51
+ "@shrkcrft/templates": "^0.1.0-alpha.27",
52
+ "@shrkcrft/context": "^0.1.0-alpha.27",
53
+ "@shrkcrft/pipelines": "^0.1.0-alpha.27",
54
+ "@shrkcrft/packs": "^0.1.0-alpha.27",
55
+ "@shrkcrft/presets": "^0.1.0-alpha.27",
56
+ "@shrkcrft/boundaries": "^0.1.0-alpha.27",
57
+ "@shrkcrft/generator": "^0.1.0-alpha.27",
58
+ "@shrkcrft/importer": "^0.1.0-alpha.27",
59
+ "@shrkcrft/plugin-api": "^0.1.0-alpha.27",
60
+ "@shrkcrft/dashboard-api": "^0.1.0-alpha.27",
61
61
  "typescript": "^5.6.0"
62
62
  },
63
63
  "publishConfig": {