@mrciphersmith/keryx 0.3.3 → 0.3.5
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/cli.js +125 -51
- package/package.json +1 -1
- package/src/gdskills/bundled/install-manifest.json +231 -2
- package/src/gdskills/bundled/stacks/csharp-dotnet/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/governance/eval.json +1881 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/governance/scout.json +33 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/pack.json +38 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/rules/coding-style.mdc +100 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/rules/patterns.mdc +107 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/rules/security.mdc +86 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/rules/testing.mdc +89 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/SKILL.md +143 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/evals.json +77 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/SKILL.md +121 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/evals.json +77 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/SKILL.md +134 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/evals.json +76 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/SKILL.md +130 -0
- package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/evals.json +77 -0
- package/src/gdskills/bundled/stacks/flutter-dart/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/flutter-dart/governance/eval.json +1849 -0
- package/src/gdskills/bundled/stacks/flutter-dart/governance/scout.json +33 -0
- package/src/gdskills/bundled/stacks/flutter-dart/pack.json +41 -0
- package/src/gdskills/bundled/stacks/flutter-dart/rules/coding-style.mdc +98 -0
- package/src/gdskills/bundled/stacks/flutter-dart/rules/patterns.mdc +88 -0
- package/src/gdskills/bundled/stacks/flutter-dart/rules/security.mdc +91 -0
- package/src/gdskills/bundled/stacks/flutter-dart/rules/testing.mdc +101 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/SKILL.md +134 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/evals.json +79 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/SKILL.md +124 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/evals.json +74 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/SKILL.md +139 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/evals.json +77 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/SKILL.md +134 -0
- package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/evals.json +74 -0
- package/src/gdskills/bundled/stacks/kotlin-android/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/kotlin-android/governance/eval.json +1889 -0
- package/src/gdskills/bundled/stacks/kotlin-android/governance/scout.json +34 -0
- package/src/gdskills/bundled/stacks/kotlin-android/pack.json +38 -0
- package/src/gdskills/bundled/stacks/kotlin-android/rules/coding-style.mdc +89 -0
- package/src/gdskills/bundled/stacks/kotlin-android/rules/patterns.mdc +96 -0
- package/src/gdskills/bundled/stacks/kotlin-android/rules/security.mdc +90 -0
- package/src/gdskills/bundled/stacks/kotlin-android/rules/testing.mdc +89 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/SKILL.md +150 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/evals.json +77 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/SKILL.md +151 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/evals.json +76 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/SKILL.md +139 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/evals.json +78 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/SKILL.md +131 -0
- package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/evals.json +77 -0
- package/src/gdskills/bundled/stacks/swift-ios/agent-refs.json +4 -0
- package/src/gdskills/bundled/stacks/swift-ios/governance/eval.json +1803 -0
- package/src/gdskills/bundled/stacks/swift-ios/governance/scout.json +32 -0
- package/src/gdskills/bundled/stacks/swift-ios/pack.json +38 -0
- package/src/gdskills/bundled/stacks/swift-ios/rules/coding-style.mdc +92 -0
- package/src/gdskills/bundled/stacks/swift-ios/rules/patterns.mdc +112 -0
- package/src/gdskills/bundled/stacks/swift-ios/rules/security.mdc +78 -0
- package/src/gdskills/bundled/stacks/swift-ios/rules/testing.mdc +90 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/SKILL.md +144 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/evals.json +75 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/SKILL.md +122 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/evals.json +75 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/SKILL.md +131 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/evals.json +75 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/SKILL.md +149 -0
- package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/evals.json +76 -0
package/dist/cli.js
CHANGED
|
@@ -17259,7 +17259,7 @@ var package_default;
|
|
|
17259
17259
|
var init_package = __esm(() => {
|
|
17260
17260
|
package_default = {
|
|
17261
17261
|
name: "@mrciphersmith/keryx",
|
|
17262
|
-
version: "0.3.
|
|
17262
|
+
version: "0.3.5",
|
|
17263
17263
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
17264
17264
|
private: false,
|
|
17265
17265
|
publishConfig: {
|
|
@@ -96156,6 +96156,28 @@ function clauseFileKindApplicability(sourceCategory, clauseText, changedFileKind
|
|
|
96156
96156
|
}
|
|
96157
96157
|
return { applicable: true, reason: "hunk is a code file; rule source is not categorised docs" };
|
|
96158
96158
|
}
|
|
96159
|
+
var API_SCOPE_TERMS = ["api", "endpoint", "rest", "http", "openapi"];
|
|
96160
|
+
function isApiScopedRuleSource(source) {
|
|
96161
|
+
const haystack = `${(source.declaredPaths ?? []).join(" ")} ${ruleSourceTitle(source.text)} ${source.path}`.toLowerCase();
|
|
96162
|
+
return API_SCOPE_TERMS.some((term) => new RegExp(`\\b${term}\\b`).test(haystack));
|
|
96163
|
+
}
|
|
96164
|
+
var API_SURFACE_DIR_RE = /(^|\/)(api|routes|controllers|handlers|server)\//i;
|
|
96165
|
+
var HTTP_FRAMEWORK_IMPORT_RE = /\bfrom\s*["'](?:express|fastify|koa|hono|@hono\/[\w-]+|hapi|@nestjs\/(?:common|core)|next\/server|h3)["']/;
|
|
96166
|
+
function looksLikeApiSurfaceHunk(region) {
|
|
96167
|
+
return API_SURFACE_DIR_RE.test(region.path) || HTTP_FRAMEWORK_IMPORT_RE.test(region.text);
|
|
96168
|
+
}
|
|
96169
|
+
function clauseApiScopeApplicability(source, region) {
|
|
96170
|
+
if (!isApiScopedRuleSource(source)) {
|
|
96171
|
+
return { applicable: true, reason: "rule source is not API/endpoint-scoped \u2014 this gate does not apply" };
|
|
96172
|
+
}
|
|
96173
|
+
if (looksLikeApiSurfaceHunk(region)) {
|
|
96174
|
+
return { applicable: true, reason: `rule source is API/endpoint-scoped and ${region.path} looks like an API surface` };
|
|
96175
|
+
}
|
|
96176
|
+
return {
|
|
96177
|
+
applicable: false,
|
|
96178
|
+
reason: `rule source is API/endpoint-scoped (its declared paths/description/title name one of: ${API_SCOPE_TERMS.join(", ")}) but ${region.path} ` + "does not look like an API surface (no api/routes/controllers/handlers/server path segment, and this hunk imports no known HTTP framework)"
|
|
96179
|
+
};
|
|
96180
|
+
}
|
|
96159
96181
|
var DEFAULT_MAX_JEV_RULE_CALLS = 150;
|
|
96160
96182
|
function isHunkCheckableClause(clause) {
|
|
96161
96183
|
return clause.state_kind === "hunk" && clause.checkable;
|
|
@@ -96199,6 +96221,11 @@ function selectRuleHunkPairs(regions, taggedSources, detectedStack, maxCalls = D
|
|
|
96199
96221
|
notApplicable.push({ region, ruleId: source.path, reason: decision.reason });
|
|
96200
96222
|
continue;
|
|
96201
96223
|
}
|
|
96224
|
+
const apiScopeDecision = clauseApiScopeApplicability(source, region);
|
|
96225
|
+
if (!apiScopeDecision.applicable) {
|
|
96226
|
+
notApplicable.push({ region, ruleId: source.path, reason: apiScopeDecision.reason });
|
|
96227
|
+
continue;
|
|
96228
|
+
}
|
|
96202
96229
|
let sawHunkCheckable = false;
|
|
96203
96230
|
let anyFileKindApplicable = false;
|
|
96204
96231
|
for (const clause of clauses) {
|
|
@@ -97042,6 +97069,10 @@ function touchedExportedSymbols(regionText) {
|
|
|
97042
97069
|
return [...symbols];
|
|
97043
97070
|
}
|
|
97044
97071
|
var TEST_INFIX_RE = /\.(test|spec)\./;
|
|
97072
|
+
var TEST_DIR_RE = /(^|\/)(__tests__|tests?)\//;
|
|
97073
|
+
function isTestFilePath(path) {
|
|
97074
|
+
return TEST_INFIX_RE.test(path) || TEST_DIR_RE.test(path);
|
|
97075
|
+
}
|
|
97045
97076
|
function stemOf(filePath) {
|
|
97046
97077
|
const base = filePath.split("/").at(-1) ?? filePath;
|
|
97047
97078
|
return base.replace(/\.(test|spec)\.[jt]sx?$/, "").replace(/\.[jt]sx?$/, "");
|
|
@@ -97056,7 +97087,7 @@ function testFilesTouchedNearby(regionPath, allChangedFiles) {
|
|
|
97056
97087
|
return allChangedFiles.filter((file) => {
|
|
97057
97088
|
if (file === regionPath)
|
|
97058
97089
|
return false;
|
|
97059
|
-
if (!
|
|
97090
|
+
if (!isTestFilePath(file))
|
|
97060
97091
|
return false;
|
|
97061
97092
|
return stemOf(file) === stem || dirOf(file) === dir;
|
|
97062
97093
|
});
|
|
@@ -97163,7 +97194,10 @@ function batchRiskQuestionsForHunk(facts) {
|
|
|
97163
97194
|
return batches;
|
|
97164
97195
|
}
|
|
97165
97196
|
var NON_CODE_HUNK_RE = /\.(md|txt)$/i;
|
|
97197
|
+
var GENERATED_METADATA_PATH_RE = /(^|\/)\.metaproject\/(flows|data|reviews)\//;
|
|
97166
97198
|
function isNonCodeHunk(path) {
|
|
97199
|
+
if (GENERATED_METADATA_PATH_RE.test(path))
|
|
97200
|
+
return true;
|
|
97167
97201
|
if (/(^|\/)(__fixtures__|fixtures|testdata|__snapshots__|snapshots)\//.test(path))
|
|
97168
97202
|
return false;
|
|
97169
97203
|
return NON_CODE_HUNK_RE.test(path);
|
|
@@ -97237,6 +97271,8 @@ function synthesizeRiskFindings(scored, threshold = DEFAULT_JEV_RISK_THRESHOLD)
|
|
|
97237
97271
|
for (const hunk of rankHunksByRisk(scored)) {
|
|
97238
97272
|
if (hunk.combinedRisk < threshold || hunk.facts.hasNearbyTest)
|
|
97239
97273
|
continue;
|
|
97274
|
+
if (isTestFilePath(hunk.facts.region.path))
|
|
97275
|
+
continue;
|
|
97240
97276
|
const { region } = hunk.facts;
|
|
97241
97277
|
const key = `jev-risk::${region.path}:${region.startLine}-${region.endLine}`;
|
|
97242
97278
|
const severity = hunk.combinedRisk >= 0.85 ? "minor" : "info";
|
|
@@ -97267,6 +97303,8 @@ function riskFindingStats(findings) {
|
|
|
97267
97303
|
function computeRiskRoutingHints(scored, threshold = DEFAULT_JEV_RISK_THRESHOLD) {
|
|
97268
97304
|
const hints = [];
|
|
97269
97305
|
for (const hunk of rankHunksByRisk(scored)) {
|
|
97306
|
+
if (isTestFilePath(hunk.facts.region.path))
|
|
97307
|
+
continue;
|
|
97270
97308
|
const { region } = hunk.facts;
|
|
97271
97309
|
if (hunk.probabilities.security >= threshold) {
|
|
97272
97310
|
hints.push({ file: region.path, startLine: region.startLine, endLine: region.endLine, dimension: "security", probability: hunk.probabilities.security, suggestedReviewer: "review-security-code" });
|
|
@@ -97420,7 +97458,7 @@ async function computeJevRiskResult(options) {
|
|
|
97420
97458
|
topDimension: hunk.topDimension
|
|
97421
97459
|
}));
|
|
97422
97460
|
const status = findings.length > 0 ? "DONE_WITH_CONCERNS" : "DONE";
|
|
97423
|
-
const summary = `Scored ${scored.length} hunk(s) (of ${selection.selected.length + selection.skipped.length} retained) across 5 risk dimensions against ${targetLabel}; ` + `${findings.length} finding(s) at/above threshold ${threshold} with no nearby test. ` + `${selection.skipped.length} hunk(s) skipped by --max-calls ${selection.maxCalls} (${selection.pairsSkipped} pair(s)); ` + `${selection.notCode.length} hunk(s) skipped as not a code hunk (docs/.md/.txt).`;
|
|
97461
|
+
const summary = `Scored ${scored.length} hunk(s) (of ${selection.selected.length + selection.skipped.length} retained) across 5 risk dimensions against ${targetLabel}; ` + `${findings.length} finding(s) at/above threshold ${threshold} with no nearby test. ` + `${selection.skipped.length} hunk(s) skipped by --max-calls ${selection.maxCalls} (${selection.pairsSkipped} pair(s)); ` + `${selection.notCode.length} hunk(s) skipped as not a code hunk (docs/.md/.txt, or .metaproject/{flows,data,reviews} bookkeeping).`;
|
|
97424
97462
|
return {
|
|
97425
97463
|
status,
|
|
97426
97464
|
reviewer: "review-jev-risk",
|
|
@@ -98266,7 +98304,6 @@ function boundLinkedSections(linked, maxCalls = DEFAULT_MAX_JEV_DOCS_CALLS, maxP
|
|
|
98266
98304
|
};
|
|
98267
98305
|
}
|
|
98268
98306
|
var JEV_DOCS_TOKEN_BUDGET = 64000;
|
|
98269
|
-
var QUESTIONS_BUDGET_FRACTION4 = 0.5;
|
|
98270
98307
|
var HUNK_TEXT_CHARS = 2000;
|
|
98271
98308
|
var SECTION_TEXT_CHARS = 4000;
|
|
98272
98309
|
function docsQuestionKey(linked) {
|
|
@@ -98300,19 +98337,25 @@ ${bounded}`;
|
|
|
98300
98337
|
].join(`
|
|
98301
98338
|
`);
|
|
98302
98339
|
}
|
|
98340
|
+
function buildDocsBatch(items) {
|
|
98341
|
+
return {
|
|
98342
|
+
items,
|
|
98343
|
+
state: items.map(renderSectionFacts).join(`
|
|
98344
|
+
|
|
98345
|
+
`),
|
|
98346
|
+
questions: Object.fromEntries(items.map((item) => [docsQuestionKey(item), questionFor4(item)]))
|
|
98347
|
+
};
|
|
98348
|
+
}
|
|
98349
|
+
var DOCS_BATCH_BUDGET_FRACTION = 0.4;
|
|
98350
|
+
var MAX_SECTIONS_PER_BATCH = 3;
|
|
98303
98351
|
function batchDocsSections(items) {
|
|
98304
98352
|
const batches = [];
|
|
98305
98353
|
let current = [];
|
|
98354
|
+
const effectiveBudget = JEV_DOCS_TOKEN_BUDGET * DOCS_BATCH_BUDGET_FRACTION;
|
|
98306
98355
|
const flush = () => {
|
|
98307
98356
|
if (current.length === 0)
|
|
98308
98357
|
return;
|
|
98309
|
-
batches.push(
|
|
98310
|
-
items: current,
|
|
98311
|
-
state: current.map(renderSectionFacts).join(`
|
|
98312
|
-
|
|
98313
|
-
`),
|
|
98314
|
-
questions: Object.fromEntries(current.map((item) => [docsQuestionKey(item), questionFor4(item)]))
|
|
98315
|
-
});
|
|
98358
|
+
batches.push(buildDocsBatch(current));
|
|
98316
98359
|
current = [];
|
|
98317
98360
|
};
|
|
98318
98361
|
for (const item of items) {
|
|
@@ -98322,8 +98365,7 @@ function batchDocsSections(items) {
|
|
|
98322
98365
|
`));
|
|
98323
98366
|
const questionsTokens = estimateTokens2(attempt.map((linked) => `${docsQuestionKey(linked)}:noul:${questionFor4(linked).instructions}`).join(`
|
|
98324
98367
|
`));
|
|
98325
|
-
|
|
98326
|
-
if (current.length > 0 && (stateTokens + questionsTokens > JEV_DOCS_TOKEN_BUDGET || !withinQuestionsShare)) {
|
|
98368
|
+
if (current.length > 0 && (attempt.length > MAX_SECTIONS_PER_BATCH || stateTokens + questionsTokens > effectiveBudget)) {
|
|
98327
98369
|
flush();
|
|
98328
98370
|
current = [item];
|
|
98329
98371
|
} else {
|
|
@@ -98472,6 +98514,12 @@ function renderJevDocsMarkdown(result) {
|
|
|
98472
98514
|
}
|
|
98473
98515
|
|
|
98474
98516
|
// src/commands/review-jev-docs.ts
|
|
98517
|
+
function messageOf(error) {
|
|
98518
|
+
return error instanceof Error ? error.message : String(error);
|
|
98519
|
+
}
|
|
98520
|
+
function isMaxTokensExceededError(error) {
|
|
98521
|
+
return error instanceof JevRequestError && error.status === 400 && /max_tokens/i.test(error.message);
|
|
98522
|
+
}
|
|
98475
98523
|
var JEV_DOCS_FLAGS = ["--diff", "--pr", "--max-calls", "--threshold", "--model", "--repo", "--fixtures", "--include", "--json"];
|
|
98476
98524
|
function rejectUnknownJevDocsFlags(args) {
|
|
98477
98525
|
const unknown = args.filter((arg) => arg.startsWith("--") && !JEV_DOCS_FLAGS.includes(arg.split("=")[0]));
|
|
@@ -98681,29 +98729,54 @@ async function computeJevDocsResult(options) {
|
|
|
98681
98729
|
let outputTokens = 0;
|
|
98682
98730
|
let costUsd = 0;
|
|
98683
98731
|
let sawUsage = false;
|
|
98684
|
-
|
|
98685
|
-
|
|
98686
|
-
|
|
98687
|
-
|
|
98688
|
-
|
|
98689
|
-
|
|
98690
|
-
|
|
98691
|
-
|
|
98692
|
-
|
|
98693
|
-
|
|
98732
|
+
let jevError;
|
|
98733
|
+
const attemptBatch = async (batch) => {
|
|
98734
|
+
try {
|
|
98735
|
+
const result = await callJevSystemOne(fetchFn, { model, state: batch.state, questions: batch.questions }, { env: options.env ?? process.env });
|
|
98736
|
+
jevCalls += 1;
|
|
98737
|
+
if (result.usage.input_tokens !== undefined) {
|
|
98738
|
+
inputTokens += result.usage.input_tokens;
|
|
98739
|
+
sawUsage = true;
|
|
98740
|
+
}
|
|
98741
|
+
if (result.usage.output_tokens !== undefined) {
|
|
98742
|
+
outputTokens += result.usage.output_tokens;
|
|
98743
|
+
sawUsage = true;
|
|
98744
|
+
}
|
|
98745
|
+
if (result.usage.cost !== undefined) {
|
|
98746
|
+
costUsd += result.usage.cost;
|
|
98747
|
+
sawUsage = true;
|
|
98748
|
+
}
|
|
98749
|
+
for (const item of batch.items) {
|
|
98750
|
+
const key = `${item.section.file}::${item.section.line}`;
|
|
98751
|
+
const answer = result.answers[key];
|
|
98752
|
+
if (answer === undefined || answer.type !== "noul")
|
|
98753
|
+
continue;
|
|
98754
|
+
const finding = synthesizeDocsFinding(item, answer.noul, threshold);
|
|
98755
|
+
if (finding !== undefined)
|
|
98756
|
+
jevFindings.push(finding);
|
|
98757
|
+
}
|
|
98758
|
+
return { ok: true };
|
|
98759
|
+
} catch (error) {
|
|
98760
|
+
return { ok: false, error };
|
|
98694
98761
|
}
|
|
98695
|
-
|
|
98696
|
-
|
|
98697
|
-
|
|
98762
|
+
};
|
|
98763
|
+
for (const batch of batches) {
|
|
98764
|
+
const attempt = await attemptBatch(batch);
|
|
98765
|
+
if (attempt.ok)
|
|
98766
|
+
continue;
|
|
98767
|
+
if (isMaxTokensExceededError(attempt.error) && batch.items.length > 1) {
|
|
98768
|
+
const mid = Math.ceil(batch.items.length / 2);
|
|
98769
|
+
const halves = [buildDocsBatch(batch.items.slice(0, mid)), buildDocsBatch(batch.items.slice(mid))];
|
|
98770
|
+
for (const half of halves) {
|
|
98771
|
+
const halfAttempt = await attemptBatch(half);
|
|
98772
|
+
if (!halfAttempt.ok && jevError === undefined) {
|
|
98773
|
+
jevError = messageOf(halfAttempt.error);
|
|
98774
|
+
}
|
|
98775
|
+
}
|
|
98776
|
+
continue;
|
|
98698
98777
|
}
|
|
98699
|
-
|
|
98700
|
-
|
|
98701
|
-
const answer = result.answers[key];
|
|
98702
|
-
if (answer === undefined || answer.type !== "noul")
|
|
98703
|
-
continue;
|
|
98704
|
-
const finding = synthesizeDocsFinding(item, answer.noul, threshold);
|
|
98705
|
-
if (finding !== undefined)
|
|
98706
|
-
jevFindings.push(finding);
|
|
98778
|
+
if (jevError === undefined) {
|
|
98779
|
+
jevError = messageOf(attempt.error);
|
|
98707
98780
|
}
|
|
98708
98781
|
}
|
|
98709
98782
|
const findings = [...flagFindings, ...jevFindings].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
@@ -98717,6 +98790,7 @@ async function computeJevDocsResult(options) {
|
|
|
98717
98790
|
findings,
|
|
98718
98791
|
stats,
|
|
98719
98792
|
tokens: sawUsage ? { jevCalls, inputTokens, outputTokens, costUsd } : { jevCalls },
|
|
98793
|
+
...jevError !== undefined ? { jevError } : {},
|
|
98720
98794
|
selection: {
|
|
98721
98795
|
maxCalls,
|
|
98722
98796
|
maxPerFile,
|
|
@@ -98838,7 +98912,7 @@ function commentFactLines(facts) {
|
|
|
98838
98912
|
];
|
|
98839
98913
|
}
|
|
98840
98914
|
var COMMENT_TOKEN_BUDGET = 64000;
|
|
98841
|
-
var
|
|
98915
|
+
var QUESTIONS_BUDGET_FRACTION4 = 0.5;
|
|
98842
98916
|
var REPLY_BODY_CHARS = 500;
|
|
98843
98917
|
var HUNK_TEXT_CHARS2 = 1500;
|
|
98844
98918
|
var COMMENT_BODY_CHARS = 1500;
|
|
@@ -98904,7 +98978,7 @@ function batchOpenComments(items) {
|
|
|
98904
98978
|
`));
|
|
98905
98979
|
const questionsTokens = estimateTokens2(attempt.map((f) => `${commentQuestionKey(f)}:choice`).join(`
|
|
98906
98980
|
`));
|
|
98907
|
-
const withinQuestionsShare = questionsTokens <= COMMENT_TOKEN_BUDGET *
|
|
98981
|
+
const withinQuestionsShare = questionsTokens <= COMMENT_TOKEN_BUDGET * QUESTIONS_BUDGET_FRACTION4;
|
|
98908
98982
|
if (current.length > 0 && (stateTokens + questionsTokens > COMMENT_TOKEN_BUDGET || !withinQuestionsShare)) {
|
|
98909
98983
|
flush();
|
|
98910
98984
|
current = [item];
|
|
@@ -99651,10 +99725,10 @@ function parseThreshold5(raw) {
|
|
|
99651
99725
|
}
|
|
99652
99726
|
return value;
|
|
99653
99727
|
}
|
|
99654
|
-
function
|
|
99728
|
+
function messageOf2(error) {
|
|
99655
99729
|
return error instanceof Error ? error.message : String(error);
|
|
99656
99730
|
}
|
|
99657
|
-
function
|
|
99731
|
+
function isMaxTokensExceededError2(error) {
|
|
99658
99732
|
return error instanceof JevRequestError && error.status === 400 && /max_tokens/i.test(error.message);
|
|
99659
99733
|
}
|
|
99660
99734
|
async function fixturePrPort6(dir) {
|
|
@@ -99725,19 +99799,19 @@ async function computeJevContractResult(options) {
|
|
|
99725
99799
|
const attempt = await attemptBatch(batch);
|
|
99726
99800
|
if (attempt.ok)
|
|
99727
99801
|
continue;
|
|
99728
|
-
if (
|
|
99802
|
+
if (isMaxTokensExceededError2(attempt.error) && batch.items.length > 1) {
|
|
99729
99803
|
const mid = Math.ceil(batch.items.length / 2);
|
|
99730
99804
|
const halves = [buildContractClaimBatch(batch.items.slice(0, mid)), buildContractClaimBatch(batch.items.slice(mid))];
|
|
99731
99805
|
for (const half of halves) {
|
|
99732
99806
|
const halfAttempt = await attemptBatch(half);
|
|
99733
99807
|
if (!halfAttempt.ok && jevError === undefined) {
|
|
99734
|
-
jevError =
|
|
99808
|
+
jevError = messageOf2(halfAttempt.error);
|
|
99735
99809
|
}
|
|
99736
99810
|
}
|
|
99737
99811
|
continue;
|
|
99738
99812
|
}
|
|
99739
99813
|
if (jevError === undefined) {
|
|
99740
|
-
jevError =
|
|
99814
|
+
jevError = messageOf2(attempt.error);
|
|
99741
99815
|
}
|
|
99742
99816
|
}
|
|
99743
99817
|
for (const item of items) {
|
|
@@ -100149,10 +100223,10 @@ function parseThreshold6(raw) {
|
|
|
100149
100223
|
return value;
|
|
100150
100224
|
}
|
|
100151
100225
|
var LIKELY_DUPLICATE_THRESHOLD = 0.5;
|
|
100152
|
-
function
|
|
100226
|
+
function messageOf3(error) {
|
|
100153
100227
|
return error instanceof Error ? error.message : String(error);
|
|
100154
100228
|
}
|
|
100155
|
-
function
|
|
100229
|
+
function isMaxTokensExceededError3(error) {
|
|
100156
100230
|
return error instanceof JevRequestError && error.status === 400 && /max_tokens/i.test(error.message);
|
|
100157
100231
|
}
|
|
100158
100232
|
async function loadReportRaw(reportPath) {
|
|
@@ -100226,19 +100300,19 @@ async function computeJevTriageResult(options) {
|
|
|
100226
100300
|
const attempt = await attemptBatch(batch);
|
|
100227
100301
|
if (attempt.ok)
|
|
100228
100302
|
continue;
|
|
100229
|
-
if (
|
|
100303
|
+
if (isMaxTokensExceededError3(attempt.error) && batch.items.length > 1) {
|
|
100230
100304
|
const mid = Math.ceil(batch.items.length / 2);
|
|
100231
100305
|
const halves = [buildTriageBatch(batch.items.slice(0, mid)), buildTriageBatch(batch.items.slice(mid))];
|
|
100232
100306
|
for (const half of halves) {
|
|
100233
100307
|
const halfAttempt = await attemptBatch(half);
|
|
100234
100308
|
if (!halfAttempt.ok && jevError === undefined) {
|
|
100235
|
-
jevError =
|
|
100309
|
+
jevError = messageOf3(halfAttempt.error);
|
|
100236
100310
|
}
|
|
100237
100311
|
}
|
|
100238
100312
|
continue;
|
|
100239
100313
|
}
|
|
100240
100314
|
if (jevError === undefined) {
|
|
100241
|
-
jevError =
|
|
100315
|
+
jevError = messageOf3(attempt.error);
|
|
100242
100316
|
}
|
|
100243
100317
|
}
|
|
100244
100318
|
}
|
|
@@ -101421,7 +101495,7 @@ function applyDeterministicOverride(verdict, signals) {
|
|
|
101421
101495
|
// src/review/conform-jev.ts
|
|
101422
101496
|
init_service4();
|
|
101423
101497
|
var CONFORM_TOKEN_BUDGET = 64000;
|
|
101424
|
-
var
|
|
101498
|
+
var QUESTIONS_BUDGET_FRACTION5 = 0.5;
|
|
101425
101499
|
function questionFor6(clause) {
|
|
101426
101500
|
return {
|
|
101427
101501
|
type: "noul",
|
|
@@ -101461,7 +101535,7 @@ function batchConformItems(items, sharedRedactedText) {
|
|
|
101461
101535
|
const factsTokens = estimateTokens2(renderFacts(attempt));
|
|
101462
101536
|
const questionsTokens = estimateQuestionsTokens(attempt);
|
|
101463
101537
|
const total = sharedTokens + factsTokens + questionsTokens;
|
|
101464
|
-
const withinQuestionsShare = questionsTokens <= CONFORM_TOKEN_BUDGET *
|
|
101538
|
+
const withinQuestionsShare = questionsTokens <= CONFORM_TOKEN_BUDGET * QUESTIONS_BUDGET_FRACTION5;
|
|
101465
101539
|
if (current.length > 0 && (total > CONFORM_TOKEN_BUDGET || !withinQuestionsShare)) {
|
|
101466
101540
|
flush();
|
|
101467
101541
|
current = [item];
|
|
@@ -110205,7 +110279,7 @@ async function diagnose(server, options) {
|
|
|
110205
110279
|
skipped: catalog.skipped
|
|
110206
110280
|
};
|
|
110207
110281
|
} catch (error) {
|
|
110208
|
-
return { ...base, status: "failed", toolCount: 0, skipped: [], detail:
|
|
110282
|
+
return { ...base, status: "failed", toolCount: 0, skipped: [], detail: messageOf4(error) };
|
|
110209
110283
|
} finally {
|
|
110210
110284
|
try {
|
|
110211
110285
|
await connection.close();
|
|
@@ -110227,7 +110301,7 @@ function oauthErrorCodeOf(error) {
|
|
|
110227
110301
|
return typeof code === "string" ? code : "";
|
|
110228
110302
|
}
|
|
110229
110303
|
function explainConnectFailure(transport, server, error) {
|
|
110230
|
-
const message = sanitiseForDisplay(
|
|
110304
|
+
const message = sanitiseForDisplay(messageOf4(error));
|
|
110231
110305
|
if (transport !== "http")
|
|
110232
110306
|
return message;
|
|
110233
110307
|
const url = displayUrl(server.raw.url);
|
|
@@ -110300,7 +110374,7 @@ function syscallCodeOf(error) {
|
|
|
110300
110374
|
}
|
|
110301
110375
|
return;
|
|
110302
110376
|
}
|
|
110303
|
-
function
|
|
110377
|
+
function messageOf4(error) {
|
|
110304
110378
|
return error instanceof Error ? error.message : String(error);
|
|
110305
110379
|
}
|
|
110306
110380
|
async function withTimeout(work, ms, name) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -180,7 +180,15 @@
|
|
|
180
180
|
"c-cpp-rules",
|
|
181
181
|
"c-cpp-skills",
|
|
182
182
|
"sql-db-rules",
|
|
183
|
-
"sql-db-skills"
|
|
183
|
+
"sql-db-skills",
|
|
184
|
+
"csharp-dotnet-rules",
|
|
185
|
+
"csharp-dotnet-skills",
|
|
186
|
+
"swift-ios-rules",
|
|
187
|
+
"swift-ios-skills",
|
|
188
|
+
"kotlin-android-rules",
|
|
189
|
+
"kotlin-android-skills",
|
|
190
|
+
"flutter-dart-rules",
|
|
191
|
+
"flutter-dart-skills"
|
|
184
192
|
],
|
|
185
193
|
"components": [
|
|
186
194
|
"lang:ts-js-node",
|
|
@@ -197,7 +205,11 @@
|
|
|
197
205
|
"framework:php-laravel",
|
|
198
206
|
"framework:ruby-rails",
|
|
199
207
|
"lang:c-cpp",
|
|
200
|
-
"capability:sql-db"
|
|
208
|
+
"capability:sql-db",
|
|
209
|
+
"lang:csharp-dotnet",
|
|
210
|
+
"framework:swift-ios",
|
|
211
|
+
"framework:kotlin-android",
|
|
212
|
+
"framework:flutter-dart"
|
|
201
213
|
]
|
|
202
214
|
},
|
|
203
215
|
"php-laravel": {
|
|
@@ -243,6 +255,50 @@
|
|
|
243
255
|
"capability:sql-db"
|
|
244
256
|
],
|
|
245
257
|
"stackDetectionAware": true
|
|
258
|
+
},
|
|
259
|
+
"csharp-dotnet": {
|
|
260
|
+
"description": "Common rules plus the C#/.NET stack pack component (`csharp-dotnet-rules` + `csharp-dotnet-skills`, from src/gdskills/bundled/stacks/csharp-dotnet/), installed when `keryx stack detect` finds a matching tag.",
|
|
261
|
+
"modules": [
|
|
262
|
+
"core-common-rules",
|
|
263
|
+
"skill-lifecycle"
|
|
264
|
+
],
|
|
265
|
+
"components": [
|
|
266
|
+
"lang:csharp-dotnet"
|
|
267
|
+
],
|
|
268
|
+
"stackDetectionAware": true
|
|
269
|
+
},
|
|
270
|
+
"swift-ios": {
|
|
271
|
+
"description": "Common rules plus the Swift/iOS stack pack component (`swift-ios-rules` + `swift-ios-skills`, from src/gdskills/bundled/stacks/swift-ios/), installed when `keryx stack detect` finds a matching tag. Standalone pack: no `lang:swift` base exists yet (flow 336 description.md).",
|
|
272
|
+
"modules": [
|
|
273
|
+
"core-common-rules",
|
|
274
|
+
"skill-lifecycle"
|
|
275
|
+
],
|
|
276
|
+
"components": [
|
|
277
|
+
"framework:swift-ios"
|
|
278
|
+
],
|
|
279
|
+
"stackDetectionAware": true
|
|
280
|
+
},
|
|
281
|
+
"kotlin-android": {
|
|
282
|
+
"description": "Common rules plus the Kotlin/Android (Jetpack Compose) stack pack component (`kotlin-android-rules` + `kotlin-android-skills`), installed when `keryx stack detect` finds a matching tag. Standalone pack (flow 336 description.md).",
|
|
283
|
+
"modules": [
|
|
284
|
+
"core-common-rules",
|
|
285
|
+
"skill-lifecycle"
|
|
286
|
+
],
|
|
287
|
+
"components": [
|
|
288
|
+
"framework:kotlin-android"
|
|
289
|
+
],
|
|
290
|
+
"stackDetectionAware": true
|
|
291
|
+
},
|
|
292
|
+
"flutter-dart": {
|
|
293
|
+
"description": "Common rules plus the Flutter/Dart stack pack component (`flutter-dart-rules` + `flutter-dart-skills`), installed when `keryx stack detect` finds a matching tag. Standalone pack (flow 336 description.md).",
|
|
294
|
+
"modules": [
|
|
295
|
+
"core-common-rules",
|
|
296
|
+
"skill-lifecycle"
|
|
297
|
+
],
|
|
298
|
+
"components": [
|
|
299
|
+
"framework:flutter-dart"
|
|
300
|
+
],
|
|
301
|
+
"stackDetectionAware": true
|
|
246
302
|
}
|
|
247
303
|
},
|
|
248
304
|
"modules": {
|
|
@@ -928,6 +984,126 @@
|
|
|
928
984
|
"defaultInstall": true,
|
|
929
985
|
"cost": "medium",
|
|
930
986
|
"stability": "experimental"
|
|
987
|
+
},
|
|
988
|
+
"csharp-dotnet-rules": {
|
|
989
|
+
"kind": "rule",
|
|
990
|
+
"description": "C#/.NET stack pack rules (coding-style, patterns, security, testing; scoped to *.cs) from src/gdskills/bundled/stacks/csharp-dotnet/rules/.",
|
|
991
|
+
"paths": [
|
|
992
|
+
"src/gdskills/bundled/stacks/csharp-dotnet/rules/*.mdc"
|
|
993
|
+
],
|
|
994
|
+
"targets": [
|
|
995
|
+
"claude",
|
|
996
|
+
"keryx-shell"
|
|
997
|
+
],
|
|
998
|
+
"dependencies": [],
|
|
999
|
+
"defaultInstall": true,
|
|
1000
|
+
"cost": "light",
|
|
1001
|
+
"stability": "experimental"
|
|
1002
|
+
},
|
|
1003
|
+
"csharp-dotnet-skills": {
|
|
1004
|
+
"kind": "skill",
|
|
1005
|
+
"description": "C#/.NET stack pack skills (implementation, testing, code review, build-fix) from src/gdskills/bundled/stacks/csharp-dotnet/skills/.",
|
|
1006
|
+
"paths": [
|
|
1007
|
+
"src/gdskills/bundled/stacks/csharp-dotnet/skills/**"
|
|
1008
|
+
],
|
|
1009
|
+
"targets": [
|
|
1010
|
+
"claude",
|
|
1011
|
+
"keryx-shell"
|
|
1012
|
+
],
|
|
1013
|
+
"dependencies": [],
|
|
1014
|
+
"defaultInstall": true,
|
|
1015
|
+
"cost": "medium",
|
|
1016
|
+
"stability": "experimental"
|
|
1017
|
+
},
|
|
1018
|
+
"swift-ios-rules": {
|
|
1019
|
+
"kind": "rule",
|
|
1020
|
+
"description": "Swift/iOS stack pack rules (coding-style, patterns, security, testing; scoped to *.swift) from src/gdskills/bundled/stacks/swift-ios/rules/.",
|
|
1021
|
+
"paths": [
|
|
1022
|
+
"src/gdskills/bundled/stacks/swift-ios/rules/*.mdc"
|
|
1023
|
+
],
|
|
1024
|
+
"targets": [
|
|
1025
|
+
"claude",
|
|
1026
|
+
"keryx-shell"
|
|
1027
|
+
],
|
|
1028
|
+
"dependencies": [],
|
|
1029
|
+
"defaultInstall": true,
|
|
1030
|
+
"cost": "light",
|
|
1031
|
+
"stability": "experimental"
|
|
1032
|
+
},
|
|
1033
|
+
"swift-ios-skills": {
|
|
1034
|
+
"kind": "skill",
|
|
1035
|
+
"description": "Swift/iOS stack pack skills (implementation, testing, code review, build-fix) from src/gdskills/bundled/stacks/swift-ios/skills/.",
|
|
1036
|
+
"paths": [
|
|
1037
|
+
"src/gdskills/bundled/stacks/swift-ios/skills/**"
|
|
1038
|
+
],
|
|
1039
|
+
"targets": [
|
|
1040
|
+
"claude",
|
|
1041
|
+
"keryx-shell"
|
|
1042
|
+
],
|
|
1043
|
+
"dependencies": [],
|
|
1044
|
+
"defaultInstall": true,
|
|
1045
|
+
"cost": "medium",
|
|
1046
|
+
"stability": "experimental"
|
|
1047
|
+
},
|
|
1048
|
+
"kotlin-android-rules": {
|
|
1049
|
+
"kind": "rule",
|
|
1050
|
+
"description": "Kotlin/Android (Jetpack Compose) stack pack rules (coding-style, patterns, security, testing; scoped to *.kt/*.kts) from src/gdskills/bundled/stacks/kotlin-android/rules/.",
|
|
1051
|
+
"paths": [
|
|
1052
|
+
"src/gdskills/bundled/stacks/kotlin-android/rules/*.mdc"
|
|
1053
|
+
],
|
|
1054
|
+
"targets": [
|
|
1055
|
+
"claude",
|
|
1056
|
+
"keryx-shell"
|
|
1057
|
+
],
|
|
1058
|
+
"dependencies": [],
|
|
1059
|
+
"defaultInstall": true,
|
|
1060
|
+
"cost": "light",
|
|
1061
|
+
"stability": "experimental"
|
|
1062
|
+
},
|
|
1063
|
+
"kotlin-android-skills": {
|
|
1064
|
+
"kind": "skill",
|
|
1065
|
+
"description": "Kotlin/Android (Jetpack Compose) stack pack skills (implementation, testing, code review, build-fix) from src/gdskills/bundled/stacks/kotlin-android/skills/.",
|
|
1066
|
+
"paths": [
|
|
1067
|
+
"src/gdskills/bundled/stacks/kotlin-android/skills/**"
|
|
1068
|
+
],
|
|
1069
|
+
"targets": [
|
|
1070
|
+
"claude",
|
|
1071
|
+
"keryx-shell"
|
|
1072
|
+
],
|
|
1073
|
+
"dependencies": [],
|
|
1074
|
+
"defaultInstall": true,
|
|
1075
|
+
"cost": "medium",
|
|
1076
|
+
"stability": "experimental"
|
|
1077
|
+
},
|
|
1078
|
+
"flutter-dart-rules": {
|
|
1079
|
+
"kind": "rule",
|
|
1080
|
+
"description": "Flutter/Dart stack pack rules (coding-style, patterns, security, testing; scoped to *.dart) from src/gdskills/bundled/stacks/flutter-dart/rules/.",
|
|
1081
|
+
"paths": [
|
|
1082
|
+
"src/gdskills/bundled/stacks/flutter-dart/rules/*.mdc"
|
|
1083
|
+
],
|
|
1084
|
+
"targets": [
|
|
1085
|
+
"claude",
|
|
1086
|
+
"keryx-shell"
|
|
1087
|
+
],
|
|
1088
|
+
"dependencies": [],
|
|
1089
|
+
"defaultInstall": true,
|
|
1090
|
+
"cost": "light",
|
|
1091
|
+
"stability": "experimental"
|
|
1092
|
+
},
|
|
1093
|
+
"flutter-dart-skills": {
|
|
1094
|
+
"kind": "skill",
|
|
1095
|
+
"description": "Flutter/Dart stack pack skills (implementation, testing, code review, build-fix) from src/gdskills/bundled/stacks/flutter-dart/skills/.",
|
|
1096
|
+
"paths": [
|
|
1097
|
+
"src/gdskills/bundled/stacks/flutter-dart/skills/**"
|
|
1098
|
+
],
|
|
1099
|
+
"targets": [
|
|
1100
|
+
"claude",
|
|
1101
|
+
"keryx-shell"
|
|
1102
|
+
],
|
|
1103
|
+
"dependencies": [],
|
|
1104
|
+
"defaultInstall": true,
|
|
1105
|
+
"cost": "medium",
|
|
1106
|
+
"stability": "experimental"
|
|
931
1107
|
}
|
|
932
1108
|
},
|
|
933
1109
|
"components": {
|
|
@@ -1139,6 +1315,59 @@
|
|
|
1139
1315
|
"provenance": {
|
|
1140
1316
|
"origin": "authored"
|
|
1141
1317
|
}
|
|
1318
|
+
},
|
|
1319
|
+
"lang:csharp-dotnet": {
|
|
1320
|
+
"family": "language",
|
|
1321
|
+
"modules": [
|
|
1322
|
+
"csharp-dotnet-rules",
|
|
1323
|
+
"csharp-dotnet-skills"
|
|
1324
|
+
],
|
|
1325
|
+
"detectionMarkers": [
|
|
1326
|
+
"csharp",
|
|
1327
|
+
"dotnet"
|
|
1328
|
+
],
|
|
1329
|
+
"provenance": {
|
|
1330
|
+
"origin": "authored"
|
|
1331
|
+
}
|
|
1332
|
+
},
|
|
1333
|
+
"framework:swift-ios": {
|
|
1334
|
+
"family": "framework",
|
|
1335
|
+
"modules": [
|
|
1336
|
+
"swift-ios-rules",
|
|
1337
|
+
"swift-ios-skills"
|
|
1338
|
+
],
|
|
1339
|
+
"detectionMarkers": [
|
|
1340
|
+
"ios"
|
|
1341
|
+
],
|
|
1342
|
+
"provenance": {
|
|
1343
|
+
"origin": "authored"
|
|
1344
|
+
}
|
|
1345
|
+
},
|
|
1346
|
+
"framework:kotlin-android": {
|
|
1347
|
+
"family": "framework",
|
|
1348
|
+
"modules": [
|
|
1349
|
+
"kotlin-android-rules",
|
|
1350
|
+
"kotlin-android-skills"
|
|
1351
|
+
],
|
|
1352
|
+
"detectionMarkers": [
|
|
1353
|
+
"android"
|
|
1354
|
+
],
|
|
1355
|
+
"provenance": {
|
|
1356
|
+
"origin": "authored"
|
|
1357
|
+
}
|
|
1358
|
+
},
|
|
1359
|
+
"framework:flutter-dart": {
|
|
1360
|
+
"family": "framework",
|
|
1361
|
+
"modules": [
|
|
1362
|
+
"flutter-dart-rules",
|
|
1363
|
+
"flutter-dart-skills"
|
|
1364
|
+
],
|
|
1365
|
+
"detectionMarkers": [
|
|
1366
|
+
"flutter"
|
|
1367
|
+
],
|
|
1368
|
+
"provenance": {
|
|
1369
|
+
"origin": "authored"
|
|
1370
|
+
}
|
|
1142
1371
|
}
|
|
1143
1372
|
}
|
|
1144
1373
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{
|
|
2
|
+
"agents": [],
|
|
3
|
+
"note": "no pair -- honest DeepSeek deepseek-chat runner+judge gate (trials=10, strictness=high, flow 336) fails all 4 skills on trigger accuracy, never on behavior (every behavior scenario clears the 0.8 floor, mostly 1.0/1.0): dotnet-implementation TP 2/7 FP 1/8, dotnet-testing TP 4/7 FP 0/8, dotnet-code-review TP 3/7 FP 0/8, dotnet-build-fix TP 1/7 FP 0/8 (worst -- distinctive .NET vocabulary like NuGet/StyleCop/CS#### still did not route). Genuine routing weakness against an increasingly crowded catalog (12+ implement/test/review/build-fix category-mates across stacks), not an authoring defect -- stays experimental per flow 336's stack-pack-lessons.md rule against tuning descriptions to restate failing eval prompts."
|
|
4
|
+
}
|