@shrkcrft/inspector 0.1.0-alpha.2 → 0.1.0-alpha.21

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.
Files changed (194) hide show
  1. package/dist/agent-brief.d.ts.map +1 -1
  2. package/dist/agent-brief.js +59 -10
  3. package/dist/agent-contract-gate.d.ts.map +1 -1
  4. package/dist/agent-contract-gate.js +25 -2
  5. package/dist/agent-instructions.d.ts.map +1 -1
  6. package/dist/agent-instructions.js +11 -0
  7. package/dist/agent-task-prep.d.ts.map +1 -1
  8. package/dist/agent-task-prep.js +1 -3
  9. package/dist/ai-readiness.d.ts +84 -9
  10. package/dist/ai-readiness.d.ts.map +1 -1
  11. package/dist/ai-readiness.js +181 -35
  12. package/dist/apply-dispatch-trace.d.ts +1 -2
  13. package/dist/apply-dispatch-trace.d.ts.map +1 -1
  14. package/dist/apply-dispatch-trace.js +0 -9
  15. package/dist/area-explore.d.ts.map +1 -1
  16. package/dist/area-explore.js +4 -6
  17. package/dist/area-map.d.ts +0 -5
  18. package/dist/area-map.d.ts.map +1 -1
  19. package/dist/area-map.js +0 -10
  20. package/dist/changed-preflight.d.ts +7 -0
  21. package/dist/changed-preflight.d.ts.map +1 -1
  22. package/dist/changed-preflight.js +56 -9
  23. package/dist/changes-summary.d.ts.map +1 -1
  24. package/dist/changes-summary.js +20 -6
  25. package/dist/check-guardrail-globs.d.ts +16 -0
  26. package/dist/check-guardrail-globs.d.ts.map +1 -0
  27. package/dist/check-guardrail-globs.js +38 -0
  28. package/dist/code-intelligence-doctor.d.ts +21 -0
  29. package/dist/code-intelligence-doctor.d.ts.map +1 -0
  30. package/dist/code-intelligence-doctor.js +985 -0
  31. package/dist/command-recommender.d.ts.map +1 -1
  32. package/dist/command-recommender.js +23 -0
  33. package/dist/compliance-profiles.js +1 -1
  34. package/dist/construct-adoption-diff.d.ts.map +1 -1
  35. package/dist/construct-adoption-diff.js +2 -1
  36. package/dist/construct-adoption.d.ts.map +1 -1
  37. package/dist/construct-adoption.js +10 -11
  38. package/dist/construct-inference.d.ts.map +1 -1
  39. package/dist/construct-inference.js +5 -2
  40. package/dist/construct-registry.d.ts.map +1 -1
  41. package/dist/construct-registry.js +2 -10
  42. package/dist/contract-file-rule.d.ts +8 -0
  43. package/dist/contract-file-rule.d.ts.map +1 -1
  44. package/dist/contract-file-rule.js +8 -3
  45. package/dist/contract-template-registry.d.ts.map +1 -1
  46. package/dist/contract-template-registry.js +2 -10
  47. package/dist/contradictions.d.ts +8 -1
  48. package/dist/contradictions.d.ts.map +1 -1
  49. package/dist/contradictions.js +37 -35
  50. package/dist/convention-registry.d.ts.map +1 -1
  51. package/dist/convention-registry.js +2 -10
  52. package/dist/coverage-report.d.ts.map +1 -1
  53. package/dist/coverage-report.js +14 -1
  54. package/dist/dashboard/dashboard-knowledge.d.ts +8 -0
  55. package/dist/dashboard/dashboard-knowledge.d.ts.map +1 -0
  56. package/dist/dashboard/dashboard-knowledge.js +259 -0
  57. package/dist/decision-records.d.ts.map +1 -1
  58. package/dist/decision-records.js +5 -10
  59. package/dist/delegate-catalog.d.ts +45 -0
  60. package/dist/delegate-catalog.d.ts.map +1 -0
  61. package/dist/delegate-catalog.js +50 -0
  62. package/dist/delegate-doctor.d.ts +15 -0
  63. package/dist/delegate-doctor.d.ts.map +1 -0
  64. package/dist/delegate-doctor.js +36 -0
  65. package/dist/delegate-pack-recipes.d.ts +29 -0
  66. package/dist/delegate-pack-recipes.d.ts.map +1 -0
  67. package/dist/delegate-pack-recipes.js +77 -0
  68. package/dist/demo-script.d.ts +0 -1
  69. package/dist/demo-script.d.ts.map +1 -1
  70. package/dist/demo-script.js +0 -43
  71. package/dist/docs-check.js +1 -1
  72. package/dist/drift-baseline.d.ts.map +1 -1
  73. package/dist/drift-baseline.js +5 -2
  74. package/dist/feedback-ingestion.d.ts.map +1 -1
  75. package/dist/feedback-ingestion.js +2 -16
  76. package/dist/git-helpers.d.ts +15 -0
  77. package/dist/git-helpers.d.ts.map +1 -1
  78. package/dist/git-helpers.js +51 -4
  79. package/dist/helper-registry.d.ts +27 -54
  80. package/dist/helper-registry.d.ts.map +1 -1
  81. package/dist/helper-registry.js +16 -517
  82. package/dist/impact-analysis.d.ts.map +1 -1
  83. package/dist/impact-analysis.js +14 -7
  84. package/dist/index.d.ts +8 -2
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +8 -2
  87. package/dist/ingest-drafts.js +8 -4
  88. package/dist/migration-profile-registry.d.ts.map +1 -1
  89. package/dist/migration-profile-registry.js +2 -10
  90. package/dist/monorepo-onboarding.js +2 -2
  91. package/dist/onboarding-report.d.ts.map +1 -1
  92. package/dist/onboarding-report.js +5 -1
  93. package/dist/onboarding.d.ts +1 -1
  94. package/dist/onboarding.d.ts.map +1 -1
  95. package/dist/onboarding.js +9 -66
  96. package/dist/ownership.js +2 -10
  97. package/dist/pack-contributions-inventory.d.ts +0 -1
  98. package/dist/pack-contributions-inventory.d.ts.map +1 -1
  99. package/dist/pack-contributions-inventory.js +17 -29
  100. package/dist/pack-helper-registry.d.ts.map +1 -1
  101. package/dist/pack-helper-registry.js +2 -10
  102. package/dist/pack-release-check.d.ts.map +1 -1
  103. package/dist/pack-release-check.js +4 -11
  104. package/dist/pack-signature-status.d.ts.map +1 -1
  105. package/dist/pack-signature-status.js +18 -2
  106. package/dist/pack-test-runner.js +2 -10
  107. package/dist/plan-review.d.ts.map +1 -1
  108. package/dist/plan-review.js +5 -10
  109. package/dist/plan-simulation.d.ts +13 -0
  110. package/dist/plan-simulation.d.ts.map +1 -1
  111. package/dist/plan-simulation.js +19 -28
  112. package/dist/playbook-registry.d.ts.map +1 -1
  113. package/dist/playbook-registry.js +2 -10
  114. package/dist/policy-engine.d.ts.map +1 -1
  115. package/dist/policy-engine.js +3 -11
  116. package/dist/policy-test.js +3 -11
  117. package/dist/profile-registry.d.ts +0 -1
  118. package/dist/profile-registry.d.ts.map +1 -1
  119. package/dist/profile-registry.js +4 -32
  120. package/dist/propose-knowledge.d.ts +15 -0
  121. package/dist/propose-knowledge.d.ts.map +1 -1
  122. package/dist/propose-knowledge.js +37 -4
  123. package/dist/quality-baseline.d.ts.map +1 -1
  124. package/dist/quality-baseline.js +3 -1
  125. package/dist/ranker-explainability.d.ts.map +1 -1
  126. package/dist/ranker-explainability.js +3 -9
  127. package/dist/registration-hint-registry.d.ts.map +1 -1
  128. package/dist/registration-hint-registry.js +2 -10
  129. package/dist/registry-lifecycle.d.ts +6 -0
  130. package/dist/registry-lifecycle.d.ts.map +1 -1
  131. package/dist/registry-lifecycle.js +137 -10
  132. package/dist/release-readiness.js +3 -3
  133. package/dist/repo-memory.d.ts.map +1 -1
  134. package/dist/repo-memory.js +3 -1
  135. package/dist/reposet.js +1 -1
  136. package/dist/repository-intelligence.d.ts.map +1 -1
  137. package/dist/repository-intelligence.js +7 -2
  138. package/dist/repository-knowledge-model.d.ts +1 -1
  139. package/dist/repository-knowledge-model.d.ts.map +1 -1
  140. package/dist/repository-stats.d.ts.map +1 -1
  141. package/dist/repository-stats.js +3 -1
  142. package/dist/resolve-verification-commands.d.ts +26 -0
  143. package/dist/resolve-verification-commands.d.ts.map +1 -0
  144. package/dist/resolve-verification-commands.js +55 -0
  145. package/dist/review-packet.d.ts.map +1 -1
  146. package/dist/review-packet.js +14 -17
  147. package/dist/rule-drift.d.ts.map +1 -1
  148. package/dist/rule-drift.js +24 -9
  149. package/dist/rule-scaffold.d.ts.map +1 -1
  150. package/dist/rule-scaffold.js +12 -4
  151. package/dist/scaffold-patterns.js +2 -10
  152. package/dist/schema-inventory.d.ts.map +1 -1
  153. package/dist/schema-inventory.js +3 -1
  154. package/dist/search-tuning-registry.d.ts.map +1 -1
  155. package/dist/search-tuning-registry.js +2 -10
  156. package/dist/self-config-doctor-v2.d.ts +1 -1
  157. package/dist/self-config-doctor-v2.d.ts.map +1 -1
  158. package/dist/self-config-doctor-v2.js +6 -10
  159. package/dist/self-config-doctor.d.ts.map +1 -1
  160. package/dist/self-config-doctor.js +7 -13
  161. package/dist/sharkcraft-inspector.d.ts +14 -0
  162. package/dist/sharkcraft-inspector.d.ts.map +1 -1
  163. package/dist/sharkcraft-inspector.js +103 -1
  164. package/dist/start-here.d.ts +2 -2
  165. package/dist/start-here.d.ts.map +1 -1
  166. package/dist/start-here.js +16 -1
  167. package/dist/synthesize-from-onboarding.d.ts +68 -0
  168. package/dist/synthesize-from-onboarding.d.ts.map +1 -0
  169. package/dist/synthesize-from-onboarding.js +508 -0
  170. package/dist/task-packet.d.ts +13 -0
  171. package/dist/task-packet.d.ts.map +1 -1
  172. package/dist/task-packet.js +59 -6
  173. package/dist/task-ranker.d.ts.map +1 -1
  174. package/dist/task-ranker.js +1 -31
  175. package/dist/task-routing-hint-registry.d.ts.map +1 -1
  176. package/dist/task-routing-hint-registry.js +2 -10
  177. package/dist/template-drift.d.ts +7 -0
  178. package/dist/template-drift.d.ts.map +1 -1
  179. package/dist/template-drift.js +14 -6
  180. package/dist/test-impact.d.ts.map +1 -1
  181. package/dist/test-impact.js +5 -2
  182. package/dist/test-runner.d.ts.map +1 -1
  183. package/dist/test-runner.js +12 -17
  184. package/dist/universal-search.d.ts +0 -1
  185. package/dist/universal-search.d.ts.map +1 -1
  186. package/dist/universal-search.js +0 -12
  187. package/dist/why-file.js +66 -22
  188. package/package.json +18 -18
  189. package/dist/plugin-lifecycle-profile-registry.d.ts +0 -52
  190. package/dist/plugin-lifecycle-profile-registry.d.ts.map +0 -1
  191. package/dist/plugin-lifecycle-profile-registry.js +0 -202
  192. package/dist/plugin-lifecycle.d.ts +0 -132
  193. package/dist/plugin-lifecycle.d.ts.map +0 -1
  194. package/dist/plugin-lifecycle.js +0 -477
