@shrkcrft/inspector 0.1.0-alpha.2 → 0.1.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-brief.d.ts.map +1 -1
- package/dist/agent-brief.js +59 -10
- package/dist/agent-contract-gate.d.ts.map +1 -1
- package/dist/agent-contract-gate.js +25 -2
- package/dist/agent-instructions.d.ts.map +1 -1
- package/dist/agent-instructions.js +11 -0
- package/dist/agent-task-prep.d.ts.map +1 -1
- package/dist/agent-task-prep.js +1 -3
- package/dist/ai-readiness.d.ts +84 -9
- package/dist/ai-readiness.d.ts.map +1 -1
- package/dist/ai-readiness.js +181 -35
- package/dist/apply-dispatch-trace.d.ts +1 -2
- package/dist/apply-dispatch-trace.d.ts.map +1 -1
- package/dist/apply-dispatch-trace.js +0 -9
- package/dist/area-explore.d.ts.map +1 -1
- package/dist/area-explore.js +4 -6
- package/dist/area-map.d.ts +0 -5
- package/dist/area-map.d.ts.map +1 -1
- package/dist/area-map.js +0 -10
- package/dist/changed-preflight.d.ts +7 -0
- package/dist/changed-preflight.d.ts.map +1 -1
- package/dist/changed-preflight.js +56 -9
- package/dist/changes-summary.d.ts.map +1 -1
- package/dist/changes-summary.js +20 -6
- package/dist/check-guardrail-globs.d.ts +16 -0
- package/dist/check-guardrail-globs.d.ts.map +1 -0
- package/dist/check-guardrail-globs.js +38 -0
- package/dist/code-intelligence-doctor.d.ts +21 -0
- package/dist/code-intelligence-doctor.d.ts.map +1 -0
- package/dist/code-intelligence-doctor.js +985 -0
- package/dist/command-recommender.d.ts.map +1 -1
- package/dist/command-recommender.js +23 -0
- package/dist/compliance-profiles.js +1 -1
- package/dist/construct-adoption-diff.d.ts.map +1 -1
- package/dist/construct-adoption-diff.js +2 -1
- package/dist/construct-adoption.d.ts.map +1 -1
- package/dist/construct-adoption.js +10 -11
- package/dist/construct-inference.d.ts.map +1 -1
- package/dist/construct-inference.js +5 -2
- package/dist/construct-registry.d.ts.map +1 -1
- package/dist/construct-registry.js +2 -10
- package/dist/contract-file-rule.d.ts +8 -0
- package/dist/contract-file-rule.d.ts.map +1 -1
- package/dist/contract-file-rule.js +8 -3
- package/dist/contract-template-registry.d.ts.map +1 -1
- package/dist/contract-template-registry.js +2 -10
- package/dist/contradictions.d.ts +8 -1
- package/dist/contradictions.d.ts.map +1 -1
- package/dist/contradictions.js +37 -35
- package/dist/convention-registry.d.ts.map +1 -1
- package/dist/convention-registry.js +2 -10
- package/dist/coverage-report.d.ts.map +1 -1
- package/dist/coverage-report.js +14 -1
- package/dist/dashboard/dashboard-knowledge.d.ts +8 -0
- package/dist/dashboard/dashboard-knowledge.d.ts.map +1 -0
- package/dist/dashboard/dashboard-knowledge.js +259 -0
- package/dist/decision-records.d.ts.map +1 -1
- package/dist/decision-records.js +5 -10
- package/dist/delegate-catalog.d.ts +45 -0
- package/dist/delegate-catalog.d.ts.map +1 -0
- package/dist/delegate-catalog.js +50 -0
- package/dist/delegate-doctor.d.ts +15 -0
- package/dist/delegate-doctor.d.ts.map +1 -0
- package/dist/delegate-doctor.js +36 -0
- package/dist/delegate-pack-recipes.d.ts +29 -0
- package/dist/delegate-pack-recipes.d.ts.map +1 -0
- package/dist/delegate-pack-recipes.js +77 -0
- package/dist/demo-script.d.ts +0 -1
- package/dist/demo-script.d.ts.map +1 -1
- package/dist/demo-script.js +0 -43
- package/dist/docs-check.js +1 -1
- package/dist/drift-baseline.d.ts.map +1 -1
- package/dist/drift-baseline.js +5 -2
- package/dist/feedback-ingestion.d.ts.map +1 -1
- package/dist/feedback-ingestion.js +2 -16
- package/dist/git-helpers.d.ts +15 -0
- package/dist/git-helpers.d.ts.map +1 -1
- package/dist/git-helpers.js +51 -4
- package/dist/helper-registry.d.ts +27 -54
- package/dist/helper-registry.d.ts.map +1 -1
- package/dist/helper-registry.js +16 -517
- package/dist/impact-analysis.d.ts.map +1 -1
- package/dist/impact-analysis.js +14 -7
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/ingest-drafts.js +8 -4
- package/dist/migration-profile-registry.d.ts.map +1 -1
- package/dist/migration-profile-registry.js +2 -10
- package/dist/monorepo-onboarding.js +2 -2
- package/dist/onboarding-report.d.ts.map +1 -1
- package/dist/onboarding-report.js +5 -1
- package/dist/onboarding.d.ts +1 -1
- package/dist/onboarding.d.ts.map +1 -1
- package/dist/onboarding.js +9 -66
- package/dist/ownership.js +2 -10
- package/dist/pack-contributions-inventory.d.ts +0 -1
- package/dist/pack-contributions-inventory.d.ts.map +1 -1
- package/dist/pack-contributions-inventory.js +17 -29
- package/dist/pack-helper-registry.d.ts.map +1 -1
- package/dist/pack-helper-registry.js +2 -10
- package/dist/pack-release-check.d.ts.map +1 -1
- package/dist/pack-release-check.js +4 -11
- package/dist/pack-signature-status.d.ts.map +1 -1
- package/dist/pack-signature-status.js +18 -2
- package/dist/pack-test-runner.js +2 -10
- package/dist/plan-review.d.ts.map +1 -1
- package/dist/plan-review.js +5 -10
- package/dist/plan-simulation.d.ts +13 -0
- package/dist/plan-simulation.d.ts.map +1 -1
- package/dist/plan-simulation.js +19 -28
- package/dist/playbook-registry.d.ts.map +1 -1
- package/dist/playbook-registry.js +2 -10
- package/dist/policy-engine.d.ts.map +1 -1
- package/dist/policy-engine.js +3 -11
- package/dist/policy-test.js +3 -11
- package/dist/profile-registry.d.ts +0 -1
- package/dist/profile-registry.d.ts.map +1 -1
- package/dist/profile-registry.js +4 -32
- package/dist/propose-knowledge.d.ts +15 -0
- package/dist/propose-knowledge.d.ts.map +1 -1
- package/dist/propose-knowledge.js +37 -4
- package/dist/quality-baseline.d.ts.map +1 -1
- package/dist/quality-baseline.js +3 -1
- package/dist/ranker-explainability.d.ts.map +1 -1
- package/dist/ranker-explainability.js +3 -9
- package/dist/registration-hint-registry.d.ts.map +1 -1
- package/dist/registration-hint-registry.js +2 -10
- package/dist/registry-lifecycle.d.ts +6 -0
- package/dist/registry-lifecycle.d.ts.map +1 -1
- package/dist/registry-lifecycle.js +137 -10
- package/dist/release-readiness.js +3 -3
- package/dist/repo-memory.d.ts.map +1 -1
- package/dist/repo-memory.js +3 -1
- package/dist/reposet.js +1 -1
- package/dist/repository-intelligence.d.ts.map +1 -1
- package/dist/repository-intelligence.js +7 -2
- package/dist/repository-knowledge-model.d.ts +1 -1
- package/dist/repository-knowledge-model.d.ts.map +1 -1
- package/dist/repository-stats.d.ts.map +1 -1
- package/dist/repository-stats.js +3 -1
- package/dist/resolve-verification-commands.d.ts +26 -0
- package/dist/resolve-verification-commands.d.ts.map +1 -0
- package/dist/resolve-verification-commands.js +55 -0
- package/dist/review-packet.d.ts.map +1 -1
- package/dist/review-packet.js +14 -17
- package/dist/rule-drift.d.ts.map +1 -1
- package/dist/rule-drift.js +24 -9
- package/dist/rule-scaffold.d.ts.map +1 -1
- package/dist/rule-scaffold.js +12 -4
- package/dist/scaffold-patterns.js +2 -10
- package/dist/schema-inventory.d.ts.map +1 -1
- package/dist/schema-inventory.js +3 -1
- package/dist/search-tuning-registry.d.ts.map +1 -1
- package/dist/search-tuning-registry.js +2 -10
- 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 +6 -10
- package/dist/self-config-doctor.d.ts.map +1 -1
- package/dist/self-config-doctor.js +7 -13
- package/dist/sharkcraft-inspector.d.ts +14 -0
- package/dist/sharkcraft-inspector.d.ts.map +1 -1
- package/dist/sharkcraft-inspector.js +103 -1
- package/dist/start-here.d.ts +2 -2
- package/dist/start-here.d.ts.map +1 -1
- package/dist/start-here.js +16 -1
- package/dist/synthesize-from-onboarding.d.ts +68 -0
- package/dist/synthesize-from-onboarding.d.ts.map +1 -0
- package/dist/synthesize-from-onboarding.js +508 -0
- package/dist/task-packet.d.ts +13 -0
- package/dist/task-packet.d.ts.map +1 -1
- package/dist/task-packet.js +59 -6
- package/dist/task-ranker.d.ts.map +1 -1
- package/dist/task-ranker.js +1 -31
- package/dist/task-routing-hint-registry.d.ts.map +1 -1
- package/dist/task-routing-hint-registry.js +2 -10
- package/dist/template-drift.d.ts +7 -0
- package/dist/template-drift.d.ts.map +1 -1
- package/dist/template-drift.js +14 -6
- package/dist/test-impact.d.ts.map +1 -1
- package/dist/test-impact.js +5 -2
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +12 -17
- package/dist/universal-search.d.ts +0 -1
- package/dist/universal-search.d.ts.map +1 -1
- package/dist/universal-search.js +0 -12
- package/dist/why-file.js +66 -22
- package/package.json +18 -18
- package/dist/plugin-lifecycle-profile-registry.d.ts +0 -52
- package/dist/plugin-lifecycle-profile-registry.d.ts.map +0 -1
- package/dist/plugin-lifecycle-profile-registry.js +0 -202
- package/dist/plugin-lifecycle.d.ts +0 -132
- package/dist/plugin-lifecycle.d.ts.map +0 -1
- package/dist/plugin-lifecycle.js +0 -477
package/dist/task-packet.js
CHANGED
|
@@ -2,6 +2,23 @@ import { buildContext } from '@shrkcrft/context';
|
|
|
2
2
|
import { aggregateActionHints, } from '@shrkcrft/knowledge';
|
|
3
3
|
import { rankAll } from "./task-ranker.js";
|
|
4
4
|
import { buildProjectOverview, renderOverviewText } from "./project-overview.js";
|
|
5
|
+
import { resolveVerificationCommands } from "./resolve-verification-commands.js";
|
|
6
|
+
/**
|
|
7
|
+
* Per-field caps applied to the packet when `compact: true`.
|
|
8
|
+
* Keeps the JSON small while still covering the highest-signal hits.
|
|
9
|
+
*/
|
|
10
|
+
const COMPACT_CAPS = {
|
|
11
|
+
rules: 5,
|
|
12
|
+
paths: 5,
|
|
13
|
+
templates: 3,
|
|
14
|
+
commands: 5,
|
|
15
|
+
mcpTools: 5,
|
|
16
|
+
forbiddenActions: 5,
|
|
17
|
+
verificationCommands: 5,
|
|
18
|
+
safetyNotes: 5,
|
|
19
|
+
relatedTemplates: 5,
|
|
20
|
+
relatedPathConventions: 5,
|
|
21
|
+
};
|
|
5
22
|
function findPipelinesByTags(pipelines, ...tags) {
|
|
6
23
|
return pipelines.filter((p) => p.tags?.some((t) => tags.includes(t.toLowerCase())));
|
|
7
24
|
}
|
|
@@ -46,6 +63,7 @@ function pickPipelines(pipelines, task) {
|
|
|
46
63
|
*/
|
|
47
64
|
export function buildTaskPacket(inspection, task, options = {}) {
|
|
48
65
|
const maxTokens = options.maxTokens ?? 3500;
|
|
66
|
+
const compact = options.compact !== false;
|
|
49
67
|
const overview = buildProjectOverview(inspection.workspace, inspection.config?.projectName);
|
|
50
68
|
const overviewText = renderOverviewText(overview);
|
|
51
69
|
const contextResult = buildContext(inspection.knowledgeEntries, {
|
|
@@ -55,17 +73,41 @@ export function buildTaskPacket(inspection, task, options = {}) {
|
|
|
55
73
|
projectOverview: overviewText,
|
|
56
74
|
});
|
|
57
75
|
// ── Deterministic ranker — replaces the old substring search ─────────
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const
|
|
76
|
+
// Compact mode requests top-5; full mode requests top-10 (the original).
|
|
77
|
+
const rankN = compact ? 8 : 10;
|
|
78
|
+
const ranking = rankAll(inspection, task, rankN);
|
|
79
|
+
const relevantRules = compact
|
|
80
|
+
? ranking.rules.slice(0, COMPACT_CAPS.rules).map((r) => r.item)
|
|
81
|
+
: ranking.rules.map((r) => r.item);
|
|
82
|
+
const relevantPaths = compact
|
|
83
|
+
? ranking.paths.slice(0, COMPACT_CAPS.paths).map((r) => r.item)
|
|
84
|
+
: ranking.paths.map((r) => r.item);
|
|
85
|
+
const relevantTemplates = compact
|
|
86
|
+
? ranking.templates.slice(0, COMPACT_CAPS.templates).map((r) => r.item)
|
|
87
|
+
: ranking.templates.map((r) => r.item);
|
|
62
88
|
// Aggregate hints from the *ranked* knowledge so unrelated entries don't
|
|
63
89
|
// leak into the action-hints surface.
|
|
64
90
|
const hintCorpus = [
|
|
65
91
|
...ranking.rules.slice(0, 8).map((r) => r.item),
|
|
66
92
|
...inspection.knowledgeEntries.filter((e) => e.priority === 'critical' || e.priority === 'high'),
|
|
67
93
|
];
|
|
68
|
-
const
|
|
94
|
+
const actionHintsRaw = aggregateActionHints(hintCorpus);
|
|
95
|
+
// Cap each per-field aggregate when compact. Aggregator already
|
|
96
|
+
// priority-sorts entries, so the top-N kept here is the highest-signal
|
|
97
|
+
// slice of each field. `requiresHumanReview` / `writePolicy` /
|
|
98
|
+
// `preferredFlow` / `contributingEntries` are unchanged.
|
|
99
|
+
const actionHints = compact
|
|
100
|
+
? {
|
|
101
|
+
...actionHintsRaw,
|
|
102
|
+
commands: actionHintsRaw.commands.slice(0, COMPACT_CAPS.commands),
|
|
103
|
+
mcpTools: actionHintsRaw.mcpTools.slice(0, COMPACT_CAPS.mcpTools),
|
|
104
|
+
forbiddenActions: actionHintsRaw.forbiddenActions.slice(0, COMPACT_CAPS.forbiddenActions),
|
|
105
|
+
verificationCommands: actionHintsRaw.verificationCommands.slice(0, COMPACT_CAPS.verificationCommands),
|
|
106
|
+
safetyNotes: actionHintsRaw.safetyNotes.slice(0, COMPACT_CAPS.safetyNotes),
|
|
107
|
+
relatedTemplates: actionHintsRaw.relatedTemplates.slice(0, COMPACT_CAPS.relatedTemplates),
|
|
108
|
+
relatedPathConventions: actionHintsRaw.relatedPathConventions.slice(0, COMPACT_CAPS.relatedPathConventions),
|
|
109
|
+
}
|
|
110
|
+
: actionHintsRaw;
|
|
69
111
|
// Pipelines: prefer ranker output, then verb fallback for context-only.
|
|
70
112
|
const rankedPipelines = ranking.pipelines.slice(0, 3).map((p) => ({
|
|
71
113
|
pipelineId: p.item.id,
|
|
@@ -89,6 +131,17 @@ export function buildTaskPacket(inspection, task, options = {}) {
|
|
|
89
131
|
confidence: (r.score >= 15 ? 'high' : r.score >= 9 ? 'medium' : 'low'),
|
|
90
132
|
reasons: r.reasons,
|
|
91
133
|
}));
|
|
134
|
+
// Verification commands: prefer the matched pipeline's declared gates, then
|
|
135
|
+
// the config's trusted gate set, then the knowledge action-hint defaults —
|
|
136
|
+
// so the packet tells the agent to run the gates the pack actually declares
|
|
137
|
+
// (e.g. `bun test` / `bun x tsc … --noEmit`) instead of a generic fallback.
|
|
138
|
+
const resolvedVerification = resolveVerificationCommands(inspection, {
|
|
139
|
+
pipelineIds: recommendedPipelines.map((p) => p.pipelineId),
|
|
140
|
+
knowledgeDefaults: actionHints.verificationCommands,
|
|
141
|
+
});
|
|
142
|
+
const verificationCommands = compact
|
|
143
|
+
? resolvedVerification.slice(0, COMPACT_CAPS.verificationCommands)
|
|
144
|
+
: resolvedVerification;
|
|
92
145
|
const tokenEstimate = contextResult.totalTokens +
|
|
93
146
|
Math.ceil((actionHints.commands.length + actionHints.mcpTools.length + actionHints.verificationCommands.length) *
|
|
94
147
|
4);
|
|
@@ -144,7 +197,7 @@ export function buildTaskPacket(inspection, task, options = {}) {
|
|
|
144
197
|
recommendedMcpTools: actionHints.mcpTools.map((t) => t.tool),
|
|
145
198
|
recommendedCliCommands: actionHints.commands.map((c) => typeof c === 'string' ? c : c.command),
|
|
146
199
|
forbiddenActions: actionHints.forbiddenActions,
|
|
147
|
-
verificationCommands
|
|
200
|
+
verificationCommands,
|
|
148
201
|
humanReviewPoints,
|
|
149
202
|
tokenEstimate,
|
|
150
203
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-ranker.d.ts","sourceRoot":"","sources":["../src/task-ranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;;;;;;GAQG;AAEH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"task-ranker.d.ts","sourceRoot":"","sources":["../src/task-ranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAElE;;;;;;;;GAQG;AAEH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAmOD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,IAAI,EAAE,MAAM,GACX,WAAW,CAAC,eAAe,CAAC,EAAE,CAqBhC;AAGD,wBAAgB,aAAa,CAC3B,SAAS,EAAE,SAAS,mBAAmB,EAAE,EACzC,IAAI,EAAE,MAAM,GACX,WAAW,CAAC,mBAAmB,CAAC,EAAE,CAiBpC;AAGD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,eAAe,EAAE,EACjC,IAAI,EAAE,MAAM,GACX,WAAW,CAAC,eAAe,CAAC,EAAE,CAEhC;AAGD,wBAAgB,aAAa,CAC3B,SAAS,EAAE,SAAS,mBAAmB,EAAE,EACzC,IAAI,EAAE,MAAM,GACX,WAAW,CAAC,mBAAmB,CAAC,EAAE,CAkCpC;AAGD,wBAAgB,WAAW,CACzB,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAClC,WAAW,CAAC,OAAO,CAAC,EAAE,CAgCxB;AAGD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC;IACtC,KAAK,EAAE,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC;IACtC,SAAS,EAAE,WAAW,CAAC,mBAAmB,CAAC,EAAE,CAAC;IAC9C,SAAS,EAAE,WAAW,CAAC,mBAAmB,CAAC,EAAE,CAAC;IAC9C,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;CACjC;AAED,wBAAgB,OAAO,CACrB,UAAU,EAAE;IACV,gBAAgB,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC1C,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC1C,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,SAAS,OAAO,EAAE,CAAA;KAAE,CAAC;IACnD,SAAS,EAAE;QAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC;IAC3C,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,SAAS,eAAe,EAAE,CAAA;KAAE,CAAC;IACxD,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,SAAS,eAAe,EAAE,CAAA;KAAE,CAAC;CACzD,EACD,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,MAAW,GACjB,cAAc,CAiEhB;AAGD,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,EAChC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAC7B,KAAK,GAAE,MAAU,GAChB,MAAM,CAKR;AAED,uFAAuF;AACvF,YAAY,EAAE,eAAe,EAAE,CAAC"}
|
package/dist/task-ranker.js
CHANGED
|
@@ -29,33 +29,8 @@ const VERB_HINTS = [
|
|
|
29
29
|
// ── Domain hints (what *kind of thing* is being worked on) ──────────────
|
|
30
30
|
// These boost rules/templates/pipelines whose own `appliesWhen` or `tags`
|
|
31
31
|
// declare the same domain — much higher signal than verb hints alone for
|
|
32
|
-
// "create a
|
|
32
|
+
// "create a *service*" vs "add a *utility*".
|
|
33
33
|
const DOMAIN_HINTS = [
|
|
34
|
-
{
|
|
35
|
-
token: 'plugin',
|
|
36
|
-
appliesWhen: ['create-plugin', 'generate-plugin', 'plugin-dev', 'register-plugin'],
|
|
37
|
-
tags: ['plugin'],
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
token: 'defaults',
|
|
41
|
-
appliesWhen: ['register-defaults', 'create-defaults', 'plugin-defaults'],
|
|
42
|
-
tags: ['defaults'],
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
token: 'capability',
|
|
46
|
-
appliesWhen: ['create-capability', 'generate-capability'],
|
|
47
|
-
tags: ['capability'],
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
token: 'policy',
|
|
51
|
-
appliesWhen: ['create-policy', 'generate-policy'],
|
|
52
|
-
tags: ['policy'],
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
token: 'adapter',
|
|
56
|
-
appliesWhen: ['create-adapter', 'generate-adapter'],
|
|
57
|
-
tags: ['adapter'],
|
|
58
|
-
},
|
|
59
34
|
{
|
|
60
35
|
token: 'service',
|
|
61
36
|
appliesWhen: ['generate-service'],
|
|
@@ -81,11 +56,6 @@ const DOMAIN_HINTS = [
|
|
|
81
56
|
appliesWhen: ['generate-route'],
|
|
82
57
|
tags: ['http', 'routes', 'api'],
|
|
83
58
|
},
|
|
84
|
-
{
|
|
85
|
-
token: 'kernel',
|
|
86
|
-
appliesWhen: ['create-kernel-service'],
|
|
87
|
-
tags: ['kernel'],
|
|
88
|
-
},
|
|
89
59
|
];
|
|
90
60
|
function tokenize(s) {
|
|
91
61
|
return s
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-routing-hint-registry.d.ts","sourceRoot":"","sources":["../src/task-routing-hint-registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"task-routing-hint-registry.d.ts","sourceRoot":"","sources":["../src/task-routing-hint-registry.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAGvE,eAAO,MAAM,iCAAiC,6CAA6C,CAAC;AAE5F,oBAAY,qBAAqB;IAC/B,KAAK,UAAU;IACf,IAAI,SAAS;IACb,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AA4BD,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC;IAAE,OAAO,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAAC,MAAM,EAAE,SAAS,2BAA2B,EAAE,CAAA;CAAE,CAAC,CAoFxG;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC,SAAS,qBAAqB,EAAE,CAAC,CAG3C;AAED,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC,SAAS,2BAA2B,EAAE,CAAC,CAGjD;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,qBAAqB,EACjC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,uBAAuB,EAAE,CAAC,CA0C7C"}
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
-
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
1
|
/**
|
|
10
2
|
* Task routing hint registry. Pack- and local-contributed task
|
|
11
3
|
* routing hints bias the recommender output toward project-specific
|
|
@@ -15,8 +7,8 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
15
7
|
*/
|
|
16
8
|
import { existsSync } from 'node:fs';
|
|
17
9
|
import * as nodePath from 'node:path';
|
|
18
|
-
import { pathToFileURL } from 'node:url';
|
|
19
10
|
import { validateTaskRoutingHint, } from '@shrkcrft/plugin-api';
|
|
11
|
+
import { importModuleViaLoader } from '@shrkcrft/core';
|
|
20
12
|
export const TASK_ROUTING_HINT_REGISTRY_SCHEMA = 'sharkcraft.task-routing-hint-registry/v1';
|
|
21
13
|
export var TaskRoutingHintSource;
|
|
22
14
|
(function (TaskRoutingHintSource) {
|
|
@@ -25,7 +17,7 @@ export var TaskRoutingHintSource;
|
|
|
25
17
|
TaskRoutingHintSource["Fixture"] = "fixture";
|
|
26
18
|
})(TaskRoutingHintSource || (TaskRoutingHintSource = {}));
|
|
27
19
|
async function importDefault(file) {
|
|
28
|
-
const mod = (await
|
|
20
|
+
const mod = (await importModuleViaLoader(file));
|
|
29
21
|
if (Array.isArray(mod.default))
|
|
30
22
|
return mod.default;
|
|
31
23
|
if (mod.default && typeof mod.default === 'object')
|
package/dist/template-drift.d.ts
CHANGED
|
@@ -35,5 +35,12 @@ export interface ITemplateDriftCheckOptions {
|
|
|
35
35
|
/** Sample variable values for templates with required vars (key→string). */
|
|
36
36
|
sampleVars?: Readonly<Record<string, string>>;
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* A rendered sample path "matches" a path convention when it IS the
|
|
40
|
+
* convention's canonical target, or lives directly under it. The trailing
|
|
41
|
+
* slash guard stops `libs/nge/core` from spuriously matching
|
|
42
|
+
* `libs/nge/core-extra`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function samplePathMatchesConvention(samplePath: string, conventionPath: string): boolean;
|
|
38
45
|
export declare function buildTemplateDriftReport(inspection: ISharkcraftInspection, options?: ITemplateDriftCheckOptions): ITemplateDriftReport;
|
|
39
46
|
//# sourceMappingURL=template-drift.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-drift.d.ts","sourceRoot":"","sources":["../src/template-drift.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,qBAAqB,iCAAiC,CAAC;AAEpE,oBAAY,mBAAmB;IAC7B,IAAI,SAAS;IACb,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,MAAM,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,qBAAqB,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,0BAA0B;IACzC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC/C;
|
|
1
|
+
{"version":3,"file":"template-drift.d.ts","sourceRoot":"","sources":["../src/template-drift.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,qBAAqB,iCAAiC,CAAC;AAEpE,oBAAY,mBAAmB;IAC7B,IAAI,SAAS;IACb,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,MAAM,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,qBAAqB,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,0BAA0B;IACzC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC/C;AAoFD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,OAAO,CAET;AAoND,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,qBAAqB,EACjC,OAAO,GAAE,0BAA+B,GACvC,oBAAoB,CA8DtB"}
|
package/dist/template-drift.js
CHANGED
|
@@ -99,6 +99,15 @@ function safeRender(template, values) {
|
|
|
99
99
|
}
|
|
100
100
|
return { paths, warnings, ops };
|
|
101
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* A rendered sample path "matches" a path convention when it IS the
|
|
104
|
+
* convention's canonical target, or lives directly under it. The trailing
|
|
105
|
+
* slash guard stops `libs/nge/core` from spuriously matching
|
|
106
|
+
* `libs/nge/core-extra`.
|
|
107
|
+
*/
|
|
108
|
+
export function samplePathMatchesConvention(samplePath, conventionPath) {
|
|
109
|
+
return samplePath === conventionPath || samplePath.startsWith(`${conventionPath}/`);
|
|
110
|
+
}
|
|
102
111
|
function checkPathConventions(inspection, paths) {
|
|
103
112
|
const issues = [];
|
|
104
113
|
// Path conventions are name patterns; we only flag a path that obviously
|
|
@@ -111,12 +120,11 @@ function checkPathConventions(inspection, paths) {
|
|
|
111
120
|
for (const p of paths) {
|
|
112
121
|
let matched = false;
|
|
113
122
|
for (const c of conventions) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (cleaned.length > 4 && p.includes(cleaned)) {
|
|
123
|
+
// Path conventions carry their canonical path in `metadata.path`
|
|
124
|
+
// (IPathConvention), NOT a `pattern` field. A sample path matches a
|
|
125
|
+
// convention when it IS that target or lives under it.
|
|
126
|
+
const target = c.metadata?.path;
|
|
127
|
+
if (target && samplePathMatchesConvention(p, target)) {
|
|
120
128
|
matched = true;
|
|
121
129
|
break;
|
|
122
130
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-impact.d.ts","sourceRoot":"","sources":["../src/test-impact.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,kBAAkB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,qEAAqE;IACrE,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,oCAAoC;IACpC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,0DAA0D;IAC1D,eAAe,EAAE,SAAS;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACjF,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"test-impact.d.ts","sourceRoot":"","sources":["../src/test-impact.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,kBAAkB,8BAA8B,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,kBAAkB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,qEAAqE;IACrE,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,oCAAoC;IACpC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,0DAA0D;IAC1D,eAAe,EAAE,SAAS;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACjF,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAoCD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,qBAAqB,EACjC,KAAK,EAAE,gBAAgB,GACtB,WAAW,CAyEb;AAoDD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOvD"}
|
package/dist/test-impact.js
CHANGED
|
@@ -7,8 +7,11 @@ const TEST_PATTERNS = [
|
|
|
7
7
|
(f) => f.replace(/^src\//, 'tests/').replace(/\.(ts|tsx|js|jsx)$/, '.test.$1'),
|
|
8
8
|
(f) => f.replace(/\.([tj]s)$/, '.spec.$1'),
|
|
9
9
|
(f) => f.replace(/\.([tj]s)$/, '.test.$1'),
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// Guard on `.tsx`: a bare `.replace(/\.tsx$/, …)` is a no-op on a `.ts`
|
|
11
|
+
// file, so it would echo the input source file back as its own "test"
|
|
12
|
+
// (existing on disk → falsely confidence 100%, runs zero tests).
|
|
13
|
+
(f) => (/\.tsx$/.test(f) ? f.replace(/\.tsx$/, '.test.tsx') : null),
|
|
14
|
+
(f) => (/\.tsx$/.test(f) ? f.replace(/\.tsx$/, '.spec.tsx') : null),
|
|
12
15
|
(f) => {
|
|
13
16
|
const parsed = nodePath.parse(f);
|
|
14
17
|
if (!parsed.name)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"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"}
|
package/dist/test-runner.js
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
|
-
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
-
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
1
|
import { existsSync } from 'node:fs';
|
|
10
2
|
import * as nodePath from 'node:path';
|
|
11
|
-
import { pathToFileURL } from 'node:url';
|
|
12
3
|
import { buildContext } from '@shrkcrft/context';
|
|
13
4
|
import { buildTaskPacket } from "./task-packet.js";
|
|
14
5
|
import { rankKnowledgeEntries } from "./task-ranker.js";
|
|
15
6
|
import { buildProjectOverview, renderOverviewText } from "./project-overview.js";
|
|
16
7
|
import { HELPERS } from "./helper-registry.js";
|
|
8
|
+
import { importModuleViaLoader } from '@shrkcrft/core';
|
|
17
9
|
async function importDefaultArray(absPath) {
|
|
18
10
|
if (!existsSync(absPath))
|
|
19
11
|
return [];
|
|
20
12
|
try {
|
|
21
|
-
const mod = (await
|
|
13
|
+
const mod = (await importModuleViaLoader(absPath));
|
|
22
14
|
return Array.isArray(mod.default) ? mod.default : [];
|
|
23
15
|
}
|
|
24
16
|
catch {
|
|
@@ -152,14 +144,17 @@ function buildMissingIncludeSuggestions(id, existsInRegistry, task) {
|
|
|
152
144
|
}
|
|
153
145
|
return [
|
|
154
146
|
`Entry "${id}" exists but did not make the context for task "${task}".`,
|
|
155
|
-
`Try adding domain-aligned appliesWhen values (
|
|
156
|
-
`Add task-relevant tags (
|
|
147
|
+
`Try adding domain-aligned appliesWhen values (generate-service / generate-utility / create-pipeline / …).`,
|
|
148
|
+
`Add task-relevant tags (service / utility / route / …).`,
|
|
157
149
|
`Reference the entry from a preset's includes.knowledgeIds / ruleIds so it ranks higher.`,
|
|
158
150
|
`Or raise its priority / shorten the title to include task-relevant tokens.`,
|
|
159
151
|
];
|
|
160
152
|
}
|
|
161
153
|
export function runAgentContractTest(inspection, test, registries) {
|
|
162
|
-
|
|
154
|
+
// Self-tests assert specific rules/templates appear for a task — they
|
|
155
|
+
// test semantics, not packet size. Opt out of the compact cap so the
|
|
156
|
+
// assertions see the full ranking.
|
|
157
|
+
const packet = buildTaskPacket(inspection, test.task, { maxTokens: 3500, compact: false });
|
|
163
158
|
const actualPipelines = packet.recommendedPipelines.map((p) => p.pipelineId);
|
|
164
159
|
const missingTemplates = (test.expectedTemplates ?? []).filter((id) => !packet.relevantTemplates.some((t) => t.id === id));
|
|
165
160
|
const missingRules = (test.expectedRules ?? []).filter((id) => !packet.relevantRules.some((r) => r.id === id));
|
|
@@ -227,7 +222,7 @@ export function runAgentContractTest(inspection, test, registries) {
|
|
|
227
222
|
suggestions: exists
|
|
228
223
|
? [
|
|
229
224
|
`Template "${id}" exists but the ranker did not place it in the top results.`,
|
|
230
|
-
'Add task-aligned tags/appliesWhen to the template (e.g. tags:["
|
|
225
|
+
'Add task-aligned tags/appliesWhen to the template (e.g. tags:["service"], appliesWhen:["generate-service"]).',
|
|
231
226
|
'Reference the template from a preset that matches the task profile (includes.templateIds).',
|
|
232
227
|
'Reference it from a pipeline step (`step.references`).',
|
|
233
228
|
]
|
|
@@ -245,8 +240,8 @@ export function runAgentContractTest(inspection, test, registries) {
|
|
|
245
240
|
suggestions: exists
|
|
246
241
|
? [
|
|
247
242
|
`Rule "${id}" exists but the ranker did not surface it for "${test.task}".`,
|
|
248
|
-
'Align its appliesWhen with the domain (e.g.
|
|
249
|
-
'Add domain tags (
|
|
243
|
+
'Align its appliesWhen with the domain (e.g. generate-service / generate-utility / create-pipeline).',
|
|
244
|
+
'Add domain tags (service / utility / route / pipeline).',
|
|
250
245
|
'Reference it from actionHints.relatedTemplates on a rule that *is* ranking, or include it in a preset.',
|
|
251
246
|
]
|
|
252
247
|
: [
|
|
@@ -477,7 +472,7 @@ async function importDefaultIdsArray(absPath) {
|
|
|
477
472
|
if (!existsSync(absPath))
|
|
478
473
|
return [];
|
|
479
474
|
try {
|
|
480
|
-
const mod = (await
|
|
475
|
+
const mod = (await importModuleViaLoader(absPath));
|
|
481
476
|
return Array.isArray(mod.default) ? mod.default : [];
|
|
482
477
|
}
|
|
483
478
|
catch {
|
|
@@ -17,7 +17,6 @@ export declare enum SearchResultKind {
|
|
|
17
17
|
ScaffoldPattern = "scaffold-pattern",
|
|
18
18
|
ContractTemplate = "contract-template",
|
|
19
19
|
MigrationProfile = "migration-profile",
|
|
20
|
-
PluginLifecycleProfile = "plugin-lifecycle-profile",
|
|
21
20
|
FeedbackRule = "feedback-rule",
|
|
22
21
|
TaskRoutingHint = "task-routing-hint",
|
|
23
22
|
Docs = "docs",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"universal-search.d.ts","sourceRoot":"","sources":["../src/universal-search.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"universal-search.d.ts","sourceRoot":"","sources":["../src/universal-search.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAgC,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGhG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,uBAAuB,mCAAmC,CAAC;AAExE,oBAAY,gBAAgB;IAC1B,OAAO,YAAY;IACnB,OAAO,aAAa;IACpB,SAAS,cAAc;IACvB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,UAAU,eAAe;IACzB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,eAAe,qBAAqB;IACpC,gBAAgB,sBAAsB;IACtC,gBAAgB,sBAAsB;IACtC,YAAY,kBAAkB;IAC9B,eAAe,sBAAsB;IACrC,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,WAAW,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACrD,QAAQ,CAAC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAClD,QAAQ,CAAC,aAAa,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACvD,QAAQ,CAAC,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACnD,QAAQ,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,OAAO,uBAAuB,CAAC;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,CAAC;IAC5C,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;IACzC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAC3D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AA+CD,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,qBAAqB,EACjC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CA4NjC;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAmDhF;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CA8BpF"}
|
package/dist/universal-search.js
CHANGED
|
@@ -17,7 +17,6 @@ import { buildPackContributionsInventory } from "./pack-contributions-inventory.
|
|
|
17
17
|
import { listConventions } from "./convention-registry.js";
|
|
18
18
|
import { listPackHelpers } from "./pack-helper-registry.js";
|
|
19
19
|
import { explainTaskRouting } from "./task-routing-hint-registry.js";
|
|
20
|
-
import { listPluginLifecycleProfiles } from "./plugin-lifecycle-profile-registry.js";
|
|
21
20
|
import { uncertaintyReportFromSummary } from "./uncertainty-report.js";
|
|
22
21
|
import { buildUncertaintySummary } from "./uncertainty.js";
|
|
23
22
|
import { buildTaskPacket } from "./task-packet.js";
|
|
@@ -39,7 +38,6 @@ export var SearchResultKind;
|
|
|
39
38
|
SearchResultKind["ScaffoldPattern"] = "scaffold-pattern";
|
|
40
39
|
SearchResultKind["ContractTemplate"] = "contract-template";
|
|
41
40
|
SearchResultKind["MigrationProfile"] = "migration-profile";
|
|
42
|
-
SearchResultKind["PluginLifecycleProfile"] = "plugin-lifecycle-profile";
|
|
43
41
|
SearchResultKind["FeedbackRule"] = "feedback-rule";
|
|
44
42
|
SearchResultKind["TaskRoutingHint"] = "task-routing-hint";
|
|
45
43
|
SearchResultKind["Docs"] = "docs";
|
|
@@ -89,7 +87,6 @@ export async function buildUniversalSearch(inspection, query, options = {}) {
|
|
|
89
87
|
const conventions = await listConventions(inspection);
|
|
90
88
|
const helpers = await listPackHelpers(inspection);
|
|
91
89
|
const routing = await explainTaskRouting(inspection, q);
|
|
92
|
-
const lifecycle = await listPluginLifecycleProfiles(inspection);
|
|
93
90
|
const knowledgeEntries = inspection.knowledgeEntries;
|
|
94
91
|
const allHits = [];
|
|
95
92
|
// Knowledge
|
|
@@ -113,13 +110,6 @@ export async function buildUniversalSearch(inspection, query, options = {}) {
|
|
|
113
110
|
allHits.push(makeHit(SearchResultKind.Helper, h.helper.id, h.helper.title, h.source === 'pack' ? 'pack' : 'local', h.packageName, s, `shrk helper plan ${h.helper.id}`));
|
|
114
111
|
}
|
|
115
112
|
}
|
|
116
|
-
// Plugin lifecycle profiles
|
|
117
|
-
for (const p of lifecycle) {
|
|
118
|
-
const s = score(`${p.profile.id} ${p.profile.title} ${(p.profile.tags ?? []).join(' ')}`, q);
|
|
119
|
-
if (s.score > 0) {
|
|
120
|
-
allHits.push(makeHit(SearchResultKind.PluginLifecycleProfile, p.profile.id, p.profile.title, p.source === 'pack' ? 'pack' : 'local', p.packageName, s, `shrk plugin lifecycle profile ${p.profile.id}`));
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
113
|
// Pack contributions (catch-all for kinds we didn't iterate above)
|
|
124
114
|
for (const e of inv.entries) {
|
|
125
115
|
if (allHits.find((h) => h.id === e.id && String(h.kind) === e.kind))
|
|
@@ -140,7 +130,6 @@ export async function buildUniversalSearch(inspection, query, options = {}) {
|
|
|
140
130
|
decision: SearchResultKind.Decision,
|
|
141
131
|
'contract-template': SearchResultKind.ContractTemplate,
|
|
142
132
|
'migration-profile': SearchResultKind.MigrationProfile,
|
|
143
|
-
'plugin-lifecycle-profile': SearchResultKind.PluginLifecycleProfile,
|
|
144
133
|
'feedback-rule': SearchResultKind.FeedbackRule,
|
|
145
134
|
'task-routing-hint': SearchResultKind.TaskRoutingHint,
|
|
146
135
|
helper: SearchResultKind.Helper,
|
|
@@ -184,7 +173,6 @@ export async function buildUniversalSearch(inspection, query, options = {}) {
|
|
|
184
173
|
SearchResultKind.Policy,
|
|
185
174
|
SearchResultKind.ContractTemplate,
|
|
186
175
|
SearchResultKind.MigrationProfile,
|
|
187
|
-
SearchResultKind.PluginLifecycleProfile,
|
|
188
176
|
SearchResultKind.ScaffoldPattern,
|
|
189
177
|
SearchResultKind.FeedbackRule,
|
|
190
178
|
SearchResultKind.TaskRoutingHint,
|
package/dist/why-file.js
CHANGED
|
@@ -23,7 +23,7 @@ export function buildWhyReport(input) {
|
|
|
23
23
|
const inferredPackage = inferPackage(target.relativePath);
|
|
24
24
|
const inferredLayer = inferLayer(target.relativePath);
|
|
25
25
|
const pathConventions = matchPathConventions(input.inspection, target);
|
|
26
|
-
const rules = matchRules(input.inspection, target, limit);
|
|
26
|
+
const rules = matchRules(input.inspection, target, limit, inferredPackage, inferredLayer);
|
|
27
27
|
const boundaries = matchBoundaries(input.inspection, target);
|
|
28
28
|
const knowledge = matchKnowledge(input.inspection, target, limit);
|
|
29
29
|
const suggestedNext = buildSuggestions(target, rules, knowledge);
|
|
@@ -78,14 +78,20 @@ function inferLayer(relPath) {
|
|
|
78
78
|
return segments[1];
|
|
79
79
|
return undefined;
|
|
80
80
|
}
|
|
81
|
+
/** Does `targetRel` equal, or live under, the canonical directory/file path? */
|
|
82
|
+
function pathCovers(targetRel, canonical) {
|
|
83
|
+
const normalized = canonical.replace(/^\.\//, '').replace(/\/+$/, '');
|
|
84
|
+
if (!normalized)
|
|
85
|
+
return false;
|
|
86
|
+
return targetRel === normalized || targetRel.startsWith(`${normalized}/`);
|
|
87
|
+
}
|
|
81
88
|
function matchPathConventions(inspection, target) {
|
|
82
89
|
const out = [];
|
|
83
90
|
for (const p of inspection.pathService.list()) {
|
|
84
91
|
const canonical = p.metadata?.path ?? '';
|
|
85
92
|
if (!canonical)
|
|
86
93
|
continue;
|
|
87
|
-
|
|
88
|
-
if (target.relativePath === normalized || target.relativePath.startsWith(normalized.endsWith('/') ? normalized : `${normalized}/`)) {
|
|
94
|
+
if (pathCovers(target.relativePath, canonical)) {
|
|
89
95
|
out.push({
|
|
90
96
|
id: p.id,
|
|
91
97
|
title: p.title,
|
|
@@ -96,30 +102,74 @@ function matchPathConventions(inspection, target) {
|
|
|
96
102
|
}
|
|
97
103
|
return out;
|
|
98
104
|
}
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Precise PATH evidence that a rule applies to a file — not topical token
|
|
107
|
+
* overlap (scope/tags/appliesWhen are free-form labels, so the old
|
|
108
|
+
* intersection attached nearly every rule to every file). Priority order:
|
|
109
|
+
* explicit file/dir references → path-glob scope/tag → package reference →
|
|
110
|
+
* scope/tag equal to the inferred package or layer.
|
|
111
|
+
*/
|
|
112
|
+
function ruleReasonForFile(r, target, inferredPackage, inferredLayer) {
|
|
113
|
+
const rel = target.relativePath;
|
|
114
|
+
// 1. Explicit file/directory references that cover the target.
|
|
115
|
+
for (const ref of r.references ?? []) {
|
|
116
|
+
const p = (ref.path ?? '').replace(/^\.\//, '');
|
|
117
|
+
if ((ref.kind === 'file' || ref.kind === 'directory') && p && pathCovers(rel, p)) {
|
|
118
|
+
return ref.kind === 'directory' ? `directory reference ${p}` : `file reference ${p}`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// 1b. Anchors that point at a covering path.
|
|
122
|
+
for (const a of r.anchors ?? []) {
|
|
123
|
+
const p = (a.path ?? '').replace(/^\.\//, '');
|
|
124
|
+
if (p && pathCovers(rel, p))
|
|
125
|
+
return `anchor path ${p}`;
|
|
126
|
+
}
|
|
127
|
+
// 2. Scope/tag values that are themselves path globs matching the target.
|
|
128
|
+
const pathish = [...(r.scope ?? []), ...(r.tags ?? [])].filter((s) => /[/*?[]/.test(s));
|
|
129
|
+
if (pathish.length > 0) {
|
|
130
|
+
const hit = pathish.find((g) => matchesAny(rel, [g]));
|
|
131
|
+
if (hit)
|
|
132
|
+
return `path pattern ${hit}`;
|
|
133
|
+
}
|
|
134
|
+
// 3. Package reference / scope-or-tag equal to the inferred package or layer.
|
|
135
|
+
const labels = [...(r.scope ?? []), ...(r.tags ?? [])];
|
|
136
|
+
if (inferredPackage) {
|
|
137
|
+
for (const ref of r.references ?? []) {
|
|
138
|
+
if (ref.kind === 'package' && ref.id && samePath(ref.id, inferredPackage)) {
|
|
139
|
+
return `package reference ${ref.id}`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (labels.some((l) => samePath(l, inferredPackage)))
|
|
143
|
+
return `scoped to package ${inferredPackage}`;
|
|
144
|
+
}
|
|
145
|
+
if (inferredLayer && labels.some((l) => l.toLowerCase() === inferredLayer.toLowerCase())) {
|
|
146
|
+
return `scoped to layer ${inferredLayer}`;
|
|
147
|
+
}
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
function samePath(a, b) {
|
|
151
|
+
const n = (s) => s.replace(/^\.?\/+/, '').replace(/\/+$/, '').toLowerCase();
|
|
152
|
+
return n(a) === n(b);
|
|
153
|
+
}
|
|
154
|
+
function matchRules(inspection, target, limit, inferredPackage, inferredLayer) {
|
|
101
155
|
const out = [];
|
|
102
156
|
for (const rule of inspection.ruleService.list()) {
|
|
103
157
|
const r = rule;
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
const appliesWhen = r.appliesWhen ?? [];
|
|
107
|
-
const allTokens = new Set([...scope, ...tags, ...appliesWhen].map((t) => t.toLowerCase()));
|
|
108
|
-
const hits = tokens.filter((t) => allTokens.has(t.toLowerCase()));
|
|
109
|
-
if (hits.length === 0)
|
|
158
|
+
const reason = ruleReasonForFile(r, target, inferredPackage, inferredLayer);
|
|
159
|
+
if (!reason)
|
|
110
160
|
continue;
|
|
111
161
|
out.push({
|
|
112
162
|
id: r.id,
|
|
113
163
|
title: r.title,
|
|
114
164
|
priority: r.priority ?? 'medium',
|
|
115
|
-
scope,
|
|
116
|
-
tags,
|
|
117
|
-
appliesWhen,
|
|
118
|
-
reason
|
|
165
|
+
scope: r.scope ?? [],
|
|
166
|
+
tags: r.tags ?? [],
|
|
167
|
+
appliesWhen: r.appliesWhen ?? [],
|
|
168
|
+
reason,
|
|
119
169
|
...sourceField(inspection, r.id),
|
|
120
170
|
});
|
|
121
171
|
}
|
|
122
|
-
// Sort by priority weight desc
|
|
172
|
+
// Sort by priority weight desc (stable for equal weights).
|
|
123
173
|
const weight = { critical: 4, high: 3, medium: 2, low: 1 };
|
|
124
174
|
out.sort((a, b) => (weight[b.priority] ?? 2) - (weight[a.priority] ?? 2));
|
|
125
175
|
return out.slice(0, limit);
|
|
@@ -183,12 +233,6 @@ function buildSuggestions(target, rules, knowledge) {
|
|
|
183
233
|
out.push(`shrk impact "${target.relativePath}"`);
|
|
184
234
|
return out;
|
|
185
235
|
}
|
|
186
|
-
function pathTokens(relPath) {
|
|
187
|
-
return relPath
|
|
188
|
-
.replace(/\.[^./]+$/, '') // drop extension
|
|
189
|
-
.split(/[/\\.\-_]/)
|
|
190
|
-
.filter((t) => t.length > 0);
|
|
191
|
-
}
|
|
192
236
|
function sourceField(inspection, id) {
|
|
193
237
|
let map;
|
|
194
238
|
if (inspection && 'entrySources' in inspection) {
|