@shrkcrft/inspector 0.1.0-alpha.6 → 0.1.0-alpha.8

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 (112) hide show
  1. package/dist/agent-brief.d.ts.map +1 -1
  2. package/dist/agent-brief.js +59 -10
  3. package/dist/agent-task-prep.d.ts.map +1 -1
  4. package/dist/agent-task-prep.js +1 -3
  5. package/dist/ai-readiness.d.ts +84 -9
  6. package/dist/ai-readiness.d.ts.map +1 -1
  7. package/dist/ai-readiness.js +161 -30
  8. package/dist/apply-dispatch-trace.d.ts +1 -2
  9. package/dist/apply-dispatch-trace.d.ts.map +1 -1
  10. package/dist/apply-dispatch-trace.js +0 -9
  11. package/dist/area-explore.d.ts.map +1 -1
  12. package/dist/area-explore.js +1 -5
  13. package/dist/area-map.d.ts +0 -5
  14. package/dist/area-map.d.ts.map +1 -1
  15. package/dist/area-map.js +0 -10
  16. package/dist/compliance-profiles.js +1 -1
  17. package/dist/construct-adoption.d.ts.map +1 -1
  18. package/dist/construct-adoption.js +10 -11
  19. package/dist/construct-registry.d.ts.map +1 -1
  20. package/dist/construct-registry.js +2 -10
  21. package/dist/contract-template-registry.d.ts.map +1 -1
  22. package/dist/contract-template-registry.js +2 -10
  23. package/dist/convention-registry.d.ts.map +1 -1
  24. package/dist/convention-registry.js +2 -10
  25. package/dist/decision-records.d.ts.map +1 -1
  26. package/dist/decision-records.js +2 -9
  27. package/dist/demo-script.d.ts +0 -1
  28. package/dist/demo-script.d.ts.map +1 -1
  29. package/dist/demo-script.js +0 -43
  30. package/dist/docs-check.js +1 -1
  31. package/dist/drift-baseline.d.ts.map +1 -1
  32. package/dist/drift-baseline.js +5 -2
  33. package/dist/feedback-ingestion.d.ts.map +1 -1
  34. package/dist/feedback-ingestion.js +2 -16
  35. package/dist/helper-registry.d.ts +27 -54
  36. package/dist/helper-registry.d.ts.map +1 -1
  37. package/dist/helper-registry.js +16 -517
  38. package/dist/impact-analysis.d.ts.map +1 -1
  39. package/dist/impact-analysis.js +4 -5
  40. package/dist/index.d.ts +1 -2
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +1 -2
  43. package/dist/migration-profile-registry.d.ts.map +1 -1
  44. package/dist/migration-profile-registry.js +2 -10
  45. package/dist/monorepo-onboarding.js +2 -2
  46. package/dist/onboarding-report.d.ts.map +1 -1
  47. package/dist/onboarding-report.js +5 -1
  48. package/dist/onboarding.d.ts +1 -1
  49. package/dist/onboarding.d.ts.map +1 -1
  50. package/dist/onboarding.js +5 -64
  51. package/dist/ownership.js +2 -10
  52. package/dist/pack-contributions-inventory.d.ts +0 -1
  53. package/dist/pack-contributions-inventory.d.ts.map +1 -1
  54. package/dist/pack-contributions-inventory.js +0 -24
  55. package/dist/pack-helper-registry.d.ts.map +1 -1
  56. package/dist/pack-helper-registry.js +2 -10
  57. package/dist/pack-release-check.d.ts.map +1 -1
  58. package/dist/pack-release-check.js +4 -11
  59. package/dist/pack-signature-status.d.ts.map +1 -1
  60. package/dist/pack-signature-status.js +0 -1
  61. package/dist/pack-test-runner.js +2 -10
  62. package/dist/plan-simulation.d.ts.map +1 -1
  63. package/dist/plan-simulation.js +3 -20
  64. package/dist/playbook-registry.d.ts.map +1 -1
  65. package/dist/playbook-registry.js +2 -10
  66. package/dist/policy-engine.d.ts.map +1 -1
  67. package/dist/policy-engine.js +3 -11
  68. package/dist/policy-test.js +3 -11
  69. package/dist/profile-registry.d.ts +0 -1
  70. package/dist/profile-registry.d.ts.map +1 -1
  71. package/dist/profile-registry.js +4 -32
  72. package/dist/quality-baseline.d.ts.map +1 -1
  73. package/dist/quality-baseline.js +3 -1
  74. package/dist/ranker-explainability.d.ts.map +1 -1
  75. package/dist/ranker-explainability.js +3 -9
  76. package/dist/registration-hint-registry.d.ts.map +1 -1
  77. package/dist/registration-hint-registry.js +2 -10
  78. package/dist/release-readiness.js +3 -3
  79. package/dist/reposet.js +1 -1
  80. package/dist/repository-knowledge-model.d.ts +1 -1
  81. package/dist/repository-knowledge-model.d.ts.map +1 -1
  82. package/dist/scaffold-patterns.js +2 -10
  83. package/dist/search-tuning-registry.d.ts.map +1 -1
  84. package/dist/search-tuning-registry.js +2 -10
  85. package/dist/self-config-doctor-v2.d.ts +1 -1
  86. package/dist/self-config-doctor-v2.d.ts.map +1 -1
  87. package/dist/self-config-doctor-v2.js +6 -10
  88. package/dist/self-config-doctor.d.ts.map +1 -1
  89. package/dist/self-config-doctor.js +7 -13
  90. package/dist/sharkcraft-inspector.d.ts.map +1 -1
  91. package/dist/sharkcraft-inspector.js +1 -0
  92. package/dist/start-here.d.ts +1 -1
  93. package/dist/start-here.js +1 -1
  94. package/dist/synthesize-from-onboarding.d.ts +68 -0
  95. package/dist/synthesize-from-onboarding.d.ts.map +1 -0
  96. package/dist/synthesize-from-onboarding.js +508 -0
  97. package/dist/task-ranker.d.ts.map +1 -1
  98. package/dist/task-ranker.js +1 -31
  99. package/dist/task-routing-hint-registry.d.ts.map +1 -1
  100. package/dist/task-routing-hint-registry.js +2 -10
  101. package/dist/test-runner.d.ts.map +1 -1
  102. package/dist/test-runner.js +8 -16
  103. package/dist/universal-search.d.ts +0 -1
  104. package/dist/universal-search.d.ts.map +1 -1
  105. package/dist/universal-search.js +0 -12
  106. package/package.json +17 -17
  107. package/dist/plugin-lifecycle-profile-registry.d.ts +0 -52
  108. package/dist/plugin-lifecycle-profile-registry.d.ts.map +0 -1
  109. package/dist/plugin-lifecycle-profile-registry.js +0 -202
  110. package/dist/plugin-lifecycle.d.ts +0 -132
  111. package/dist/plugin-lifecycle.d.ts.map +0 -1
  112. package/dist/plugin-lifecycle.js +0 -477