@@ -0,0 +1,259 @@
1
+ /**
2
+ * Dashboard data builders for the Knowledge explorer page. Pure, deterministic,
3
+ * JSON-serializable — no network, no LLM (the LLM-backed "ask" lives in the CLI
4
+ * dashboard layer so the inspector stays AI-free). The dashboard API server
5
+ * wraps these with @shrkcrft/dashboard-api envelopes.
6
+ */
7
+ import { relative } from 'node:path';
8
+ import { hasActionHints, priorityWeight, searchKnowledge, } from '@shrkcrft/knowledge';
9
+ import { buildKnowledgeGraph, getGraphNode } from "../knowledge-graph.js";
10
+ /** GraphSvg colours by kind — map a knowledge entry's type to one of them. */
11
+ function nodeKindForType(type) {
12
+ if (type === 'rule')
13
+ return 'rule';
14
+ if (type === 'path')
15
+ return 'path';
16
+ if (type === 'template')
17
+ return 'template';
18
+ return 'knowledge';
19
+ }
20
+ function sourceLabel(entry, projectRoot) {
21
+ const origin = entry.source?.origin;
22
+ if (!origin)
23
+ return entry.source?.loader ?? 'local';
24
+ if (origin.startsWith('http'))
25
+ return origin;
26
+ const rel = relative(projectRoot, origin);
27
+ return rel && !rel.startsWith('..') ? rel : origin;
28
+ }
29
+ function commandHint(command, purpose) {
30
+ return { command, purpose, safety: 'read-only' };
31
+ }
32
+ function summaryOf(entry, projectRoot) {
33
+ const summary = {
34
+ id: entry.id,
35
+ title: entry.title,
36
+ type: String(entry.type),
37
+ priority: String(entry.priority),
38
+ scope: [...entry.scope],
39
+ tags: [...entry.tags],
40
+ relatedCount: (entry.related?.length ?? 0),
41
+ hasActionHints: hasActionHints(entry),
42
+ source: sourceLabel(entry, projectRoot),
43
+ };
44
+ return entry.summary ? { ...summary, summary: entry.summary } : summary;
45
+ }
46
+ function mapActionHints(h) {
47
+ return {
48
+ commands: (h.commands ?? []).map((c) => c.command),
49
+ mcpTools: (h.mcpTools ?? []).map((t) => t.tool),
50
+ preferredFlow: [...(h.preferredFlow ?? [])],
51
+ forbiddenActions: [...(h.forbiddenActions ?? [])],
52
+ verificationCommands: [...(h.verificationCommands ?? [])],
53
+ relatedTemplates: [...(h.relatedTemplates ?? [])],
54
+ relatedPathConventions: [...(h.relatedPathConventions ?? [])],
55
+ relatedKnowledge: [...(h.relatedKnowledge ?? [])],
56
+ ...(h.writePolicy ? { writePolicy: String(h.writePolicy) } : {}),
57
+ };
58
+ }
59
+ function detailOf(entry, projectRoot) {
60
+ const examples = (entry.examples ?? []).map((ex) => ({
61
+ ...(ex.title ? { title: ex.title } : {}),
62
+ ...(ex.description ? { description: ex.description } : {}),
63
+ ...(ex.language ? { language: ex.language } : {}),
64
+ ...(ex.code ? { code: ex.code } : {}),
65
+ }));
66
+ const detail = {
67
+ id: entry.id,
68
+ title: entry.title,
69
+ type: String(entry.type),
70
+ priority: String(entry.priority),
71
+ scope: [...entry.scope],
72
+ tags: [...entry.tags],
73
+ appliesWhen: [...entry.appliesWhen],
74
+ content: entry.content,
75
+ related: [...(entry.related ?? [])],
76
+ source: sourceLabel(entry, projectRoot),
77
+ examples,
78
+ };
79
+ const withSummary = entry.summary ? { ...detail, summary: entry.summary } : detail;
80
+ return entry.actionHints
81
+ ? { ...withSummary, actionHints: mapActionHints(entry.actionHints) }
82
+ : withSummary;
83
+ }
84
+ function facetCounts(entries, pick) {
85
+ const counts = new Map();
86
+ for (const e of entries) {
87
+ for (const v of pick(e)) {
88
+ if (!v)
89
+ continue;
90
+ counts.set(v, (counts.get(v) ?? 0) + 1);
91
+ }
92
+ }
93
+ return [...counts.entries()]
94
+ .map(([value, count]) => ({ value, count }))
95
+ .sort((a, b) => b.count - a.count || a.value.localeCompare(b.value));
96
+ }
97
+ /** Sort: highest priority first, then alphabetical by id. */
98
+ function byPriorityThenId(a, b) {
99
+ const w = priorityWeight(b.priority) - priorityWeight(a.priority);
100
+ return w !== 0 ? w : a.id.localeCompare(b.id);
101
+ }
102
+ function roundScore(n) {
103
+ return Math.round(n * 100) / 100;
104
+ }
105
+ function computeInsights(entries) {
106
+ const byPriority = { critical: 0, high: 0, medium: 0, low: 0 };
107
+ let withoutActionHints = 0;
108
+ let withoutSummary = 0;
109
+ let orphans = 0;
110
+ for (const e of entries) {
111
+ const p = String(e.priority);
112
+ if (p === 'critical' || p === 'high' || p === 'medium' || p === 'low')
113
+ byPriority[p] += 1;
114
+ if (!hasActionHints(e))
115
+ withoutActionHints += 1;
116
+ if (!e.summary)
117
+ withoutSummary += 1;
118
+ if (!(e.related?.length) && !(e.actionHints?.relatedKnowledge?.length))
119
+ orphans += 1;
120
+ }
121
+ return { byPriority, withoutActionHints, withoutSummary, orphans };
122
+ }
123
+ export function buildDashboardKnowledgeList(inspection) {
124
+ const entries = inspection.knowledgeEntries;
125
+ const sorted = [...entries].sort(byPriorityThenId);
126
+ return {
127
+ available: entries.length > 0,
128
+ total: entries.length,
129
+ entries: sorted.map((e) => summaryOf(e, inspection.projectRoot)),
130
+ facets: {
131
+ types: facetCounts(entries, (e) => [String(e.type)]),
132
+ scopes: facetCounts(entries, (e) => e.scope),
133
+ tags: facetCounts(entries, (e) => e.tags),
134
+ priorities: facetCounts(entries, (e) => [String(e.priority)]),
135
+ },
136
+ insights: computeInsights(entries),
137
+ commandHints: [
138
+ commandHint('shrk knowledge list', 'List every knowledge entry'),
139
+ commandHint('shrk knowledge search "<query>"', 'Rank entries by relevance to a query'),
140
+ commandHint('shrk knowledge get <id>', 'Read a single entry in the terminal'),
141
+ ],
142
+ };
143
+ }
144
+ export function buildDashboardKnowledgeEntry(inspection, id) {
145
+ const entries = inspection.knowledgeEntries;
146
+ const entry = entries.find((e) => e.id === id);
147
+ if (!entry) {
148
+ return { found: false, inbound: [], outbound: [], related: [], commandHints: [] };
149
+ }
150
+ const graph = buildKnowledgeGraph(inspection);
151
+ const located = getGraphNode(graph, { id });
152
+ // Graph edge endpoints are namespaced node keys (`kind:id`), so resolve the
153
+ // raw id + kind through byId rather than echoing the key.
154
+ const toNeighbor = (endpointKey, relation, why) => {
155
+ const node = graph.byId.get(endpointKey);
156
+ // Edges only ever target nodes present in the graph, but if a lookup ever
157
+ // misses, strip the `kind:` prefix so a raw id (not the namespaced key)
158
+ // still reaches the client — `id` must be a clickable entry id.
159
+ const colon = endpointKey.indexOf(':');
160
+ const fallbackId = colon >= 0 ? endpointKey.slice(colon + 1) : endpointKey;
161
+ return {
162
+ id: node?.id ?? fallbackId,
163
+ kind: node?.kind ?? 'knowledge',
164
+ relation,
165
+ why,
166
+ };
167
+ };
168
+ const inbound = (located?.incoming ?? []).map((e) => toNeighbor(e.from, e.relation, e.why));
169
+ const outbound = (located?.outgoing ?? []).map((e) => toNeighbor(e.to, e.relation, e.why));
170
+ const relatedIds = [
171
+ ...new Set([...(entry.related ?? []), ...(entry.actionHints?.relatedKnowledge ?? [])]),
172
+ ];
173
+ const related = relatedIds
174
+ .map((rid) => entries.find((e) => e.id === rid))
175
+ .filter((e) => Boolean(e))
176
+ .map((e) => summaryOf(e, inspection.projectRoot));
177
+ return {
178
+ found: true,
179
+ entry: detailOf(entry, inspection.projectRoot),
180
+ inbound,
181
+ outbound,
182
+ related,
183
+ commandHints: [
184
+ commandHint(`shrk knowledge get ${entry.id}`, 'Read this entry in the terminal'),
185
+ commandHint(`shrk graph node ${entry.id}`, 'Inspect this node and its edges'),
186
+ ],
187
+ };
188
+ }
189
+ /** Cap the rendered graph — the ring layout stays legible up to ~120 nodes. */
190
+ const MAX_GRAPH_NODES = 120;
191
+ export function buildDashboardKnowledgeGraph(inspection) {
192
+ const all = [...inspection.knowledgeEntries].sort(byPriorityThenId);
193
+ const truncated = all.length > MAX_GRAPH_NODES;
194
+ const entries = all.slice(0, MAX_GRAPH_NODES);
195
+ const ids = new Set(entries.map((e) => e.id));
196
+ const nodes = entries.map((e) => ({
197
+ id: e.id,
198
+ kind: nodeKindForType(String(e.type)),
199
+ label: e.title,
200
+ }));
201
+ const edges = [];
202
+ const seen = new Set();
203
+ const addEdge = (from, to, kind) => {
204
+ if (from === to || !ids.has(from) || !ids.has(to))
205
+ return;
206
+ const key = from < to ? `${from}|${to}|${kind}` : `${to}|${from}|${kind}`;
207
+ if (seen.has(key))
208
+ return;
209
+ seen.add(key);
210
+ edges.push({ from, to, kind });
211
+ };
212
+ // Semantic edges: explicit cross-references.
213
+ for (const e of entries) {
214
+ for (const t of [...(e.related ?? []), ...(e.actionHints?.relatedKnowledge ?? [])]) {
215
+ addEdge(e.id, t, 'related');
216
+ }
217
+ }
218
+ // Scope clusters: chain entries that share a scope so the graph forms loose,
219
+ // legible neighbourhoods instead of an O(n²) hairball.
220
+ const byScope = new Map();
221
+ for (const e of entries) {
222
+ for (const s of e.scope) {
223
+ const list = byScope.get(s) ?? [];
224
+ list.push(e.id);
225
+ byScope.set(s, list);
226
+ }
227
+ }
228
+ for (const group of byScope.values()) {
229
+ for (let i = 1; i < group.length; i += 1) {
230
+ addEdge(group[i - 1], group[i], 'scope');
231
+ }
232
+ }
233
+ return { available: entries.length > 0, nodes, edges, truncated };
234
+ }
235
+ /** Relevance-ranked "more like this" for one entry (lexical, deterministic). */
236
+ export function buildDashboardKnowledgeSimilar(inspection, id) {
237
+ const entries = inspection.knowledgeEntries;
238
+ const entry = entries.find((e) => e.id === id);
239
+ if (!entry)
240
+ return { id, available: false, similar: [] };
241
+ // Use the entry's own signature (title + tags + scope) as the query. With no
242
+ // signature there's nothing to match on — return empty rather than letting
243
+ // searchKnowledge fall back to a priority-only ranking of everything.
244
+ const query = [entry.title, ...entry.tags, ...entry.scope].join(' ').trim();
245
+ if (!query)
246
+ return { id, available: false, similar: [] };
247
+ const results = searchKnowledge(entries, { query, limit: 8 });
248
+ const similar = results
249
+ .filter((r) => r.entry.id !== id)
250
+ .slice(0, 6)
251
+ .map((r) => ({
252
+ id: r.entry.id,
253
+ title: r.entry.title,
254
+ type: String(r.entry.type),
255
+ score: roundScore(r.score),
256
+ reasons: [...new Set(r.reasons.map((x) => x.field))].slice(0, 4),
257
+ }));
258
+ return { id, available: similar.length > 0, similar };
259
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"decision-records.d.ts","sourceRoot":"","sources":["../src/decision-records.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAE/D,oBAAY,cAAc;IACxB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,UAAU,eAAe;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,sBAAsB,CAAC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA8CD,wBAAgB,aAAa,CAAC,UAAU,EAAE,qBAAqB,GAAG,SAAS,eAAe,EAAE,CAyD3F;AA0BD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAuCrC;AAaD,wBAAgB,WAAW,CAAC,UAAU,EAAE,qBAAqB,EAAE,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEtG;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CA0CvE;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE/E"}
1
+ {"version":3,"file":"decision-records.d.ts","sourceRoot":"","sources":["../src/decision-records.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAGvE,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAE/D,oBAAY,cAAc;IACxB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,UAAU,eAAe;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,sBAAsB,CAAC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA8CD,wBAAgB,aAAa,CAAC,UAAU,EAAE,qBAAqB,GAAG,SAAS,eAAe,EAAE,CA2D3F;AA0BD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAuCrC;AAaD,wBAAgB,WAAW,CAAC,UAAU,EAAE,qBAAqB,EAAE,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEtG;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CA0CvE;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE/E"}
@@ -1,11 +1,3 @@
1
- var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
- if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
- return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
- return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
- });
6
- }
7
- return path;
8
- };
9
1
  /**
10
2
  * Decision / ADR support.
11
3
  *
@@ -18,6 +10,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
18
10
  */
