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

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 (142) hide show
  1. package/README.md +1 -1
  2. package/dist/adoption-state.js +1 -1
  3. package/dist/agent-brief.d.ts.map +1 -1
  4. package/dist/agent-brief.js +10 -59
  5. package/dist/agent-task-prep.d.ts.map +1 -1
  6. package/dist/agent-task-prep.js +3 -1
  7. package/dist/ai-readiness.d.ts +9 -84
  8. package/dist/ai-readiness.d.ts.map +1 -1
  9. package/dist/ai-readiness.js +30 -161
  10. package/dist/apply-dispatch-trace.d.ts +2 -1
  11. package/dist/apply-dispatch-trace.d.ts.map +1 -1
  12. package/dist/apply-dispatch-trace.js +9 -0
  13. package/dist/area-explore.d.ts.map +1 -1
  14. package/dist/area-explore.js +5 -1
  15. package/dist/area-map.d.ts +19 -0
  16. package/dist/area-map.d.ts.map +1 -1
  17. package/dist/area-map.js +27 -0
  18. package/dist/ci-permissions-fix.d.ts +1 -1
  19. package/dist/ci-permissions-fix.d.ts.map +1 -1
  20. package/dist/ci-permissions-fix.js +182 -1
  21. package/dist/compliance-profiles.js +1 -1
  22. package/dist/construct-adoption-diff.d.ts.map +1 -1
  23. package/dist/construct-adoption-diff.js +1 -2
  24. package/dist/construct-adoption.d.ts.map +1 -1
  25. package/dist/construct-adoption.js +11 -10
  26. package/dist/construct-inference.d.ts.map +1 -1
  27. package/dist/construct-inference.js +1 -2
  28. package/dist/construct-registry.d.ts.map +1 -1
  29. package/dist/construct-registry.js +10 -2
  30. package/dist/contract-template-registry.d.ts.map +1 -1
  31. package/dist/contract-template-registry.js +10 -2
  32. package/dist/convention-registry.d.ts.map +1 -1
  33. package/dist/convention-registry.js +10 -2
  34. package/dist/decision-records.d.ts.map +1 -1
  35. package/dist/decision-records.js +9 -2
  36. package/dist/demo-script.d.ts +1 -0
  37. package/dist/demo-script.d.ts.map +1 -1
  38. package/dist/demo-script.js +43 -0
  39. package/dist/docs-check.js +1 -1
  40. package/dist/drift-baseline.d.ts.map +1 -1
  41. package/dist/drift-baseline.js +2 -5
  42. package/dist/feedback-ingestion.d.ts.map +1 -1
  43. package/dist/feedback-ingestion.js +16 -2
  44. package/dist/git-helpers.d.ts +12 -0
  45. package/dist/git-helpers.d.ts.map +1 -1
  46. package/dist/git-helpers.js +63 -0
  47. package/dist/helper-registry.d.ts +54 -27
  48. package/dist/helper-registry.d.ts.map +1 -1
  49. package/dist/helper-registry.js +517 -16
  50. package/dist/impact-analysis.d.ts.map +1 -1
  51. package/dist/impact-analysis.js +5 -4
  52. package/dist/impact-render.d.ts.map +1 -1
  53. package/dist/impact-render.js +9 -0
  54. package/dist/index.d.ts +3 -1
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +3 -1
  57. package/dist/ingest-drafts.js +4 -8
  58. package/dist/migration-profile-registry.d.ts.map +1 -1
  59. package/dist/migration-profile-registry.js +10 -2
  60. package/dist/monorepo-onboarding.js +2 -2
  61. package/dist/onboarding-drafts-merge.d.ts +71 -0
  62. package/dist/onboarding-drafts-merge.d.ts.map +1 -0
  63. package/dist/onboarding-drafts-merge.js +174 -0
  64. package/dist/onboarding-drafts.d.ts +14 -0
  65. package/dist/onboarding-drafts.d.ts.map +1 -1
  66. package/dist/onboarding-drafts.js +39 -5
  67. package/dist/onboarding-report.d.ts.map +1 -1
  68. package/dist/onboarding-report.js +1 -5
  69. package/dist/onboarding.d.ts +1 -1
  70. package/dist/onboarding.d.ts.map +1 -1
  71. package/dist/onboarding.js +64 -5
  72. package/dist/ownership.js +10 -2
  73. package/dist/pack-contributions-inventory.d.ts +1 -0
  74. package/dist/pack-contributions-inventory.d.ts.map +1 -1
  75. package/dist/pack-contributions-inventory.js +24 -0
  76. package/dist/pack-helper-registry.d.ts.map +1 -1
  77. package/dist/pack-helper-registry.js +10 -2
  78. package/dist/pack-release-check.d.ts.map +1 -1
  79. package/dist/pack-release-check.js +11 -4
  80. package/dist/pack-signature-status.d.ts.map +1 -1
  81. package/dist/pack-signature-status.js +1 -0
  82. package/dist/pack-symbol-compat.d.ts +17 -4
  83. package/dist/pack-symbol-compat.d.ts.map +1 -1
  84. package/dist/pack-symbol-compat.js +155 -7
  85. package/dist/pack-test-runner.js +10 -2
  86. package/dist/plan-simulation.d.ts.map +1 -1
  87. package/dist/plan-simulation.js +20 -3
  88. package/dist/playbook-registry.d.ts.map +1 -1
  89. package/dist/playbook-registry.js +10 -2
  90. package/dist/plugin-lifecycle-profile-registry.d.ts +52 -0
  91. package/dist/plugin-lifecycle-profile-registry.d.ts.map +1 -0
  92. package/dist/plugin-lifecycle-profile-registry.js +202 -0
  93. package/dist/plugin-lifecycle.d.ts +132 -0
  94. package/dist/plugin-lifecycle.d.ts.map +1 -0
  95. package/dist/plugin-lifecycle.js +477 -0
  96. package/dist/policy-engine.d.ts.map +1 -1
  97. package/dist/policy-engine.js +11 -3
  98. package/dist/policy-test.js +11 -3
  99. package/dist/product-coherence.js +5 -5
  100. package/dist/profile-registry.d.ts +1 -0
  101. package/dist/profile-registry.d.ts.map +1 -1
  102. package/dist/profile-registry.js +32 -4
  103. package/dist/quality-baseline.d.ts.map +1 -1
  104. package/dist/quality-baseline.js +1 -3
  105. package/dist/ranker-explainability.d.ts.map +1 -1
  106. package/dist/ranker-explainability.js +9 -3
  107. package/dist/registration-hint-registry.d.ts.map +1 -1
  108. package/dist/registration-hint-registry.js +10 -2
  109. package/dist/release-readiness.js +5 -5
  110. package/dist/reposet.js +1 -1
  111. package/dist/repository-knowledge-model.d.ts +1 -1
  112. package/dist/repository-knowledge-model.d.ts.map +1 -1
  113. package/dist/review-packet-v2.d.ts.map +1 -1
  114. package/dist/review-packet-v2.js +13 -3
  115. package/dist/rule-scaffold.d.ts.map +1 -1
  116. package/dist/rule-scaffold.js +4 -12
  117. package/dist/scaffold-patterns.js +10 -2
  118. package/dist/search-tuning-registry.d.ts.map +1 -1
  119. package/dist/search-tuning-registry.js +10 -2
  120. package/dist/self-config-doctor-v2.d.ts +1 -1
  121. package/dist/self-config-doctor-v2.d.ts.map +1 -1
  122. package/dist/self-config-doctor-v2.js +10 -6
  123. package/dist/self-config-doctor.d.ts.map +1 -1
  124. package/dist/self-config-doctor.js +13 -7
  125. package/dist/sharkcraft-inspector.d.ts.map +1 -1
  126. package/dist/sharkcraft-inspector.js +0 -1
  127. package/dist/start-here.d.ts +1 -1
  128. package/dist/start-here.js +1 -1
  129. package/dist/task-ranker.d.ts.map +1 -1
  130. package/dist/task-ranker.js +31 -1
  131. package/dist/task-routing-hint-registry.d.ts.map +1 -1
  132. package/dist/task-routing-hint-registry.js +10 -2
  133. package/dist/test-runner.d.ts.map +1 -1
  134. package/dist/test-runner.js +16 -8
  135. package/dist/universal-search.d.ts +1 -0
  136. package/dist/universal-search.d.ts.map +1 -1
  137. package/dist/universal-search.js +12 -0
  138. package/dist/upgrade-advisor.js +1 -1
  139. package/package.json +21 -22
  140. package/dist/synthesize-from-onboarding.d.ts +0 -68
  141. package/dist/synthesize-from-onboarding.d.ts.map +0 -1
  142. package/dist/synthesize-from-onboarding.js +0 -508
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  SharkCraft inspector: project overview, doctor checks, AI-agent instructions.
4
4
 