@@ -1 +1 @@
1
- {"version":3,"file":"agent-brief.d.ts","sourceRoot":"","sources":["../src/agent-brief.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAS3E,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAE9D,oBAAY,SAAS;IACnB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,cAAc,mBAAmB;IACjC,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,kBAAkB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACxC,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kEAAkE;IAClE,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,8CAA8C;IAC9C,MAAM,EAAE;QACN,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,MAAM,EAAE,OAAO,CAAC;QAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC;IACF,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,sEAAsE;IACtE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,MAAM,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACtC;AAmVD,wBAAsB,eAAe,CACnC,UAAU,EAAE,qBAAqB,EACjC,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,WAAW,CAAC,CAqItB"}
1
+ {"version":3,"file":"agent-brief.d.ts","sourceRoot":"","sources":["../src/agent-brief.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAS3E,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAE9D,oBAAY,SAAS;IACnB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,cAAc,mBAAmB;IACjC,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,kBAAkB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACxC,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kEAAkE;IAClE,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,8CAA8C;IAC9C,MAAM,EAAE;QACN,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,MAAM,EAAE,OAAO,CAAC;QAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC;IACF,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,sEAAsE;IACtE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,MAAM,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACtC;AA+XD,wBAAsB,eAAe,CACnC,UAAU,EAAE,qBAAqB,EACjC,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,WAAW,CAAC,CAyItB"}
@@ -149,15 +149,23 @@ function pipelineSection(packet) {
149
149
  function actionHintsSection(packet) {
150
150
  const lines = [];
151
151
  const h = packet.actionHints;
152
+ // h.commands is IActionHintCommand[] (objects with .command + optional
153
+ // .purpose); h.mcpTools is IActionHintMcpTool[] (.tool + .purpose).
154
+ // Earlier versions string-interpolated the whole object, producing
155
+ // `- [object Object]` in the rendered brief.
152
156
  if (h.commands.length > 0) {
153
157
  lines.push('**Commands:**');
154
- for (const c of h.commands.slice(0, 5))
155
- lines.push(`- \`${c}\``);
158
+ for (const c of h.commands.slice(0, 5)) {
159
+ const purpose = c.purpose ? ` — ${c.purpose}` : '';
160
+ lines.push(`- \`${c.command}\`${purpose}`);
161
+ }
156
162
  }
157
163
  if (h.mcpTools.length > 0) {
158
164
  lines.push('**MCP tools:**');
159
- for (const m of h.mcpTools.slice(0, 5))
160
- lines.push(`- \`${m}\``);
165
+ for (const m of h.mcpTools.slice(0, 5)) {
166
+ const purpose = m.purpose ? ` — ${m.purpose}` : '';
167
+ lines.push(`- \`${m.tool}\`${purpose}`);
168
+ }
161
169
  }
162
170
  if (h.verificationCommands.length > 0) {
163
171
  lines.push('**Verification:**');
@@ -233,8 +241,14 @@ function boundarySection(impact) {
233
241
  }
234
242
  return section('boundary', 'Boundary concerns', lines.join('\n'));
235
243
  }
244
+ /**
245
+ * Compute the deduplicated suggested-commands list. The result lands
246
+ * in `IAgentBrief.suggestedCommands` (JSON contract preserved); a
247
+ * markdown section is rendered ONLY if the list isn't already
248
+ * covered by action-hints + verification (which it usually is — the
249
+ * duplication was a major source of the ~100-line brief bloat).
250
+ */
236
251
  function suggestedCommandsSection(impact, packet) {
237
- const lines = [];
238
252
  const commands = new Set();
239
253
  for (const c of impact?.suggestedTestCommands ?? [])
240
254
  commands.add(c);
@@ -242,10 +256,21 @@ function suggestedCommandsSection(impact, packet) {
242
256
  commands.add(c);
243
257
  for (const c of packet.recommendedCliCommands ?? [])
244
258
  commands.add(c);
245
- for (const c of [...commands].slice(0, 10))
246
- lines.push(`- \`${c}\``);
259
+ // Already-shown set: verification commands + action-hint commands
260
+ // that are about to render in the actionHintsSection. Anything in
261
+ // that set should NOT also appear in "Suggested commands".
262
+ const alreadyShown = new Set();
263
+ for (const v of packet.actionHints.verificationCommands ?? [])
264
+ alreadyShown.add(v);
265
+ for (const c of packet.actionHints.commands ?? [])
266
+ alreadyShown.add(c.command);
267
+ const uniqueNew = [...commands].filter((c) => !alreadyShown.has(c));
268
+ if (uniqueNew.length === 0) {
269
+ return { section: null, commands: [...commands] };
270
+ }
271
+ const lines = uniqueNew.slice(0, 10).map((c) => `- \`${c}\``);
247
272
  return {
248
- section: section('suggested-commands', 'Suggested commands', lines.join('\n') || '_None._'),
273
+ section: section('suggested-commands', 'Suggested commands (not already listed above)', lines.join('\n')),
249
274
  commands: [...commands],
250
275
  };
251
276
  }
@@ -313,12 +338,31 @@ async function qualitySection(inspection, baselineFile) {
313
338
  ];
314
339
  return section('quality', 'Quality baseline', lines.join('\n'));
315
340
  }
341
+ /**
342
+ * Empty-section detector. A section is "empty" when its body is just
343
+ * an italicized placeholder like `_None._` / `_No impact analysis
344
+ * available._` / `_No ownership data._`. Suppressing these compresses
345
+ * the typical brief from ~100 lines to ~40 — Claude doesn't need to
346
+ * read "Policy concerns: _None detected._" to make a decision.
347
+ */
348
+ function isEmptyBody(body) {
349
+ const trimmed = body.trim();
350
+ if (!trimmed)
351
+ return true;
352
+ // Pure single-line italicized placeholder, e.g. `_None._` / `_No X data._`.
353
+ return /^_[^_]+_$/.test(trimmed);
354
+ }
316
355
  function sectionsToMarkdown(task, mode, sections) {
317
356
  const lines = [];
318
357
  lines.push(`# SharkCraft brief: ${task || '(no task)'}`);
319
358
  lines.push('');
320
- lines.push(`_Mode: \`${mode}\`${new Date().toISOString()}_`);
359
+ // Mode only timestamp adds noise to a "single page Claude reads
360
+ // first" doc. The IAgentBrief.generatedAt field still carries it
361
+ // for tooling that needs the timestamp.
362
+ lines.push(`_Mode: \`${mode}\`_`);
321
363
  for (const s of sections) {
364
+ if (isEmptyBody(s.body))
365
+ continue;
322
366
  lines.push('');
323
367
  lines.push(`## ${s.title}`);
324
368
  lines.push('');
@@ -398,7 +442,12 @@ export async function buildAgentBrief(inspection, input) {
398
442
  }
399
443
  // Always include suggested commands + safety.
400
444
  const { section: cmdSection, commands } = suggestedCommandsSection(impact, packet);
401
- sections.push(cmdSection);
445
+ // Only push when the section returns one — most briefs no longer
446
+ // include this section because everything it would list is already
447
+ // in action-hints / verification. The `commands` array still ships
448
+ // in IAgentBrief.suggestedCommands for tooling that consumes it.
449
+ if (cmdSection)
450
+ sections.push(cmdSection);
402
451
  sections.push(safetySection());
403
452
  // Apply per-section budgets when requested.
404
453
  const trimmedSections = input.sectionBudgets && Object.keys(input.sectionBudgets).length > 0
@@ -1 +1 @@
1
- {"version":3,"file":"agent-task-prep.d.ts","sourceRoot":"","sources":["../src/agent-task-prep.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,sBAAsB,kCAAkC,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,OAAO,sBAAsB,CAAC;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC/C,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpE,QAAQ,CAAC,mBAAmB,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvE,QAAQ,CAAC,YAAY,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IAC5F,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,qBAAqB,EACjC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,oBAAoB,CAAC,CAqD/B"}
1
+ {"version":3,"file":"agent-task-prep.d.ts","sourceRoot":"","sources":["../src/agent-task-prep.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,sBAAsB,kCAAkC,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,OAAO,sBAAsB,CAAC;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC/C,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpE,QAAQ,CAAC,mBAAmB,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvE,QAAQ,CAAC,YAAY,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IAC5F,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,qBAAqB,EACjC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,oBAAoB,CAAC,CAoD/B"}
@@ -13,7 +13,6 @@
13
13
  * Read-only. Never writes; never executes commands.
14
14
  */
15
15
  import { buildTaskPacket } from "./task-packet.js";
16
- import { listPluginLifecycleProfiles } from "./plugin-lifecycle-profile-registry.js";
17
16
  import { listConventions } from "./convention-registry.js";
18
17
  import { listTaskRoutingHints, explainTaskRouting } from "./task-routing-hint-registry.js";
19
18
  import { buildUncertaintySummary } from "./uncertainty.js";
@@ -21,7 +20,6 @@ export const AGENT_TASK_PREP_SCHEMA = 'sharkcraft.agent-task-prep/v1';
21
20
  export async function prepareAgentTask(inspection, task) {
22
21
  const packet = buildTaskPacket(inspection, task);
23
22
  const uncertaintyReport = buildUncertaintySummary(packet);
24
- const lifecycle = await listPluginLifecycleProfiles(inspection);
25
23
  const conventions = await listConventions(inspection);
26
24
  const routing = await explainTaskRouting(inspection, task);
27
25
  await listTaskRoutingHints(inspection); // warm cache
@@ -60,7 +58,7 @@ export async function prepareAgentTask(inspection, task) {
60
58
  inspectionCommands,
61
59
  generationCommands,
62
60
  validationCommands,
63
- relevantProfiles: lifecycle.slice(0, 5).map((e) => ({ id: e.profile.id, title: e.profile.title })),
61
+ relevantProfiles: [],
64
62
  relevantConventions: conventions.slice(0, 5).map((e) => ({ id: e.convention.id, title: e.convention.title })),
65
63
  routingHints: routing.slice(0, 5).map((m) => ({ id: m.hint.id, title: m.hint.title, reasons: m.reasons })),
66
64
  safetyNotes: [
@@ -1,30 +1,105 @@
1
1
  import type { ISharkcraftInspection } from './sharkcraft-inspector.js';
2
+ /**
3
+ * Per-dimension applies-to status.
4
+ *
5
+ * - `core` — dimension applies to this workspace shape; counted in the
6
+ * aggregate score.
7
+ * - `advisory` — dimension applies but is not load-bearing for the
8
+ * shape; shown in output, NOT counted in the aggregate, and does NOT
9
+ * produce a recommendation. Lets the user see "you could add this"
10
+ * without dragging the score down for a perfectly-shaped repo.
11
+ * - `n/a-for-shape` — dimension is irrelevant to this workspace shape
12
+ * (e.g. "templates" for a CLI library that doesn't scaffold
13
+ * anything). Hidden from default output, NOT counted, NO
14
+ * recommendation. Surfaced with `--show-na`.
15
+ */
16
+ export type DimensionAppliesTo = 'core' | 'advisory' | 'n/a-for-shape';
2
17
  export interface IReadinessDimension {
3
18
  id: string;
4
19
  title: string;
5
20
  /** 0–10 score. */
6
21
  score: number;
7
- /** Weight applied to the score in the final aggregate. */
22
+ /** Weight applied to the score in the final aggregate (only used when applies === 'core'). */
8
23
  weight: number;
9
24
  /** Free-form note explaining the score. */
10
25
  note: string;
26
+ /** Does this dimension apply to the detected workspace shape? */
27
+ applies: DimensionAppliesTo;
28
+ /** When applies !== 'core', a one-line reason the dimension was skipped. */
29
+ appliesReason?: string;
11
30
  }
12
31
  export type ReadinessGrade = 'excellent' | 'good' | 'partial' | 'poor';
32
+ /**
33
+ * One of four binary verdicts surfaced in the doctor output. Replaces
34
+ * the older "look at the 0-100 score" UX with a clear yes/no for the
35
+ * two questions users actually want answered.
36
+ */
37
+ export interface IReadinessVerdicts {
38
+ /** Can an AI agent rely on shrk to apply changes safely? */
39
+ readyForAgentWrites: boolean;
40
+ /** Can an AI agent use shrk's read-only surface (context / task)? */
41
+ readyForAgentReads: boolean;
42
+ /** Concrete things blocking `readyForAgentWrites`. */
43
+ blockers: readonly string[];
44
+ }
13
45
  export interface IReadinessReport {
14
- /** 0..100 weighted score. */
46
+ /** 0..100 weighted score, counting only `core` dimensions. */
15
47
  score: number;
16
48
  grade: ReadinessGrade;
17
49
  dimensions: IReadinessDimension[];
18
- /** Up to 5 prioritized actions to improve the score. */
50
+ /** Up to 5 prioritized actions to improve the score (only from core dims). */
19
51
  topRecommendations: string[];
52
+ /** Honest binary verdicts that don't depend on softcap scoring. */
53
+ verdicts: IReadinessVerdicts;
54
+ /** Detected workspace shape — drives which dimensions count as core. */
55
+ workspaceShape: IWorkspaceShape;
56
+ }
57
+ /**
58
+ * Coarse classification of the workspace, used to decide which readiness
59
+ * dimensions are load-bearing. Derived from `WorkspaceProfile[]`.
60
+ */
61
+ export interface IWorkspaceShape {
62
+ /** Best-effort one-line description of the shape. */
63
+ label: string;
64
+ /** True if the workspace publishes a library (no user-facing scaffolding). */
65
+ isLibrary: boolean;
66
+ /** True if the workspace runs a service (HTTP / queue / daemon). */
67
+ isService: boolean;
68
+ /** True if the workspace is a monorepo (Nx / Turborepo / pnpm-workspaces). */
69
+ isMonorepo: boolean;
70
+ /** True if the workspace owns end-user code (Angular app / Next.js app / Nest service / generic frontend / backend). */
71
+ isApplication: boolean;
20
72
  }
21
73
  /**
22
- * Deterministic 0..100 AI-readiness score. Penalties are explicit:
23
- * - Quantity-only "stuff a registry full of entries" is capped via softCap.
24
- * - Duplicate-id warnings reduce data-quality dimension.
25
- * - Placeholder docs (TODO / TBD / "fill in") reduce docs dimension.
26
- * - Critical/high workflow entries missing actionHints reduce safety dim.
27
- * - Doctor health stays a hard gate.
74
+ * Deterministic AI-readiness report.
75
+ *
76
+ * Replaces the original "single 0-100 score" UX with a shape-aware
77
+ * report. Each dimension is classified as:
78
+ *
79
+ * - `core` counts in the aggregate score; produces a recommendation
80
+ * when below threshold.
81
+ * - `advisory` — shown but doesn't drag the score down; no
82
+ * recommendation. Used for dimensions that are nice-to-have but
83
+ * not load-bearing for the detected workspace shape (e.g. docs in
84
+ * a CLI library).
85
+ * - `n/a-for-shape` — irrelevant to this workspace; hidden by
86
+ * default. Lets a CLI library skip "add templates" without
87
+ * manually suppressing every release.
88
+ *
89
+ * Two binary verdicts ride alongside the score:
90
+ * - `readyForAgentWrites` — every gate an autonomous agent would need
91
+ * before issuing `shrk apply` (config + cli-only safety + clean
92
+ * doctor).
93
+ * - `readyForAgentReads` — every gate a read-only agent (e.g. an MCP
94
+ * context lookup) would need (knowledge entries loaded + doctor
95
+ * clean).
96
+ *
97
+ * Numerical penalties stay explicit:
98
+ * - Quantity-only "stuff a registry full of entries" is capped via softCap.
99
+ * - Duplicate-id warnings reduce data-quality dimension.
100
+ * - Placeholder docs (TODO / TBD / "fill in") reduce docs dimension.
101
+ * - Critical/high workflow entries missing actionHints reduce safety dim.
102
+ * - Doctor health stays a hard gate.
28
103
  */
29
104
  export declare function buildAiReadinessReport(inspection: ISharkcraftInspection): IReadinessReport;
30
105
  //# sourceMappingURL=ai-readiness.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-readiness.d.ts","sourceRoot":"","sources":["../src/ai-readiness.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIvE,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,wDAAwD;IACxD,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAmCD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,qBAAqB,GAAG,gBAAgB,CAqQ1F"}
1
+ {"version":3,"file":"ai-readiness.d.ts","sourceRoot":"","sources":["../src/ai-readiness.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAIvE;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,UAAU,GAAG,eAAe,CAAC;AAEvE,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,MAAM,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,OAAO,EAAE,kBAAkB,CAAC;IAC5B,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvE;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,mBAAmB,EAAE,OAAO,CAAC;IAC7B,qEAAqE;IACrE,kBAAkB,EAAE,OAAO,CAAC;IAC5B,sDAAsD;IACtD,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,8EAA8E;IAC9E,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,mEAAmE;IACnE,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,wEAAwE;IACxE,cAAc,EAAE,eAAe,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,SAAS,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,UAAU,EAAE,OAAO,CAAC;IACpB,wHAAwH;IACxH,aAAa,EAAE,OAAO,CAAC;CACxB;AAyED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,qBAAqB,GAAG,gBAAgB,CA2U1F"}
@@ -1,4 +1,5 @@
1
1
  import { KnowledgeType, hasActionHints } from '@shrkcrft/knowledge';
2
+ import { WorkspaceProfile } from '@shrkcrft/workspace';
2
3
  import { diagnoseActionHints } from "./action-hint-diagnostics.js";
3
4
  import { runDoctor } from "./sharkcraft-inspector.js";
4
5
  function gradeOf(score) {
@@ -37,17 +38,97 @@ function isCriticalOrHighWorkflow(entry) {
37
38
  return p === 'critical' || p === 'high';
38
39
  }
39
40
  /**
40
- * Deterministic 0..100 AI-readiness score. Penalties are explicit:
41
- * - Quantity-only "stuff a registry full of entries" is capped via softCap.
42
- * - Duplicate-id warnings reduce data-quality dimension.
43
- * - Placeholder docs (TODO / TBD / "fill in") reduce docs dimension.
44
- * - Critical/high workflow entries missing actionHints reduce safety dim.
45
- * - Doctor health stays a hard gate.
41
+ * Classify the workspace from its profile flags. Used to mark dimensions
42
+ * core / advisory / n/a so the aggregate score reflects what actually
43
+ * matters for this repo.
44
+ */
45
+ function classifyShape(profiles) {
46
+ const has = (p) => profiles.includes(p);
47
+ const isLibrary = has(WorkspaceProfile.IsLibrary);
48
+ const isService = has(WorkspaceProfile.IsService);
49
+ const isMonorepo = has(WorkspaceProfile.IsMonorepo) ||
50
+ has(WorkspaceProfile.HasNx) ||
51
+ has(WorkspaceProfile.HasTurborepo) ||
52
+ has(WorkspaceProfile.HasPackageWorkspaces);
53
+ const isApplication = !isLibrary &&
54
+ (has(WorkspaceProfile.IsFrontend) ||
55
+ has(WorkspaceProfile.IsBackend) ||
56
+ isService);
57
+ let label;
58
+ if (isMonorepo) {
59
+ label = isLibrary ? 'library monorepo' : 'monorepo';
60
+ }
61
+ else if (isLibrary) {
62
+ label = 'library';
63
+ }
64
+ else if (isService) {
65
+ label = 'service';
66
+ }
67
+ else if (has(WorkspaceProfile.IsFrontend)) {
68
+ label = 'frontend app';
69
+ }
70
+ else if (has(WorkspaceProfile.IsBackend)) {
71
+ label = 'backend app';
72
+ }
73
+ else if (has(WorkspaceProfile.HasTypeScript)) {
74
+ label = 'TypeScript project';
75
+ }
76
+ else {
77
+ label = 'unclassified';
78
+ }
79
+ return { label, isLibrary, isService, isMonorepo, isApplication };
80
+ }
81
+ /**
82
+ * Deterministic AI-readiness report.
83
+ *
84
+ * Replaces the original "single 0-100 score" UX with a shape-aware
85
+ * report. Each dimension is classified as:
86
+ *
87
+ * - `core` — counts in the aggregate score; produces a recommendation
88
+ * when below threshold.
89
+ * - `advisory` — shown but doesn't drag the score down; no
90
+ * recommendation. Used for dimensions that are nice-to-have but
91
+ * not load-bearing for the detected workspace shape (e.g. docs in
92
+ * a CLI library).
93
+ * - `n/a-for-shape` — irrelevant to this workspace; hidden by
94
+ * default. Lets a CLI library skip "add templates" without
95
+ * manually suppressing every release.
96
+ *
97
+ * Two binary verdicts ride alongside the score:
98
+ * - `readyForAgentWrites` — every gate an autonomous agent would need
99
+ * before issuing `shrk apply` (config + cli-only safety + clean
100
+ * doctor).
101
+ * - `readyForAgentReads` — every gate a read-only agent (e.g. an MCP
102
+ * context lookup) would need (knowledge entries loaded + doctor
103
+ * clean).
104
+ *
105
+ * Numerical penalties stay explicit:
106
+ * - Quantity-only "stuff a registry full of entries" is capped via softCap.
107
+ * - Duplicate-id warnings reduce data-quality dimension.
108
+ * - Placeholder docs (TODO / TBD / "fill in") reduce docs dimension.
109
+ * - Critical/high workflow entries missing actionHints reduce safety dim.
110
+ * - Doctor health stays a hard gate.
46
111
  */
47
112
  export function buildAiReadinessReport(inspection) {
48
113
  const dims = [];
49
114
  const recs = [];
50
- // 1) Config present
115
+ const shape = classifyShape(inspection.workspace.profiles);
116
+ // Reusable applies-to predicates.
117
+ const templatesApply = shape.isLibrary && !shape.isMonorepo
118
+ ? 'n/a-for-shape'
119
+ : shape.isApplication
120
+ ? 'core'
121
+ : 'advisory';
122
+ const pipelinesApply = shape.isLibrary && !shape.isMonorepo
123
+ ? 'n/a-for-shape'
124
+ : 'advisory';
125
+ const pathsApply = shape.isMonorepo || shape.isApplication
126
+ ? 'core'
127
+ : 'advisory';
128
+ const docsApply = shape.isApplication || shape.isMonorepo
129
+ ? 'core'
130
+ : 'advisory';
131
+ // 1) Config present — always core (this is the "did you opt in?" signal).
51
132
  dims.push({
52
133
  id: 'config',
53
134
  title: 'sharkcraft.config.ts present',
@@ -56,6 +137,7 @@ export function buildAiReadinessReport(inspection) {
56
137
  note: inspection.configFile
57
138
  ? `loaded from ${inspection.configFile}`
58
139
  : 'missing — using defaults',
140
+ applies: 'core',
59
141
  });
60
142
  if (!inspection.configFile) {
61
143
  recs.push('Create sharkcraft/sharkcraft.config.ts to opt in to project-specific config.');
@@ -68,6 +150,7 @@ export function buildAiReadinessReport(inspection) {
68
150
  weight: 1.0,
69
151
  score: softCapScore(k, 15),
70
152
  note: `${k} entries (softcap 15, full at 22)`,
153
+ applies: 'core',
71
154
  });
72
155
  if (k < 10)
73
156
  recs.push('Add more structured knowledge entries (target: 10+).');
@@ -79,10 +162,11 @@ export function buildAiReadinessReport(inspection) {
79
162
  weight: 1.0,
80
163
  score: softCapScore(rules.length, 8),
81
164
  note: `${rules.length} rules (softcap 8)`,
165
+ applies: 'core',
82
166
  });
83
167
  if (rules.length < 5)
84
168
  recs.push('Add at least 5 rules describing coding/architecture conventions.');
85
- // 4) Path conventions — softcap at 6.
169
+ // 4) Path conventions — core for monorepos / applications, advisory otherwise.
86
170
  const paths = inspection.pathService.list();
87
171
  dims.push({
88
172
  id: 'paths',
@@ -90,10 +174,16 @@ export function buildAiReadinessReport(inspection) {
90
174
  weight: 0.8,
91
175
  score: softCapScore(paths.length, 6),
92
176
  note: `${paths.length} path conventions (softcap 6)`,
177
+ applies: pathsApply,
178
+ appliesReason: pathsApply === 'advisory'
179
+ ? 'Path conventions matter most for monorepos and applications with explicit src/ layouts.'
180
+ : undefined,
93
181
  });
94
- if (paths.length < 4)
182
+ if (pathsApply === 'core' && paths.length < 4) {
95
183
  recs.push('Add path conventions for src/, services/, utils/, tests/ etc.');
96
- // 5) Templates — softcap at 4.
184
+ }
185
+ // 5) Templates — n/a for pure libraries; core for applications;
186
+ // advisory for monorepos (often useful but not load-bearing).
97
187
  const t = inspection.templates.length;
98
188
  dims.push({
99
189
  id: 'templates',
@@ -101,10 +191,18 @@ export function buildAiReadinessReport(inspection) {
101
191
  weight: 0.8,
102
192
  score: softCapScore(t, 4),
103
193
  note: `${t} templates (softcap 4)`,
194
+ applies: templatesApply,
195
+ appliesReason: templatesApply === 'n/a-for-shape'
196
+ ? 'Libraries don\'t scaffold downstream code — templates are not load-bearing here.'
197
+ : templatesApply === 'advisory'
198
+ ? 'Templates help generate consistent constructs, but the repo can be agent-ready without them.'
199
+ : undefined,
104
200
  });
105
- if (t < 3)
201
+ if (templatesApply === 'core' && t < 3) {
106
202
  recs.push('Define templates for the constructs you generate most often.');
107
- // 6) Pipelines — softcap at 3.
203
+ }
204
+ // 6) Pipelines — n/a for pure libraries; advisory for everything else.
205
+ // Pipelines are nice but rarely block agent workflows.
108
206
  const p = inspection.pipelines.length;
109
207
  dims.push({
110
208
  id: 'pipelines',
@@ -112,9 +210,13 @@ export function buildAiReadinessReport(inspection) {
112
210
  weight: 0.8,
113
211
  score: softCapScore(p, 3),
114
212
  note: `${p} pipelines (softcap 3)`,
213
+ applies: pipelinesApply,
214
+ appliesReason: pipelinesApply === 'n/a-for-shape'
215
+ ? 'Libraries don\'t orchestrate feature pipelines — this dimension does not apply.'
216
+ : 'Pipelines describe preferred flows; a repo can be agent-ready with just rules + path conventions.',
115
217
  });
116
- if (p < 2)
117
- recs.push('Add at least one feature-dev or safe-generation pipeline.');
218
+ // No recommendation when pipelines is advisory — the old "add a pipeline"
219
+ // exhortation fired on libraries it shouldn't have.
118
220
  // 7) Action-hint coverage — fraction of entries that carry hints.
119
221
  const withHints = inspection.knowledgeEntries.filter((e) => hasActionHints(e)).length;
120
222
  const hintsScore = k === 0 ? 0 : Math.min(10, Math.round((withHints / Math.max(k, 1)) * 20));
@@ -124,6 +226,7 @@ export function buildAiReadinessReport(inspection) {
124
226
  weight: 1.2,
125
227
  score: hintsScore,
126
228
  note: `${withHints} of ${k} entries carry actionHints`,
229
+ applies: 'core',
127
230
  });
128
231
  if (hintsScore < 7)
129
232
  recs.push('Add actionHints to high-priority rules (commands, mcpTools, forbiddenActions).');
@@ -135,6 +238,7 @@ export function buildAiReadinessReport(inspection) {
135
238
  weight: 0.6,
136
239
  score: haveVerify ? 10 : 0,
137
240
  note: haveVerify ? 'at least one entry lists verification commands' : 'no entry lists verification commands',
241
+ applies: 'core',
138
242
  });
139
243
  if (!haveVerify)
140
244
  recs.push('Add verificationCommands to safety/generation rules (e.g. typecheck + tests).');
@@ -146,10 +250,11 @@ export function buildAiReadinessReport(inspection) {
146
250
  weight: 0.6,
147
251
  score: haveForbidden ? 10 : 0,
148
252
  note: haveForbidden ? 'at least one entry lists forbiddenActions' : 'no entry lists forbiddenActions',
253
+ applies: 'core',
149
254
  });
150
255
  if (!haveForbidden)
151
256
  recs.push('Add forbiddenActions to clarify what agents must NOT do.');
152
- // 10) Docs — softcap at 4. Penalize placeholder docs.
257
+ // 10) Docs — softcap at 4. Penalize placeholder docs. Advisory for libraries.
153
258
  const docFiles = inspection.sourceFiles.filter((s) => s.endsWith('.md'));
154
259
  let placeholderDocCount = 0;
155
260
  for (const entry of inspection.knowledgeEntries) {
@@ -169,19 +274,17 @@ export function buildAiReadinessReport(inspection) {
169
274
  note: placeholderDocCount > 0
170
275
  ? `${docFiles.length} markdown files (-${docsPenalty} for ${placeholderDocCount} placeholder markers)`
171
276
  : `${docFiles.length} markdown files`,
277
+ applies: docsApply,
278
+ appliesReason: docsApply === 'advisory'
279
+ ? 'Standalone libraries communicate via README + API docs more than per-task markdown.'
280
+ : undefined,
172
281
  });
173
282
  if (placeholderDocCount > 0) {
174
283
  recs.push(`Replace TODO/placeholder markers in ${placeholderDocCount} doc/task file(s).`);
175
284
  }
176
285
  // 11) Doctor health — passes is a near-required gate.
177
- //
178
- // Action-hint quality warnings are also surfaced by the doctor, but the
179
- // dedicated `hint-quality` dimension below already scores them. Counting
180
- // them here too would punish the same warning twice and crush the score
181
- // once a repo crosses ten hint warnings. Exclude them from this dimension.
182
286
  const doctor = runDoctor(inspection);
183
- const structuralWarnings = doctor.checks.filter((c) => c.severity === 'warning' &&
184
- !c.id.startsWith('actionhints-')).length;
287
+ const structuralWarnings = doctor.checks.filter((c) => c.severity === 'warning' && !c.id.startsWith('actionhints-')).length;
185
288
  const doctorScore = doctor.passed ? Math.max(0, 10 - structuralWarnings) : 0;
186
289
  dims.push({
187
290
  id: 'doctor',
@@ -191,13 +294,16 @@ export function buildAiReadinessReport(inspection) {
191
294
  note: doctor.passed
192
295
  ? `passed (${structuralWarnings} structural warnings, ${doctor.summary.warnings} total)`
193
296
  : `${doctor.summary.errors} errors`,
297
+ applies: 'core',
194
298
  });
195
299
  if (!doctor.passed)
196
300
  recs.push('Fix doctor errors before relying on agent workflows.');
197
- // 12) Pack discovery health
301
+ // 12) Pack discovery health — n/a when no packs are installed (don't
302
+ // reward inaction with a neutral 5).
198
303
  const packs = inspection.packs;
304
+ const packsApply = packs.discoveredPacks.length === 0 ? 'n/a-for-shape' : 'core';
199
305
  const packsScore = packs.discoveredPacks.length === 0
200
- ? 5 // neutral when no packs are installed
306
+ ? 0 // would-be neutral 5 was masking how often this dim doesn't apply
201
307
  : packs.invalidPacks.length === 0
202
308
  ? 10
203
309
  : 4;
@@ -209,14 +315,17 @@ export function buildAiReadinessReport(inspection) {
209
315
  note: packs.discoveredPacks.length === 0
210
316
  ? 'no packs discovered'
211
317
  : `${packs.validPacks.length}/${packs.discoveredPacks.length} packs valid`,
318
+ applies: packsApply,
319
+ appliesReason: packsApply === 'n/a-for-shape'
320
+ ? 'No SharkCraft packs installed — pack-discovery health does not apply.'
321
+ : undefined,
212
322
  });
213
- if (packs.invalidPacks.length > 0) {
323
+ if (packsApply === 'core' && packs.invalidPacks.length > 0) {
214
324
  recs.push('Fix invalid pack manifests (see `shrk packs doctor`).');
215
325
  }
216
326
  // 13) Generation safety — flagship cli-only write policy rule required.
217
327
  const hasDryRunDefault = inspection.knowledgeEntries.some((e) => e.actionHints?.writePolicy === 'cli-only' ||
218
328
  (e.actionHints?.forbiddenActions ?? []).some((f) => /write through mcp/i.test(f)));
219
- // Additionally penalize when any critical/high workflow entry lacks hints.
220
329
  const workflowMissingHints = inspection.knowledgeEntries.filter((e) => isCriticalOrHighWorkflow(e) && !hasActionHints(e)).length;
221
330
  let safetyScore = hasDryRunDefault ? 10 : 3;
222
331
  if (workflowMissingHints > 0) {
@@ -232,6 +341,7 @@ export function buildAiReadinessReport(inspection) {
232
341
  ? `cli-only write policy present, but ${workflowMissingHints} critical/high workflow entry/entries lack actionHints`
233
342
  : 'cli-only write policy + forbidden-actions present'
234
343
  : 'no entry declares cli-only write policy',
344
+ applies: 'core',
235
345
  });
236
346
  if (!hasDryRunDefault) {
237
347
  recs.push('Add a critical safety rule with writePolicy:"cli-only" and "do not write through MCP".');
@@ -251,6 +361,7 @@ export function buildAiReadinessReport(inspection) {
251
361
  weight: 0.6,
252
362
  score: hintIssueScore,
253
363
  note: `${hintReport.issues.length} quality warnings across ${hintReport.evaluatedEntryCount} relevant entries`,
364
+ applies: 'core',
254
365
  });
255
366
  // 15) Data quality — duplicate ids surface as warnings.
256
367
  const dupCount = inspection.validationIssues.filter((v) => v.code === 'duplicate-id').length;
@@ -263,17 +374,37 @@ export function buildAiReadinessReport(inspection) {
263
374
  note: dupCount === 0
264
375
  ? 'no duplicate knowledge ids'
265
376
  : `${dupCount} duplicate id(s) — first occurrence kept`,
377
+ applies: 'core',
266
378
  });
267
379
  if (dupCount > 0)
268
380
  recs.push(`Resolve ${dupCount} duplicate knowledge id(s).`);
269
- // Aggregate.
270
- const totalWeight = dims.reduce((sum, d) => sum + d.weight, 0);
271
- const weightedSum = dims.reduce((sum, d) => sum + d.score * d.weight, 0);
272
- const score = Math.round((weightedSum / totalWeight) * 10);
381
+ // Aggregate over `core` dimensions only — advisory + n/a do not count.
382
+ const coreDims = dims.filter((d) => d.applies === 'core');
383
+ const totalWeight = coreDims.reduce((sum, d) => sum + d.weight, 0);
384
+ const weightedSum = coreDims.reduce((sum, d) => sum + d.score * d.weight, 0);
385
+ const score = totalWeight > 0 ? Math.round((weightedSum / totalWeight) * 10) : 0;
386
+ // Binary verdicts — honest yes/no rather than a fuzzy score.
387
+ const blockers = [];
388
+ if (!doctor.passed)
389
+ blockers.push('doctor reports errors');
390
+ if (!inspection.configFile)
391
+ blockers.push('sharkcraft.config.ts missing');
392
+ if (!hasDryRunDefault)
393
+ blockers.push('no cli-only write policy rule');
394
+ if (k === 0)
395
+ blockers.push('no knowledge entries loaded');
396
+ const readyForAgentWrites = blockers.length === 0;
397
+ const readyForAgentReads = doctor.passed && k > 0;
273
398
  return {
274
399
  score,
275
400
  grade: gradeOf(score),
276
401
  dimensions: dims,
277
402
  topRecommendations: recs.slice(0, 5),
403
+ verdicts: {
404
+ readyForAgentWrites,
405
+ readyForAgentReads,
406
+ blockers,
407
+ },
408
+ workspaceShape: shape,
278
409
  };
279
410
  }
@@ -15,12 +15,11 @@ export declare const APPLY_DISPATCH_TRACE_SCHEMA = "sharkcraft.apply-dispatch-tr
15
15
  export declare enum DispatchKind {
16
16
  Template = "template",
17
17
  Helper = "helper",
18
- PluginLifecycle = "plugin-lifecycle",
19
18
  RegistrationHint = "registration-hint",
20
19
  Synthetic = "synthetic",
21
20
  Unknown = "unknown"
22
21
  }
23
- export type DispatchSource = 'registry/template' | 'registry/helper' | 'registry/plugin-lifecycle-profile' | 'registry/registration-hint' | 'synthetic' | 'unknown';
22
+ export type DispatchSource = 'registry/template' | 'registry/helper' | 'registry/registration-hint' | 'synthetic' | 'unknown';
24
23
  export interface IDispatchFileOpCounts {
25
24
  readonly create: number;
26
25
  readonly update: number;