19
11
  import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
20
12
  import * as nodePath from 'node:path';
13
+ import { importModuleViaLoader } from '@shrkcrft/core';
21
14
  export const DECISION_RECORD_SCHEMA = 'sharkcraft.decision/v1';
22
15
  export var DecisionStatus;
23
16
  (function (DecisionStatus) {
@@ -86,7 +79,9 @@ export function listDecisions(inspection) {
86
79
  continue;
87
80
  let entries = [];
88
81
  try {
89
- entries = readdirSync(dir);
82
+ // Sort so the decision-record list (and the doctor findings derived from
83
+ // it) is deterministic, not filesystem-order-dependent.
84
+ entries = readdirSync(dir).sort();
90
85
  }
91
86
  catch {
92
87
  continue;
@@ -193,7 +188,7 @@ async function importDefaultArray(absPath) {
193
188
  if (!existsSync(absPath))
194
189
  return [];
195
190
  const { pathToFileURL } = await import('node:url');
196
- const mod = (await import(__rewriteRelativeImportExtension(pathToFileURL(absPath).href)));
191
+ const mod = (await importModuleViaLoader(absPath));
197
192
  return Array.isArray(mod.default) ? mod.default : [];
198
193
  }
199
194
  catch {
@@ -0,0 +1,45 @@
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 type { IDelegateRecipe, ISharkCraftConfig } from '@shrkcrft/config';
12
+ export interface IResolvedDelegateRecipe extends IDelegateRecipe {
13
+ /** Provider after applying the delegation-level default (never undefined). */
14
+ resolvedProvider: 'auto' | 'ollama' | 'llamacpp';
15
+ /** Model after applying the delegation-level default (undefined = provider default). */
16
+ resolvedModel?: string;
17
+ /** verificationIds that do NOT resolve to a `verificationCommands[].id`. */
18
+ unboundVerificationIds: readonly string[];
19
+ /** True when every verificationId resolves AND at least one is declared. */
20
+ verificationBound: boolean;
21
+ /** True when the recipe is safe to delegate (verification fully bound). */
22
+ delegatable: boolean;
23
+ /** Where the recipe came from. */
24
+ source: 'config' | 'pack';
25
+ /** Contributing pack, when `source === 'pack'`. */
26
+ packageName?: string;
27
+ }
28
+ /** A pack-contributed recipe (shape from `loadDelegateRecipesFromPacks`). */
29
+ export interface IPackRecipeInput {
30
+ recipe: IDelegateRecipe;
31
+ packageName: string;
32
+ }
33
+ /**
34
+ * Resolve the delegate catalog from config + pack-contributed recipes.
35
+ *
36
+ * Merge order: pack recipes first, then INLINE config recipes override a pack
37
+ * recipe of the same id. `recipeOverrides` (by id) then patch model /
38
+ * verificationIds / guardrailGlobs, or drop the recipe (`enabled: false`).
39
+ * Finally each recipe's `verificationIds` are checked against
40
+ * `verificationCommands[]` — `delegatable` only when all are bound.
41
+ */
42
+ export declare function resolveDelegateCatalog(config: ISharkCraftConfig, packRecipes?: readonly IPackRecipeInput[]): readonly IResolvedDelegateRecipe[];
43
+ /** Look up one resolved recipe by id (config recipes only; no pack loading). */
44
+ export declare function findDelegateRecipe(config: ISharkCraftConfig, recipeId: string): IResolvedDelegateRecipe | undefined;
45
+ //# sourceMappingURL=delegate-catalog.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Resolve the delegate catalog from config + pack-contributed recipes.
3
+ *
4
+ * Merge order: pack recipes first, then INLINE config recipes override a pack
5
+ * recipe of the same id. `recipeOverrides` (by id) then patch model /
6
+ * verificationIds / guardrailGlobs, or drop the recipe (`enabled: false`).
7
+ * Finally each recipe's `verificationIds` are checked against
8
+ * `verificationCommands[]` — `delegatable` only when all are bound.
9
+ */
10
+ export function resolveDelegateCatalog(config, packRecipes = []) {
11
+ const delegation = config.delegation;
12
+ if (!delegation)
13
+ return [];
14
+ const known = new Set((config.verificationCommands ?? []).map((v) => v.id));
15
+ const overrides = delegation.recipeOverrides ?? {};
16
+ const byId = new Map();
17
+ for (const pr of packRecipes)
18
+ byId.set(pr.recipe.id, { recipe: pr.recipe, source: 'pack', packageName: pr.packageName });
19
+ for (const recipe of delegation.recipes ?? [])
20
+ byId.set(recipe.id, { recipe, source: 'config' });
21
+ const out = [];
22
+ for (const { recipe, source, packageName } of byId.values()) {
23
+ const ov = overrides[recipe.id];
24
+ if (ov?.enabled === false)
25
+ continue; // dropped by override
26
+ const merged = {
27
+ ...recipe,
28
+ ...(ov?.model !== undefined ? { model: ov.model } : {}),
29
+ ...(ov?.verificationIds !== undefined ? { verificationIds: ov.verificationIds } : {}),
30
+ ...(ov?.guardrailGlobs !== undefined ? { guardrailGlobs: ov.guardrailGlobs } : {}),
31
+ };
32
+ const unbound = (merged.verificationIds ?? []).filter((id) => !known.has(id));
33
+ const verificationBound = unbound.length === 0 && (merged.verificationIds ?? []).length > 0;
34
+ out.push({
35
+ ...merged,
36
+ resolvedProvider: merged.provider ?? delegation.provider ?? 'auto',
37
+ ...(merged.model ?? delegation.model ? { resolvedModel: merged.model ?? delegation.model } : {}),
38
+ unboundVerificationIds: unbound,
39
+ verificationBound,
40
+ delegatable: verificationBound,
41
+ source,
42
+ ...(packageName ? { packageName } : {}),
43
+ });
44
+ }
45
+ return out;
46
+ }
47
+ /** Look up one resolved recipe by id (config recipes only; no pack loading). */
48
+ export function findDelegateRecipe(config, recipeId) {
49
+ return resolveDelegateCatalog(config).find((r) => r.id === recipeId);
50
+ }
@@ -0,0 +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 type { ISharkCraftConfig } from '@shrkcrft/config';
13
+ import { type IDoctorCheck } from './doctor-result.js';
14
+ export declare function buildDelegateRecipeChecks(config: ISharkCraftConfig | null): IDoctorCheck[];
15
+ //# sourceMappingURL=delegate-doctor.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,36 @@
1
+ import { DoctorSeverity } from "./doctor-result.js";
2
+ import { resolveDelegateCatalog } from "./delegate-catalog.js";
3
+ export function buildDelegateRecipeChecks(config) {
4
+ if (!config?.delegation)
5
+ return []; // not opted in → silent
6
+ const catalog = resolveDelegateCatalog(config);
7
+ if (catalog.length === 0)
8
+ return [];
9
+ const out = [];
10
+ const broken = catalog.filter((r) => !r.delegatable);
11
+ for (const r of broken) {
12
+ const reason = r.unboundVerificationIds.length > 0
13
+ ? `verificationIds not in verificationCommands[]: ${r.unboundVerificationIds.join(', ')}`
14
+ : 'no verificationIds declared';
15
+ out.push({
16
+ id: `delegate-recipe-${r.id}`,
17
+ title: `Delegate recipe "${r.id}" is not delegatable`,
18
+ severity: DoctorSeverity.Warning,
19
+ message: `${reason} — \`shrk delegate run --recipe ${r.id}\` would refuse to apply an unverified edit.`,
20
+ category: 'delegate',
21
+ code: 'recipe-unverified',
22
+ 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.',
24
+ });
25
+ }
26
+ if (broken.length === 0) {
27
+ out.push({
28
+ id: 'delegate-recipes',
29
+ title: 'Delegate recipes',
30
+ severity: DoctorSeverity.Ok,
31
+ message: `${catalog.length} delegate recipe(s) configured, all delegatable.`,
32
+ category: 'delegate',
33
+ });
34
+ }
35
+ return out;
36
+ }
@@ -0,0 +1,29 @@
1
+ import { type IDelegateRecipe } from '@shrkcrft/core';
2
+ import type { ISharkCraftConfig } from '@shrkcrft/config';
3
+ import { type IDiscoveredPack } from '@shrkcrft/packs';
4
+ import { type IResolvedDelegateRecipe } from './delegate-catalog.js';
5
+ export interface IPackDelegateRecipe {
6
+ recipe: IDelegateRecipe;
7
+ packageName: string;
8
+ /** The contributed file's relative path (for diagnostics). */
9
+ sourceFile: string;
10
+ }
11
+ export interface IPackRecipeIssue {
12
+ severity: 'warning' | 'error';
13
+ message: string;
14
+ source?: string;
15
+ }
16
+ export interface ILoadPackRecipesResult {
17
+ recipes: readonly IPackDelegateRecipe[];
18
+ issues: readonly IPackRecipeIssue[];
19
+ }
20
+ export declare function loadDelegateRecipesFromPacks(validPacks: readonly IDiscoveredPack[]): Promise<ILoadPackRecipesResult>;
21
+ /**
22
+ * One-shot: discover packs under `projectRoot`, load their delegate recipes, and
23
+ * resolve the full catalog (pack recipes + config recipes + `recipeOverrides`).
24
+ * Pack discovery is best-effort — a missing/odd `node_modules` degrades to the
25
+ * config-only catalog. Keeps `discoverPacks` inside `inspector` so the cli stays
26
+ * decoupled from `@shrkcrft/packs`.
27
+ */
28
+ export declare function resolveDelegateCatalogForProject(config: ISharkCraftConfig, projectRoot: string): Promise<readonly IResolvedDelegateRecipe[]>;
29
+ //# sourceMappingURL=delegate-pack-recipes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate-pack-recipes.d.ts","sourceRoot":"","sources":["../src/delegate-pack-recipes.ts"],"names":[],"mappings":"AAWA,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAA0B,KAAK,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAE7F,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,eAAe,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACrC;AAaD,wBAAsB,4BAA4B,CAChD,UAAU,EAAE,SAAS,eAAe,EAAE,GACrC,OAAO,CAAC,sBAAsB,CAAC,CA8BjC;AAED;;;;;;GAMG;AACH,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,SAAS,uBAAuB,EAAE,CAAC,CAY7C"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Load delegate-worker recipes contributed by discovered packs.
3
+ *
4
+ * A pack declares `contributions.delegateRecipeFiles[]`, each default-exporting
5
+ * `readonly IDelegateRecipe[]` (via `defineDelegateRecipe`). This loads them
6
+ * read-only (no model, no writes) so `resolveDelegateCatalog(config, packRecipes)`
7
+ * can merge them with the project's inline recipes + `recipeOverrides`. Mirrors
8
+ * the other pack registries (e.g. task-routing-hint-registry).
9
+ */
10
+ import { existsSync } from 'node:fs';
11
+ import * as nodePath from 'node:path';
12
+ import { importModuleViaLoader } from '@shrkcrft/core';
13
+ import { discoverPacks } from '@shrkcrft/packs';
14
+ import { resolveDelegateCatalog } from "./delegate-catalog.js";
15
+ async function importRecipes(file) {
16
+ const mod = (await importModuleViaLoader(file));
17
+ if (Array.isArray(mod.default))
18
+ return mod.default;
19
+ if (mod.default && typeof mod.default === 'object')
20
+ return [mod.default];
21
+ if (Array.isArray(mod.delegateRecipes))
22
+ return mod.delegateRecipes;
23
+ return [];
24
+ }
25
+ export async function loadDelegateRecipesFromPacks(validPacks) {
26
+ const recipes = [];
27
+ const issues = [];
28
+ for (const pack of validPacks) {
29
+ const files = pack.manifest?.contributions?.delegateRecipeFiles ?? [];
30
+ for (const rel of files) {
31
+ const file = nodePath.resolve(pack.packageRoot, rel);
32
+ if (!existsSync(file)) {
33
+ issues.push({
34
+ severity: 'warning',
35
+ message: `Pack ${pack.packageName} declares ${rel} but the file is missing.`,
36
+ source: file,
37
+ });
38
+ continue;
39
+ }
40
+ try {
41
+ const list = await importRecipes(file);
42
+ for (const recipe of list) {
43
+ recipes.push({ recipe, packageName: pack.packageName, sourceFile: rel });
44
+ }
45
+ }
46
+ catch (e) {
47
+ issues.push({
48
+ severity: 'warning',
49
+ message: `Pack ${pack.packageName} (${rel}): ${e.message}`,
50
+ source: file,
51
+ });
52
+ }
53
+ }
54
+ }
55
+ return { recipes, issues };
56
+ }
57
+ /**
58
+ * One-shot: discover packs under `projectRoot`, load their delegate recipes, and
59
+ * resolve the full catalog (pack recipes + config recipes + `recipeOverrides`).
60
+ * Pack discovery is best-effort — a missing/odd `node_modules` degrades to the
61
+ * config-only catalog. Keeps `discoverPacks` inside `inspector` so the cli stays
62
+ * decoupled from `@shrkcrft/packs`.
63
+ */
64
+ export async function resolveDelegateCatalogForProject(config, projectRoot) {
65
+ let packRecipes = [];
66
+ try {
67
+ const disc = await discoverPacks({ projectRoot });
68
+ packRecipes = (await loadDelegateRecipesFromPacks(disc.validPacks)).recipes.map((p) => ({
69
+ recipe: p.recipe,
70
+ packageName: p.packageName,
71
+ }));
72
+ }
73
+ catch {
74
+ // best-effort; configured recipes still resolve
75
+ }
76
+ return resolveDelegateCatalog(config, packRecipes);
77
+ }
@@ -1,7 +1,6 @@
1
1
  export declare const DEMO_SCRIPT_SCHEMA = "sharkcraft.demo-script/v1";
2
2
  export declare enum DemoScenario {
3
3
  UnconfiguredRepo = "unconfigured-repo",
4
- PlatformPlugin = "platform-plugin",
5
4
  PrReview = "pr-review",
6
5
  Governance = "governance"
7
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"demo-script.d.ts","sourceRoot":"","sources":["../src/demo-script.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAE9D,oBAAY,YAAY;IACtB,gBAAgB,sBAAsB;IACtC,cAAc,oBAAoB;IAClC,QAAQ,cAAc;IACtB,UAAU,eAAe;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,kBAAkB,CAAC;IAClC,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;CACnC;AAsKD,wBAAgB,iBAAiB,IAAI,SAAS,YAAY,EAAE,CAE3D;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,WAAW,CAEjE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAsBjE"}
1
+ {"version":3,"file":"demo-script.d.ts","sourceRoot":"","sources":["../src/demo-script.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAE9D,oBAAY,YAAY;IACtB,gBAAgB,sBAAsB;IACtC,QAAQ,cAAc;IACtB,UAAU,eAAe;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,kBAAkB,CAAC;IAClC,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;CACnC;AA2HD,wBAAgB,iBAAiB,IAAI,SAAS,YAAY,EAAE,CAE3D;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,WAAW,CAEjE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAsBjE"}
@@ -2,7 +2,6 @@ export const DEMO_SCRIPT_SCHEMA = 'sharkcraft.demo-script/v1';
2
2
  export var DemoScenario;
3
3
  (function (DemoScenario) {
4
4
  DemoScenario["UnconfiguredRepo"] = "unconfigured-repo";
5
- DemoScenario["PlatformPlugin"] = "platform-plugin";
6
5
  DemoScenario["PrReview"] = "pr-review";
7
6
  DemoScenario["Governance"] = "governance";
8
7
  })(DemoScenario || (DemoScenario = {}));
@@ -52,48 +51,6 @@ const SCRIPTS = {
52
51
  },
53
52
  ],
54
53
  },
55
- [DemoScenario.PlatformPlugin]: {
56
- schema: DEMO_SCRIPT_SCHEMA,
57
- scenario: DemoScenario.PlatformPlugin,
58
- title: 'Add a plugin to a platform-adopter project',
59
- description: 'Uses a pack-contributed plugin construct + playbook + lifecycle profile. SharkCraft does not embed any platform-specific assumptions; everything comes from the pack.',
60
- steps: [
61
- {
62
- title: 'Confirm packs loaded',
63
- commands: ['shrk packs doctor --require-signatures'],
64
- notes: 'Set SHARKCRAFT_PACK_SECRET so signature verification can run.',
65
- },
66
- {
67
- title: 'Inspect the plugin construct contributed by the pack',
68
- commands: ['shrk constructs list --filter plugin', 'shrk constructs get <pack>.plugin'],
69
- },
70
- {
71
- title: 'Walk the add-plugin playbook',
72
- commands: [
73
- 'shrk playbooks recommend "add a profile plugin"',
74
- 'shrk playbooks list --filter plugin',
75
- ],
76
- },
77
- {
78
- title: 'Use the lifecycle profile (rename / remove preview)',
79
- commands: [
80
- 'shrk plugin lifecycle profiles',
81
- 'shrk plugin lifecycle list --profile <id>',
82
- 'shrk plugin rename old new --profile <id> --dry-run',
83
- ],
84
- },
85
- {
86
- title: 'Render a chunked agent brief',
87
- commands: [
88
- 'shrk brief "create a user profile plugin" --mode implementation --chunk --output-dir .sharkcraft/briefs/profile-plugin',
89
- ],
90
- },
91
- {
92
- title: 'Start a dev session and let an agent take it from here',
93
- commands: ['shrk dev start "create a user profile plugin" --brief'],
94
- },
95
- ],
96
- },
97
54
  [DemoScenario.PrReview]: {
98
55
  schema: DEMO_SCRIPT_SCHEMA,
99
56
  scenario: DemoScenario.PrReview,
@@ -101,7 +101,7 @@ export function buildDocsCheck(projectRoot, options = {}) {
101
101
  severity: 'warning',
102
102
  message: 'README does not explicitly state that MCP is read-only.',
103
103
  file: 'README.md',
104
- suggestion: 'Include the phrase "MCP is read-only" so adopters can scan-find it.',
104
+ suggestion: 'Include the phrase "MCP is read-only" so consumers can scan-find it.',
105
105
  });
106
106
  }
107
107
  // Validate internal links.