5
- Part of [SharkCraft](https://github.com/shrkcrft/sharkcraft) — a deterministic, local-first toolkit that gives AI coding agents durable project context. See the main repo for documentation, examples, and the `shrk` CLI.
5
+ Part of [SharkCraft](https://github.com/sharkcraft/sharkcraft) — a deterministic, local-first toolkit that gives AI coding agents durable project context. See the main repo for documentation, examples, and the `shrk` CLI.
6
6
 
7
7
  ## Install
8
8
 
@@ -133,7 +133,7 @@ export function buildAdoptionState(input) {
133
133
  projectRoot: input.projectRoot,
134
134
  createdAt: input.previousCreatedAt ?? now,
135
135
  updatedAt: now,
136
- sharkcraftVersion: input.sharkcraftVersion ?? '0.1.0-alpha.2',
136
+ sharkcraftVersion: input.sharkcraftVersion ?? '0.1.0-alpha.9',
137
137
  command: input.command,
138
138
  sourceDraftFiles: collectDraftFileHashes(input.projectRoot),
139
139
  targetFiles: collectTargetHashes(input.projectRoot, input.targets),
@@ -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;AA+XD,wBAAsB,eAAe,CACnC,UAAU,EAAE,qBAAqB,EACjC,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,WAAW,CAAC,CAyItB"}
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"}
@@ -149,23 +149,15 @@ 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.
156
152
  if (h.commands.length > 0) {
157
153
  lines.push('**Commands:**');
158
- for (const c of h.commands.slice(0, 5)) {
159
- const purpose = c.purpose ? ` — ${c.purpose}` : '';
160
- lines.push(`- \`${c.command}\`${purpose}`);
161
- }
154
+ for (const c of h.commands.slice(0, 5))
155
+ lines.push(`- \`${c}\``);
162
156
  }
163
157
  if (h.mcpTools.length > 0) {
164
158
  lines.push('**MCP tools:**');
165
- for (const m of h.mcpTools.slice(0, 5)) {
166
- const purpose = m.purpose ? ` — ${m.purpose}` : '';
167
- lines.push(`- \`${m.tool}\`${purpose}`);
168
- }
159
+ for (const m of h.mcpTools.slice(0, 5))
160
+ lines.push(`- \`${m}\``);
169
161
  }
170
162
  if (h.verificationCommands.length > 0) {
171
163
  lines.push('**Verification:**');
@@ -241,14 +233,8 @@ function boundarySection(impact) {
241
233
  }
242
234
  return section('boundary', 'Boundary concerns', lines.join('\n'));
243
235
  }
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
- */
251
236
  function suggestedCommandsSection(impact, packet) {
237
+ const lines = [];
252
238
  const commands = new Set();
253
239
  for (const c of impact?.suggestedTestCommands ?? [])
254
240
  commands.add(c);
@@ -256,21 +242,10 @@ function suggestedCommandsSection(impact, packet) {
256
242
  commands.add(c);
257
243
  for (const c of packet.recommendedCliCommands ?? [])
258
244
  commands.add(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}\``);
245
+ for (const c of [...commands].slice(0, 10))
246
+ lines.push(`- \`${c}\``);
272
247
  return {
273
- section: section('suggested-commands', 'Suggested commands (not already listed above)', lines.join('\n')),
248
+ section: section('suggested-commands', 'Suggested commands', lines.join('\n') || '_None._'),
274
249
  commands: [...commands],
275
250
  };
276
251
  }
@@ -338,31 +313,12 @@ async function qualitySection(inspection, baselineFile) {
338
313
  ];
339
314
  return section('quality', 'Quality baseline', lines.join('\n'));
340
315
  }
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
- }
355
316
  function sectionsToMarkdown(task, mode, sections) {
356
317
  const lines = [];
357
318
  lines.push(`# SharkCraft brief: ${task || '(no task)'}`);
358
319
  lines.push('');
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}\`_`);
320
+ lines.push(`_Mode: \`${mode}\`${new Date().toISOString()}_`);
363
321
  for (const s of sections) {
364
- if (isEmptyBody(s.body))
365
- continue;
366
322
  lines.push('');
367
323
  lines.push(`## ${s.title}`);
368
324
  lines.push('');
@@ -442,12 +398,7 @@ export async function buildAgentBrief(inspection, input) {
442
398
  }
443
399
  // Always include suggested commands + safety.
444
400
  const { section: cmdSection, commands } = suggestedCommandsSection(impact, packet);
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);
401
+ sections.push(cmdSection);
451
402
  sections.push(safetySection());
