@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.
- package/README.md +1 -1
- package/dist/adoption-state.js +1 -1
- package/dist/agent-brief.d.ts.map +1 -1
- package/dist/agent-brief.js +10 -59
- package/dist/agent-task-prep.d.ts.map +1 -1
- package/dist/agent-task-prep.js +3 -1
- package/dist/ai-readiness.d.ts +9 -84
- package/dist/ai-readiness.d.ts.map +1 -1
- package/dist/ai-readiness.js +30 -161
- package/dist/apply-dispatch-trace.d.ts +2 -1
- package/dist/apply-dispatch-trace.d.ts.map +1 -1
- package/dist/apply-dispatch-trace.js +9 -0
- package/dist/area-explore.d.ts.map +1 -1
- package/dist/area-explore.js +5 -1
- package/dist/area-map.d.ts +19 -0
- package/dist/area-map.d.ts.map +1 -1
- package/dist/area-map.js +27 -0
- package/dist/ci-permissions-fix.d.ts +1 -1
- package/dist/ci-permissions-fix.d.ts.map +1 -1
- package/dist/ci-permissions-fix.js +182 -1
- package/dist/compliance-profiles.js +1 -1
- package/dist/construct-adoption-diff.d.ts.map +1 -1
- package/dist/construct-adoption-diff.js +1 -2
- package/dist/construct-adoption.d.ts.map +1 -1
- package/dist/construct-adoption.js +11 -10
- package/dist/construct-inference.d.ts.map +1 -1
- package/dist/construct-inference.js +1 -2
- package/dist/construct-registry.d.ts.map +1 -1
- package/dist/construct-registry.js +10 -2
- package/dist/contract-template-registry.d.ts.map +1 -1
- package/dist/contract-template-registry.js +10 -2
- package/dist/convention-registry.d.ts.map +1 -1
- package/dist/convention-registry.js +10 -2
- package/dist/decision-records.d.ts.map +1 -1
- package/dist/decision-records.js +9 -2
- package/dist/demo-script.d.ts +1 -0
- package/dist/demo-script.d.ts.map +1 -1
- package/dist/demo-script.js +43 -0
- package/dist/docs-check.js +1 -1
- package/dist/drift-baseline.d.ts.map +1 -1
- package/dist/drift-baseline.js +2 -5
- package/dist/feedback-ingestion.d.ts.map +1 -1
- package/dist/feedback-ingestion.js +16 -2
- package/dist/git-helpers.d.ts +12 -0
- package/dist/git-helpers.d.ts.map +1 -1
- package/dist/git-helpers.js +63 -0
- package/dist/helper-registry.d.ts +54 -27
- package/dist/helper-registry.d.ts.map +1 -1
- package/dist/helper-registry.js +517 -16
- package/dist/impact-analysis.d.ts.map +1 -1
- package/dist/impact-analysis.js +5 -4
- package/dist/impact-render.d.ts.map +1 -1
- package/dist/impact-render.js +9 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/ingest-drafts.js +4 -8
- package/dist/migration-profile-registry.d.ts.map +1 -1
- package/dist/migration-profile-registry.js +10 -2
- package/dist/monorepo-onboarding.js +2 -2
- package/dist/onboarding-drafts-merge.d.ts +71 -0
- package/dist/onboarding-drafts-merge.d.ts.map +1 -0
- package/dist/onboarding-drafts-merge.js +174 -0
- package/dist/onboarding-drafts.d.ts +14 -0
- package/dist/onboarding-drafts.d.ts.map +1 -1
- package/dist/onboarding-drafts.js +39 -5
- package/dist/onboarding-report.d.ts.map +1 -1
- package/dist/onboarding-report.js +1 -5
- package/dist/onboarding.d.ts +1 -1
- package/dist/onboarding.d.ts.map +1 -1
- package/dist/onboarding.js +64 -5
- package/dist/ownership.js +10 -2
- package/dist/pack-contributions-inventory.d.ts +1 -0
- package/dist/pack-contributions-inventory.d.ts.map +1 -1
- package/dist/pack-contributions-inventory.js +24 -0
- package/dist/pack-helper-registry.d.ts.map +1 -1
- package/dist/pack-helper-registry.js +10 -2
- package/dist/pack-release-check.d.ts.map +1 -1
- package/dist/pack-release-check.js +11 -4
- package/dist/pack-signature-status.d.ts.map +1 -1
- package/dist/pack-signature-status.js +1 -0
- package/dist/pack-symbol-compat.d.ts +17 -4
- package/dist/pack-symbol-compat.d.ts.map +1 -1
- package/dist/pack-symbol-compat.js +155 -7
- package/dist/pack-test-runner.js +10 -2
- package/dist/plan-simulation.d.ts.map +1 -1
- package/dist/plan-simulation.js +20 -3
- package/dist/playbook-registry.d.ts.map +1 -1
- package/dist/playbook-registry.js +10 -2
- package/dist/plugin-lifecycle-profile-registry.d.ts +52 -0
- package/dist/plugin-lifecycle-profile-registry.d.ts.map +1 -0
- package/dist/plugin-lifecycle-profile-registry.js +202 -0
- package/dist/plugin-lifecycle.d.ts +132 -0
- package/dist/plugin-lifecycle.d.ts.map +1 -0
- package/dist/plugin-lifecycle.js +477 -0
- package/dist/policy-engine.d.ts.map +1 -1
- package/dist/policy-engine.js +11 -3
- package/dist/policy-test.js +11 -3
- package/dist/product-coherence.js +5 -5
- package/dist/profile-registry.d.ts +1 -0
- package/dist/profile-registry.d.ts.map +1 -1
- package/dist/profile-registry.js +32 -4
- package/dist/quality-baseline.d.ts.map +1 -1
- package/dist/quality-baseline.js +1 -3
- package/dist/ranker-explainability.d.ts.map +1 -1
- package/dist/ranker-explainability.js +9 -3
- package/dist/registration-hint-registry.d.ts.map +1 -1
- package/dist/registration-hint-registry.js +10 -2
- package/dist/release-readiness.js +5 -5
- package/dist/reposet.js +1 -1
- package/dist/repository-knowledge-model.d.ts +1 -1
- package/dist/repository-knowledge-model.d.ts.map +1 -1
- package/dist/review-packet-v2.d.ts.map +1 -1
- package/dist/review-packet-v2.js +13 -3
- package/dist/rule-scaffold.d.ts.map +1 -1
- package/dist/rule-scaffold.js +4 -12
- package/dist/scaffold-patterns.js +10 -2
- package/dist/search-tuning-registry.d.ts.map +1 -1
- package/dist/search-tuning-registry.js +10 -2
- package/dist/self-config-doctor-v2.d.ts +1 -1
- package/dist/self-config-doctor-v2.d.ts.map +1 -1
- package/dist/self-config-doctor-v2.js +10 -6
- package/dist/self-config-doctor.d.ts.map +1 -1
- package/dist/self-config-doctor.js +13 -7
- package/dist/sharkcraft-inspector.d.ts.map +1 -1
- package/dist/sharkcraft-inspector.js +0 -1
- package/dist/start-here.d.ts +1 -1
- package/dist/start-here.js +1 -1
- package/dist/task-ranker.d.ts.map +1 -1
- package/dist/task-ranker.js +31 -1
- package/dist/task-routing-hint-registry.d.ts.map +1 -1
- package/dist/task-routing-hint-registry.js +10 -2
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +16 -8
- package/dist/universal-search.d.ts +1 -0
- package/dist/universal-search.d.ts.map +1 -1
- package/dist/universal-search.js +12 -0
- package/dist/upgrade-advisor.js +1 -1
- package/package.json +21 -22
- package/dist/synthesize-from-onboarding.d.ts +0 -68
- package/dist/synthesize-from-onboarding.d.ts.map +0 -1
- 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/
|
|
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
|
|
package/dist/adoption-state.js
CHANGED
|
@@ -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.
|
|
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;
|
|
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"}
|
package/dist/agent-brief.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
260
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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":"
|
|
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"}
|
package/dist/agent-task-prep.js
CHANGED
|
@@ -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: [
|
package/dist/ai-readiness.d.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
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":"
|
|
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"}
|
package/dist/ai-readiness.js
CHANGED
|
@@ -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
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
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 —
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
219
|
-
|
|
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.
|
|
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' &&
|
|
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
|
|
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
|
-
?
|
|
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 (
|
|
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
|
|
382
|
-
const
|
|
383
|
-
const
|
|
384
|
-
const
|
|
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
|
}
|