452
403
  // Apply per-section budgets when requested.
453
404
  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":"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"}
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"}
@@ -13,6 +13,7 @@
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";
16
17
  import { listConventions } from "./convention-registry.js";
17
18
  import { listTaskRoutingHints, explainTaskRouting } from "./task-routing-hint-registry.js";
18
19
  import { buildUncertaintySummary } from "./uncertainty.js";
@@ -20,6 +21,7 @@ export const AGENT_TASK_PREP_SCHEMA = 'sharkcraft.agent-task-prep/v1';
20
21
  export async function prepareAgentTask(inspection, task) {
21
22
  const packet = buildTaskPacket(inspection, task);
22
23
  const uncertaintyReport = buildUncertaintySummary(packet);
24
+ const lifecycle = await listPluginLifecycleProfiles(inspection);
23
25
  const conventions = await listConventions(inspection);
24
26
  const routing = await explainTaskRouting(inspection, task);
25
27
  await listTaskRoutingHints(inspection); // warm cache
@@ -58,7 +60,7 @@ export async function prepareAgentTask(inspection, task) {
58
60
  inspectionCommands,
59
61
  generationCommands,
60
62
  validationCommands,
61
- relevantProfiles: [],
63
+ relevantProfiles: lifecycle.slice(0, 5).map((e) => ({ id: e.profile.id, title: e.profile.title })),
62
64
  relevantConventions: conventions.slice(0, 5).map((e) => ({ id: e.convention.id, title: e.convention.title })),
63
65
  routingHints: routing.slice(0, 5).map((m) => ({ id: m.hint.id, title: m.hint.title, reasons: m.reasons })),
64
66
  safetyNotes: [
@@ -1,105 +1,30 @@
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';
17
2
  export interface IReadinessDimension {
18
3
  id: string;
19
4
  title: string;
20
5
  /** 0–10 score. */
21
6
  score: number;
22
- /** Weight applied to the score in the final aggregate (only used when applies === 'core'). */
7
+ /** Weight applied to the score in the final aggregate. */
23
8
  weight: number;
24
9
  /** Free-form note explaining the score. */
25
10
  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;
30
11
  }
31
12
  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
- }
45
13
  export interface IReadinessReport {
46
- /** 0..100 weighted score, counting only `core` dimensions. */
14
+ /** 0..100 weighted score. */
47
15
  score: number;
48
16
  grade: ReadinessGrade;
49
17
  dimensions: IReadinessDimension[];
50
- /** Up to 5 prioritized actions to improve the score (only from core dims). */
18
+ /** Up to 5 prioritized actions to improve the score. */
51
19
  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;
72
20
  }
73
21
  /**
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.
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.
103
28
  */
104
29
  export declare function buildAiReadinessReport(inspection: ISharkcraftInspection): IReadinessReport;
105
30
  //# sourceMappingURL=ai-readiness.d.ts.map
@@ -1 +1 @@
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
+ {"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,5 +1,4 @@
1
1
  import { KnowledgeType, hasActionHints } from '@shrkcrft/knowledge';
2
- import { WorkspaceProfile } from '@shrkcrft/workspace';
3
2
  import { diagnoseActionHints } from "./action-hint-diagnostics.js";
4
3
  import { runDoctor } from "./sharkcraft-inspector.js";
5
4
  function gradeOf(score) {
@@ -38,97 +37,17 @@ function isCriticalOrHighWorkflow(entry) {
38
37
  return p === 'critical' || p === 'high';
39
38
  }
40
39
  /**
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.
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.
111
46
  */
112
47
  export function buildAiReadinessReport(inspection) {
113
48
  const dims = [];
114
49
  const recs = [];
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).
50
+ // 1) Config present
132
51
  dims.push({
133
52
  id: 'config',
134
53
  title: 'sharkcraft.config.ts present',
@@ -137,7 +56,6 @@ export function buildAiReadinessReport(inspection) {
137
56
  note: inspection.configFile
138
57
  ? `loaded from ${inspection.configFile}`
139
58
  : 'missing — using defaults',
140
- applies: 'core',
141
59
  });
142
60
  if (!inspection.configFile) {
143
61
  recs.push('Create sharkcraft/sharkcraft.config.ts to opt in to project-specific config.');
@@ -150,7 +68,6 @@ export function buildAiReadinessReport(inspection) {
150
68
  weight: 1.0,
151
69
  score: softCapScore(k, 15),
152
70
  note: `${k} entries (softcap 15, full at 22)`,
153
- applies: 'core',
154
71
  });
155
72
  if (k < 10)
156
73
  recs.push('Add more structured knowledge entries (target: 10+).');
@@ -162,11 +79,10 @@ export function buildAiReadinessReport(inspection) {
162
79
  weight: 1.0,
163
80
  score: softCapScore(rules.length, 8),
164
81
  note: `${rules.length} rules (softcap 8)`,
165
- applies: 'core',
166
82
  });
167
83
  if (rules.length < 5)
168
84
  recs.push('Add at least 5 rules describing coding/architecture conventions.');
169
- // 4) Path conventions — core for monorepos / applications, advisory otherwise.
85
+ // 4) Path conventions — softcap at 6.
170
86
  const paths = inspection.pathService.list();
171
87
  dims.push({
172
88
  id: 'paths',
@@ -174,16 +90,10 @@ export function buildAiReadinessReport(inspection) {
174
90
  weight: 0.8,
175
91
  score: softCapScore(paths.length, 6),
176
92
  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,
181
93
  });
182
- if (pathsApply === 'core' && paths.length < 4) {
94
+ if (paths.length < 4)
183
95
  recs.push('Add path conventions for src/, services/, utils/, tests/ etc.');
184
- }
185
- // 5) Templates — n/a for pure libraries; core for applications;
186
- // advisory for monorepos (often useful but not load-bearing).
96
+ // 5) Templates — softcap at 4.
187
97
  const t = inspection.templates.length;
188
98
  dims.push({
189
99
  id: 'templates',
@@ -191,18 +101,10 @@ export function buildAiReadinessReport(inspection) {
191
101
  weight: 0.8,
192
102
  score: softCapScore(t, 4),
193
103
  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,
200
104
  });
201
- if (templatesApply === 'core' && t < 3) {
105
+ if (t < 3)
202
106
  recs.push('Define templates for the constructs you generate most often.');
203
- }
204
- // 6) Pipelines — n/a for pure libraries; advisory for everything else.
205
- // Pipelines are nice but rarely block agent workflows.
107
+ // 6) Pipelines — softcap at 3.
206
108
  const p = inspection.pipelines.length;
207
109
  dims.push({
208
110
  id: 'pipelines',
@@ -210,13 +112,9 @@ export function buildAiReadinessReport(inspection) {
210
112
  weight: 0.8,
211
113
  score: softCapScore(p, 3),
212
114
  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.',
217
115
  });
218
- // No recommendation when pipelines is advisory — the old "add a pipeline"
219
- // exhortation fired on libraries it shouldn't have.
116
+ if (p < 2)
117
+ recs.push('Add at least one feature-dev or safe-generation pipeline.');
220
118
  // 7) Action-hint coverage — fraction of entries that carry hints.
221
119
  const withHints = inspection.knowledgeEntries.filter((e) => hasActionHints(e)).length;
222
120
  const hintsScore = k === 0 ? 0 : Math.min(10, Math.round((withHints / Math.max(k, 1)) * 20));
@@ -226,7 +124,6 @@ export function buildAiReadinessReport(inspection) {
226
124
  weight: 1.2,
227
125
  score: hintsScore,
228
126
  note: `${withHints} of ${k} entries carry actionHints`,
229
- applies: 'core',
230
127
  });
231
128
  if (hintsScore < 7)
232
129
  recs.push('Add actionHints to high-priority rules (commands, mcpTools, forbiddenActions).');
@@ -238,7 +135,6 @@ export function buildAiReadinessReport(inspection) {
238
135
  weight: 0.6,
239
136
  score: haveVerify ? 10 : 0,
240
137
  note: haveVerify ? 'at least one entry lists verification commands' : 'no entry lists verification commands',
241
- applies: 'core',
242
138
  });
243
139
  if (!haveVerify)
244
140
  recs.push('Add verificationCommands to safety/generation rules (e.g. typecheck + tests).');
@@ -250,11 +146,10 @@ export function buildAiReadinessReport(inspection) {
250
146
  weight: 0.6,
251
147
  score: haveForbidden ? 10 : 0,
252
148
  note: haveForbidden ? 'at least one entry lists forbiddenActions' : 'no entry lists forbiddenActions',
253
- applies: 'core',
254
149
  });
255
150
  if (!haveForbidden)
256
151
  recs.push('Add forbiddenActions to clarify what agents must NOT do.');
257
- // 10) Docs — softcap at 4. Penalize placeholder docs. Advisory for libraries.
152
+ // 10) Docs — softcap at 4. Penalize placeholder docs.
258
153
  const docFiles = inspection.sourceFiles.filter((s) => s.endsWith('.md'));
259
154
  let placeholderDocCount = 0;
260
155
  for (const entry of inspection.knowledgeEntries) {
@@ -274,17 +169,19 @@ export function buildAiReadinessReport(inspection) {
274
169
  note: placeholderDocCount > 0
275
170
  ? `${docFiles.length} markdown files (-${docsPenalty} for ${placeholderDocCount} placeholder markers)`
276
171
  : `${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,
281
172
  });
282
173
  if (placeholderDocCount > 0) {
283
174
  recs.push(`Replace TODO/placeholder markers in ${placeholderDocCount} doc/task file(s).`);
284
175
  }
285
176
  // 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.
286
182
  const doctor = runDoctor(inspection);
287
- const structuralWarnings = doctor.checks.filter((c) => c.severity === 'warning' && !c.id.startsWith('actionhints-')).length;
183
+ const structuralWarnings = doctor.checks.filter((c) => c.severity === 'warning' &&
184
+ !c.id.startsWith('actionhints-')).length;
288
185
  const doctorScore = doctor.passed ? Math.max(0, 10 - structuralWarnings) : 0;
289
186
  dims.push({
290
187
  id: 'doctor',
@@ -294,16 +191,13 @@ export function buildAiReadinessReport(inspection) {
294
191
  note: doctor.passed
295
192
  ? `passed (${structuralWarnings} structural warnings, ${doctor.summary.warnings} total)`
296
193
  : `${doctor.summary.errors} errors`,
297
- applies: 'core',
298
194
  });
299
195
  if (!doctor.passed)
300
196
  recs.push('Fix doctor errors before relying on agent workflows.');
301
- // 12) Pack discovery health — n/a when no packs are installed (don't
302
- // reward inaction with a neutral 5).
197
+ // 12) Pack discovery health
303
198
  const packs = inspection.packs;
304
- const packsApply = packs.discoveredPacks.length === 0 ? 'n/a-for-shape' : 'core';
305
199
  const packsScore = packs.discoveredPacks.length === 0
306
- ? 0 // would-be neutral 5 was masking how often this dim doesn't apply
200
+ ? 5 // neutral when no packs are installed
307
201
  : packs.invalidPacks.length === 0
308
202
  ? 10
309
203
  : 4;
@@ -315,17 +209,14 @@ export function buildAiReadinessReport(inspection) {
315
209
  note: packs.discoveredPacks.length === 0
316
210
  ? 'no packs discovered'
317
211
  : `${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,
322
212
  });
323
- if (packsApply === 'core' && packs.invalidPacks.length > 0) {
213
+ if (packs.invalidPacks.length > 0) {
324
214
  recs.push('Fix invalid pack manifests (see `shrk packs doctor`).');
325
215
  }
326
216
  // 13) Generation safety — flagship cli-only write policy rule required.
327
217
  const hasDryRunDefault = inspection.knowledgeEntries.some((e) => e.actionHints?.writePolicy === 'cli-only' ||
328
218
  (e.actionHints?.forbiddenActions ?? []).some((f) => /write through mcp/i.test(f)));
219
+ // Additionally penalize when any critical/high workflow entry lacks hints.
329
220
  const workflowMissingHints = inspection.knowledgeEntries.filter((e) => isCriticalOrHighWorkflow(e) && !hasActionHints(e)).length;
330
221
  let safetyScore = hasDryRunDefault ? 10 : 3;
331
222
  if (workflowMissingHints > 0) {
@@ -341,7 +232,6 @@ export function buildAiReadinessReport(inspection) {
341
232
  ? `cli-only write policy present, but ${workflowMissingHints} critical/high workflow entry/entries lack actionHints`
342
233
  : 'cli-only write policy + forbidden-actions present'
343
234
  : 'no entry declares cli-only write policy',
344
- applies: 'core',
345
235
  });
346
236
  if (!hasDryRunDefault) {
347
237
  recs.push('Add a critical safety rule with writePolicy:"cli-only" and "do not write through MCP".');
@@ -361,7 +251,6 @@ export function buildAiReadinessReport(inspection) {
361
251
  weight: 0.6,
362
252
  score: hintIssueScore,
363
253
  note: `${hintReport.issues.length} quality warnings across ${hintReport.evaluatedEntryCount} relevant entries`,
364
- applies: 'core',
365
254
  });
366
255
  // 15) Data quality — duplicate ids surface as warnings.
367
256
  const dupCount = inspection.validationIssues.filter((v) => v.code === 'duplicate-id').length;
@@ -374,37 +263,17 @@ export function buildAiReadinessReport(inspection) {
374
263
  note: dupCount === 0
375
264
  ? 'no duplicate knowledge ids'
376
265
  : `${dupCount} duplicate id(s) — first occurrence kept`,
377
- applies: 'core',
378
266
  });
379
267
  if (dupCount > 0)
380
268
  recs.push(`Resolve ${dupCount} duplicate knowledge id(s).`);
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;
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);
398
273
  return {
399
274
  score,
400
275
  grade: gradeOf(score),
401
276
  dimensions: dims,
402
277
  topRecommendations: recs.slice(0, 5),
403
- verdicts: {
404
- readyForAgentWrites,
405
- readyForAgentReads,
406
- blockers,
407
- },
408
- workspaceShape: shape,
409
278
  };
410
279
  }