@dailephd/my-dev-kit-lab 0.6.2 → 0.7.0
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/CHANGELOG.md +26 -0
- package/README.md +11 -8
- package/benchmarks/contracts/context-window-scaling-cases.json +220 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/README.md +14 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-1/carrier-depot-catalog-01.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-1/course-module-catalog-06.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-1/library-shelf-catalog-07.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-1/sensor-station-catalog-05.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-1/staff-rota-catalog-03.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-1/supplier-contract-catalog-02.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-1/vehicle-route-catalog-04.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-2/archive-box-catalog-12.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-2/clinic-ward-catalog-08.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-2/greenhouse-bay-catalog-13.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-2/harbor-berth-catalog-10.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-2/kitchen-section-catalog-15.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-2/market-stall-catalog-09.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-2/station-platform-catalog-14.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-2/workshop-bench-catalog-11.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/archive-box-catalog-28.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/carrier-depot-catalog-17.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/clinic-ward-catalog-24.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/course-module-catalog-22.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/greenhouse-bay-catalog-29.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/harbor-berth-catalog-26.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/kitchen-section-catalog-31.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/library-shelf-catalog-23.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/market-stall-catalog-25.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/sensor-station-catalog-21.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/staff-rota-catalog-19.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/station-platform-catalog-30.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/supplier-contract-catalog-18.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/vehicle-route-catalog-20.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/warehouse-zone-catalog-16.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-3/workshop-bench-catalog-27.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/archive-box-catalog-44.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/carrier-depot-catalog-33.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/carrier-depot-catalog-49.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/clinic-ward-catalog-40.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/clinic-ward-catalog-56.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/course-module-catalog-38.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/course-module-catalog-54.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/greenhouse-bay-catalog-45.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/harbor-berth-catalog-42.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/harbor-berth-catalog-58.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/kitchen-section-catalog-47.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/library-shelf-catalog-39.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/library-shelf-catalog-55.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/market-stall-catalog-41.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/market-stall-catalog-57.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/sensor-station-catalog-37.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/sensor-station-catalog-53.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/staff-rota-catalog-35.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/staff-rota-catalog-51.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/station-platform-catalog-46.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/supplier-contract-catalog-34.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/supplier-contract-catalog-50.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/vehicle-route-catalog-36.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/vehicle-route-catalog-52.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/warehouse-zone-catalog-32.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/warehouse-zone-catalog-48.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/filler/tier-4/workshop-bench-catalog-43.ts +302 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/tasks/auditRedaction.ts +25 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/tasks/inventoryReservation.ts +26 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/tasks/invoiceTotals.ts +25 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/src/tasks/shippingQuote.ts +32 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/tests/tasks/auditRedaction.test.ts +17 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/tests/tasks/inventoryReservation.test.ts +19 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/tests/tasks/invoiceTotals.test.ts +14 -0
- package/benchmarks/projects/context-window-scaling-fixed-ts/tests/tasks/shippingQuote.test.ts +19 -0
- package/dist/src/cli/help.js +27 -10
- package/dist/src/commands/runExperimentDescribeCommand.js +5 -2
- package/dist/src/commands/runExperimentRunCommand.js +64 -8
- package/dist/src/evaluation/benchmarkMetadata.js +5 -1
- package/dist/src/evaluation/parseAgentAnswer.js +172 -24
- package/dist/src/evaluation/runMyDevKitRetrieval.js +120 -7
- package/dist/src/experiments/defaultRegistry.js +2 -0
- package/dist/src/experiments/plugins/contextWindowScaling/cliBudgets.js +31 -0
- package/dist/src/experiments/plugins/contextWindowScaling/config.js +84 -0
- package/dist/src/experiments/plugins/contextWindowScaling/contextBudget.js +43 -0
- package/dist/src/experiments/plugins/contextWindowScaling/evaluation.js +36 -0
- package/dist/src/experiments/plugins/contextWindowScaling/execution.js +187 -0
- package/dist/src/experiments/plugins/contextWindowScaling/executionArtifact.js +15 -0
- package/dist/src/experiments/plugins/contextWindowScaling/executionArtifactReader.js +186 -0
- package/dist/src/experiments/plugins/contextWindowScaling/index.js +14 -0
- package/dist/src/experiments/plugins/contextWindowScaling/metadata.js +12 -0
- package/dist/src/experiments/plugins/contextWindowScaling/metrics.js +149 -0
- package/dist/src/experiments/plugins/contextWindowScaling/plugin.js +185 -0
- package/dist/src/experiments/plugins/contextWindowScaling/projectProfile.js +51 -0
- package/dist/src/experiments/plugins/contextWindowScaling/relevantFiles.js +76 -0
- package/dist/src/experiments/plugins/contextWindowScaling/successEvidence.js +60 -0
- package/dist/src/experiments/plugins/contextWindowScaling/types.js +1 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/comparisonV2.js +49 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/config.js +5 -4
- package/dist/src/experiments/plugins/incrementalChangeStaleness/disposableTarget.js +20 -2
- package/dist/src/experiments/plugins/incrementalChangeStaleness/execution.js +42 -16
- package/dist/src/experiments/plugins/incrementalChangeStaleness/executionArtifact.js +4 -4
- package/dist/src/experiments/plugins/incrementalChangeStaleness/executionArtifactV2.js +289 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/executionV2.js +195 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/indexClone.js +76 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/lifecycle.js +64 -32
- package/dist/src/experiments/plugins/incrementalChangeStaleness/lifecyclePolicy.js +6 -4
- package/dist/src/experiments/plugins/incrementalChangeStaleness/lifecyclePolicyV2.js +78 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/lifecycleV2.js +298 -0
- package/dist/src/experiments/plugins/incrementalChangeStaleness/plugin.js +213 -12
- package/dist/src/experiments/plugins/incrementalChangeStaleness/treatmentSessionV2.js +5 -0
- package/dist/src/experiments/plugins/index.js +1 -0
- package/dist/src/experiments/plugins/warmIndexReuse/agentEvaluation.js +1 -1
- package/dist/src/experiments/plugins/warmIndexReuse/warmIndexSession.js +3 -1
- package/dist/src/mobile/android/advancedSecurity/candidateEvidence.js +9 -2
- package/dist/src/mobile/android/advancedSecurity/redaction.js +19 -10
- package/dist/src/mobile/android/advancedSecurity/secretCandidates/analyzeSecretCandidates.js +12 -2
- package/dist/src/mobile/android/advancedSecurity/signingConfiguration/analyzeSigningConfiguration.js +1 -1
- package/dist/src/mobile/android/advancedSecurity/signingConfiguration/extractSigningConfigurations.js +7 -7
- package/dist/src/plots/buildContextWindowScalingPlotData.js +96 -0
- package/dist/src/plots/index.js +1 -0
- package/dist/src/plots/writePlotArtifacts.js +12 -3
- package/dist/src/report/experiments/buildContextWindowScalingReport.js +84 -0
- package/dist/src/report/experiments/buildIncrementalChangeStalenessPluginReport.js +33 -0
- package/dist/src/report/experiments/buildIncrementalChangeStalenessReport.js +1 -1
- package/dist/src/report/experiments/buildIncrementalChangeStalenessReportV2.js +80 -0
- package/dist/src/report/experiments/buildPluginExperimentReport.js +24 -4
- package/dist/src/report/experiments/contextWindowScalingReportModel.js +3 -0
- package/dist/src/report/experiments/incrementalChangeStalenessReportModelV2.js +3 -0
- package/dist/src/report/experiments/incrementalChangeStalenessReportRowsV2.js +146 -0
- package/dist/src/report/experiments/index.js +7 -0
- package/dist/src/report/experiments/renderContextWindowScalingHtml.js +99 -0
- package/dist/src/report/experiments/renderContextWindowScalingText.js +108 -0
- package/dist/src/report/experiments/renderIncrementalChangeStalenessHtml.js +4 -0
- package/dist/src/report/experiments/renderIncrementalChangeStalenessHtmlV2.js +111 -0
- package/dist/src/report/experiments/renderIncrementalChangeStalenessTextV2.js +96 -0
- package/dist/src/report/experiments/renderPluginExperimentReportHtml.js +3 -0
- package/dist/src/report/experiments/renderPluginExperimentReportText.js +14 -0
- package/dist/src/securityValidation/staticScans/codeql.js +8 -8
- package/docs/METRICS.md +58 -0
- package/examples/tutorial-browser/prepare.mjs +13 -13
- package/examples/tutorial-browser/server.mjs +13 -13
- package/package.json +1 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { invalidExperimentConfig, isPlainObject, validExperimentConfig } from "../../config.js";
|
|
2
|
+
import { isValidContextBudgetTokens, STANDARD_CONTEXT_BUDGETS } from "./contextBudget.js";
|
|
3
|
+
const MAX_REPORTED_INVALID_BUDGETS = 5;
|
|
4
|
+
export const defaultContextWindowScalingConfig = {
|
|
5
|
+
contextBudgets: [...STANDARD_CONTEXT_BUDGETS],
|
|
6
|
+
kitCommand: "npx @dailephd/my-dev-kit@latest",
|
|
7
|
+
};
|
|
8
|
+
export const contextWindowScalingConfigDefinition = {
|
|
9
|
+
fields: [
|
|
10
|
+
{
|
|
11
|
+
name: "contextBudgets",
|
|
12
|
+
type: "array",
|
|
13
|
+
description: "Estimated-context-token budgets (positive safe integers, no duplicates). Defaults to 8192, 16384, 32768, 65536.",
|
|
14
|
+
defaultValue: [...STANDARD_CONTEXT_BUDGETS],
|
|
15
|
+
},
|
|
16
|
+
{ name: "kitCommand", type: "string", description: "my-dev-kit command used for my-dev-kit-guided retrieval." },
|
|
17
|
+
],
|
|
18
|
+
};
|
|
19
|
+
/** Returns ascending budgets; invalid input is rejected, never repaired or deduplicated. */
|
|
20
|
+
export function validateContextBudgets(value) {
|
|
21
|
+
if (!Array.isArray(value)) {
|
|
22
|
+
return { budgets: [], errors: ["contextBudgets must be an array of positive safe integers."] };
|
|
23
|
+
}
|
|
24
|
+
if (value.length === 0) {
|
|
25
|
+
return { budgets: [], errors: ["contextBudgets must not be empty."] };
|
|
26
|
+
}
|
|
27
|
+
const errors = [];
|
|
28
|
+
const invalid = value
|
|
29
|
+
.map((entry, index) => ({ entry, index }))
|
|
30
|
+
.filter(({ entry }) => !isValidContextBudgetTokens(entry));
|
|
31
|
+
for (const { entry, index } of invalid.slice(0, MAX_REPORTED_INVALID_BUDGETS)) {
|
|
32
|
+
errors.push(`contextBudgets[${index}] must be a positive safe integer (received ${describe(entry)}).`);
|
|
33
|
+
}
|
|
34
|
+
if (invalid.length > MAX_REPORTED_INVALID_BUDGETS) {
|
|
35
|
+
errors.push(`${invalid.length - MAX_REPORTED_INVALID_BUDGETS} additional invalid contextBudgets entries omitted.`);
|
|
36
|
+
}
|
|
37
|
+
if (errors.length > 0) {
|
|
38
|
+
return { budgets: [], errors };
|
|
39
|
+
}
|
|
40
|
+
const numbers = value;
|
|
41
|
+
const duplicates = [...new Set(numbers.filter((entry, index) => numbers.indexOf(entry) !== index))].sort((a, b) => a - b);
|
|
42
|
+
if (duplicates.length > 0) {
|
|
43
|
+
return {
|
|
44
|
+
budgets: [],
|
|
45
|
+
errors: [`contextBudgets contains duplicate value(s): ${duplicates.slice(0, MAX_REPORTED_INVALID_BUDGETS).join(", ")}.`],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return { budgets: [...numbers].sort((a, b) => a - b), errors: [] };
|
|
49
|
+
}
|
|
50
|
+
function describe(entry) {
|
|
51
|
+
if (typeof entry === "number") {
|
|
52
|
+
return String(entry);
|
|
53
|
+
}
|
|
54
|
+
if (typeof entry === "string") {
|
|
55
|
+
return JSON.stringify(entry.length > 20 ? `${entry.slice(0, 20)}...` : entry);
|
|
56
|
+
}
|
|
57
|
+
return typeof entry;
|
|
58
|
+
}
|
|
59
|
+
export function validateContextWindowScalingConfig(config) {
|
|
60
|
+
if (config !== undefined && !isPlainObject(config)) {
|
|
61
|
+
return invalidExperimentConfig(["context window scaling config must be an object."]);
|
|
62
|
+
}
|
|
63
|
+
const supported = Object.keys(defaultContextWindowScalingConfig);
|
|
64
|
+
const unsupported = Object.keys(config ?? {}).filter((key) => !supported.includes(key));
|
|
65
|
+
if (unsupported.length > 0) {
|
|
66
|
+
return invalidExperimentConfig([
|
|
67
|
+
`Unsupported context-window-scaling config field(s): ${unsupported.sort().join(", ")}.`,
|
|
68
|
+
]);
|
|
69
|
+
}
|
|
70
|
+
const errors = [];
|
|
71
|
+
const kitCommand = config?.kitCommand ?? defaultContextWindowScalingConfig.kitCommand;
|
|
72
|
+
if (typeof kitCommand !== "string" || !kitCommand.trim()) {
|
|
73
|
+
errors.push("kitCommand must be a non-empty string.");
|
|
74
|
+
}
|
|
75
|
+
let contextBudgets = [...STANDARD_CONTEXT_BUDGETS];
|
|
76
|
+
if (config?.contextBudgets !== undefined) {
|
|
77
|
+
const validated = validateContextBudgets(config.contextBudgets);
|
|
78
|
+
errors.push(...validated.errors);
|
|
79
|
+
contextBudgets = validated.budgets;
|
|
80
|
+
}
|
|
81
|
+
return errors.length > 0
|
|
82
|
+
? invalidExperimentConfig(errors)
|
|
83
|
+
: validExperimentConfig({ contextBudgets, kitCommand: kitCommand });
|
|
84
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export const CONTEXT_BUDGET_8K = 8192;
|
|
2
|
+
export const CONTEXT_BUDGET_16K = 16384;
|
|
3
|
+
export const CONTEXT_BUDGET_32K = 32768;
|
|
4
|
+
export const CONTEXT_BUDGET_64K = 65536;
|
|
5
|
+
export const STANDARD_CONTEXT_BUDGETS = Object.freeze([
|
|
6
|
+
CONTEXT_BUDGET_8K,
|
|
7
|
+
CONTEXT_BUDGET_16K,
|
|
8
|
+
CONTEXT_BUDGET_32K,
|
|
9
|
+
CONTEXT_BUDGET_64K,
|
|
10
|
+
]);
|
|
11
|
+
export function isValidContextBudgetTokens(value) {
|
|
12
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
13
|
+
}
|
|
14
|
+
/** Exact boundary fits: estimatedTokens <= budget. */
|
|
15
|
+
export function classifyContextFit(contextEstimatedTokens, contextBudgetTokens) {
|
|
16
|
+
assertMeasuredTokens(contextEstimatedTokens);
|
|
17
|
+
assertBudget(contextBudgetTokens);
|
|
18
|
+
return contextEstimatedTokens <= contextBudgetTokens ? "fits" : "context-too-large";
|
|
19
|
+
}
|
|
20
|
+
/** estimated / budget * 100. Not capped at 100 and not rounded. */
|
|
21
|
+
export function calculateContextBudgetUtilizationPercent(contextEstimatedTokens, contextBudgetTokens) {
|
|
22
|
+
assertMeasuredTokens(contextEstimatedTokens);
|
|
23
|
+
assertBudget(contextBudgetTokens);
|
|
24
|
+
return (contextEstimatedTokens / contextBudgetTokens) * 100;
|
|
25
|
+
}
|
|
26
|
+
export function buildContextBudgetEvidence(contextEstimatedTokens, contextBudgetTokens) {
|
|
27
|
+
return {
|
|
28
|
+
contextBudgetTokens,
|
|
29
|
+
contextEstimatedTokens,
|
|
30
|
+
contextFitStatus: classifyContextFit(contextEstimatedTokens, contextBudgetTokens),
|
|
31
|
+
contextBudgetUtilizationPercent: calculateContextBudgetUtilizationPercent(contextEstimatedTokens, contextBudgetTokens),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function assertBudget(value) {
|
|
35
|
+
if (!isValidContextBudgetTokens(value)) {
|
|
36
|
+
throw new RangeError("Context budget must be a positive safe integer.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function assertMeasuredTokens(value) {
|
|
40
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
41
|
+
throw new RangeError("Estimated context tokens must be a nonnegative safe integer.");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { resolveWithinRoot } from "../../../core/pathSafety.js";
|
|
3
|
+
import { evaluateFakeSide } from "../warmIndexReuse/agentEvaluation.js";
|
|
4
|
+
import { taskOutputSegment } from "../warmIndexReuse/selection.js";
|
|
5
|
+
import { toCorrectnessEvidence } from "./successEvidence.js";
|
|
6
|
+
/**
|
|
7
|
+
* Reuses the single existing fake-agent pipeline (prompt owner, fake agent, parseAgentAnswer,
|
|
8
|
+
* classifyAgentRunOutcome, scoreCorrectness) owned by warm-index agent evaluation. The pipeline
|
|
9
|
+
* derives its prompt from the case and never receives a budget, so the result is identical for
|
|
10
|
+
* every budget the treatment context fits.
|
|
11
|
+
*/
|
|
12
|
+
export const evaluateTreatmentWithFakeAgent = async (args) => {
|
|
13
|
+
const side = await evaluateFakeSide({
|
|
14
|
+
evaluationCase: args.evaluationCase,
|
|
15
|
+
caseId: args.evaluationCase.id,
|
|
16
|
+
// The shared pipeline's side ids map to prompt strategies; the guided treatment uses the
|
|
17
|
+
// my-dev-kit-guided strategy. The side id is internal and is not persisted as a variant.
|
|
18
|
+
variantId: args.treatment === "raw-full-file" ? "raw-full-file" : "warm-index-reuse",
|
|
19
|
+
projectProfiles: args.projectProfiles,
|
|
20
|
+
outDir: resolveWithinRoot(args.outputRoot, path.join("agents", taskOutputSegment(args.evaluationCase.id), args.treatment)),
|
|
21
|
+
cwd: args.cwd,
|
|
22
|
+
env: args.env,
|
|
23
|
+
});
|
|
24
|
+
return {
|
|
25
|
+
agentId: "fake-agent",
|
|
26
|
+
agentStatus: side.status,
|
|
27
|
+
correctness: toCorrectnessEvidence({
|
|
28
|
+
available: side.correctness.available,
|
|
29
|
+
score: side.correctness.score,
|
|
30
|
+
passed: side.correctness.passed,
|
|
31
|
+
}),
|
|
32
|
+
failureReasons: [...side.correctness.failureReasons],
|
|
33
|
+
warnings: [...side.warnings],
|
|
34
|
+
errors: [...side.errors],
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { tokenCountMethod } from "../../../core/countTokens.js";
|
|
3
|
+
import { runMyDevKitRetrieval } from "../../../evaluation/runMyDevKitRetrieval.js";
|
|
4
|
+
import { runRawFullFileBaseline } from "../../../evaluation/runRawFullFileBaseline.js";
|
|
5
|
+
import { taskOutputSegment } from "../warmIndexReuse/selection.js";
|
|
6
|
+
import { evaluateTreatmentWithFakeAgent } from "./evaluation.js";
|
|
7
|
+
import { CONTEXT_WINDOW_SCALING_TREATMENT_IDS } from "./metadata.js";
|
|
8
|
+
import { computeRelevantFileEvidence } from "./relevantFiles.js";
|
|
9
|
+
import { buildBudgetCell, UNAVAILABLE_CORRECTNESS } from "./successEvidence.js";
|
|
10
|
+
export const defaultContextWindowScalingDependencies = {
|
|
11
|
+
constructRawContext: (evaluationCase) => runRawFullFileBaseline(evaluationCase),
|
|
12
|
+
constructGuidedContext: ({ evaluationCase, kitCommand, outputDir }) => runMyDevKitRetrieval({ evaluationCase, kitCommand, outputDir, requireKit: false }),
|
|
13
|
+
evaluateTreatment: evaluateTreatmentWithFakeAgent,
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Per case: construct each treatment context once, then evaluate that one context against every
|
|
17
|
+
* budget. A deterministic evaluation runs at most once per treatment and is shared by the budgets
|
|
18
|
+
* the context fits. Nothing is truncated, retried, or rebuilt per budget.
|
|
19
|
+
*/
|
|
20
|
+
export async function executeContextWindowScalingCases(args) {
|
|
21
|
+
const deps = { ...defaultContextWindowScalingDependencies, ...args.dependencies };
|
|
22
|
+
const results = [];
|
|
23
|
+
for (const evaluationCase of args.cases) {
|
|
24
|
+
const treatments = [];
|
|
25
|
+
for (const variantId of CONTEXT_WINDOW_SCALING_TREATMENT_IDS) {
|
|
26
|
+
treatments.push(await executeTreatment({ ...args, evaluationCase, variantId, deps }));
|
|
27
|
+
}
|
|
28
|
+
results.push({
|
|
29
|
+
caseId: evaluationCase.id,
|
|
30
|
+
caseName: evaluationCase.title,
|
|
31
|
+
benchmarkProject: evaluationCase.benchmarkProject,
|
|
32
|
+
targetRoot: evaluationCase.targetRoot,
|
|
33
|
+
taskLocality: evaluationCase.taskLocality ?? null,
|
|
34
|
+
treatments,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return results;
|
|
38
|
+
}
|
|
39
|
+
async function executeTreatment(args) {
|
|
40
|
+
const { evaluationCase, variantId, deps } = args;
|
|
41
|
+
const constructed = await constructContext(args);
|
|
42
|
+
const tokens = constructed.context.estimatedTokens;
|
|
43
|
+
const expectedFiles = evaluationCase.answerKey?.expectedFiles ?? evaluationCase.expectedFiles;
|
|
44
|
+
const relevantFileEvidence = computeRelevantFileEvidence({
|
|
45
|
+
expectedFiles,
|
|
46
|
+
observedFiles: constructed.context.observedFiles,
|
|
47
|
+
});
|
|
48
|
+
let evaluation;
|
|
49
|
+
const anyFits = tokens !== null && args.contextBudgets.some((budget) => tokens <= budget);
|
|
50
|
+
if (tokens === null) {
|
|
51
|
+
evaluation = emptyEvaluation("unavailable", "Treatment context is unavailable.");
|
|
52
|
+
}
|
|
53
|
+
else if (!anyFits) {
|
|
54
|
+
evaluation = emptyEvaluation("not-evaluated-no-fitting-budget", "The context is too large for every selected budget.");
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
evaluation = await evaluateOnce(args, deps);
|
|
58
|
+
}
|
|
59
|
+
const budgetCells = args.contextBudgets.map((contextBudgetTokens) => buildBudgetCell({
|
|
60
|
+
contextBudgetTokens,
|
|
61
|
+
contextEstimatedTokens: tokens,
|
|
62
|
+
shared: evaluation.status === "evaluated" || evaluation.status === "unavailable" ? evaluation.correctness : null,
|
|
63
|
+
}));
|
|
64
|
+
return {
|
|
65
|
+
variantId,
|
|
66
|
+
status: treatmentStatus(constructed, budgetCells.map((cell) => cell.contextFitStatus === "fits" && cell.evaluationStatus === "unavailable")),
|
|
67
|
+
context: constructed.context,
|
|
68
|
+
evaluation,
|
|
69
|
+
relevantFileEvidence,
|
|
70
|
+
budgetCells,
|
|
71
|
+
errors: constructed.error ? [constructed.error] : [],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async function evaluateOnce(args, deps) {
|
|
75
|
+
try {
|
|
76
|
+
const result = await deps.evaluateTreatment({
|
|
77
|
+
evaluationCase: args.evaluationCase,
|
|
78
|
+
treatment: args.variantId,
|
|
79
|
+
projectProfiles: args.projectProfiles,
|
|
80
|
+
outputRoot: args.outputRoot,
|
|
81
|
+
cwd: args.cwd,
|
|
82
|
+
env: args.env,
|
|
83
|
+
});
|
|
84
|
+
const available = result.correctness.availability === "available";
|
|
85
|
+
return {
|
|
86
|
+
status: available ? "evaluated" : "unavailable",
|
|
87
|
+
agentId: result.agentId,
|
|
88
|
+
agentStatus: result.agentStatus,
|
|
89
|
+
evaluationCount: 1,
|
|
90
|
+
correctness: result.correctness,
|
|
91
|
+
failureReasons: result.failureReasons,
|
|
92
|
+
warnings: [...result.warnings, ...result.errors],
|
|
93
|
+
reason: available ? null : `Deterministic evaluation was not scoreable (agent status ${result.agentStatus}).`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return {
|
|
98
|
+
...emptyEvaluation("unavailable", error instanceof Error ? error.message : String(error)),
|
|
99
|
+
evaluationCount: 1,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function emptyEvaluation(status, reason) {
|
|
104
|
+
return {
|
|
105
|
+
status,
|
|
106
|
+
agentId: null,
|
|
107
|
+
agentStatus: null,
|
|
108
|
+
evaluationCount: 0,
|
|
109
|
+
correctness: { ...UNAVAILABLE_CORRECTNESS },
|
|
110
|
+
failureReasons: [],
|
|
111
|
+
warnings: [],
|
|
112
|
+
reason,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function treatmentStatus(constructed, fittingCellUnavailable) {
|
|
116
|
+
if (constructed.error)
|
|
117
|
+
return "failed";
|
|
118
|
+
if (constructed.skipped)
|
|
119
|
+
return "skipped";
|
|
120
|
+
return fittingCellUnavailable.some(Boolean) ? "partial" : "completed";
|
|
121
|
+
}
|
|
122
|
+
async function constructContext(args) {
|
|
123
|
+
const { evaluationCase, variantId, deps } = args;
|
|
124
|
+
try {
|
|
125
|
+
if (variantId === "raw-full-file") {
|
|
126
|
+
const raw = await deps.constructRawContext(evaluationCase);
|
|
127
|
+
return {
|
|
128
|
+
skipped: false,
|
|
129
|
+
error: null,
|
|
130
|
+
context: {
|
|
131
|
+
status: "available",
|
|
132
|
+
characterCount: raw.totalChars,
|
|
133
|
+
estimatedTokens: raw.totalEstimatedTokens,
|
|
134
|
+
tokenCountMethod: raw.tokenCountMethod,
|
|
135
|
+
observedFiles: [...raw.filesIncluded],
|
|
136
|
+
warnings: [],
|
|
137
|
+
reason: null,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const guided = await deps.constructGuidedContext({
|
|
142
|
+
evaluationCase,
|
|
143
|
+
kitCommand: args.kitCommand,
|
|
144
|
+
outputDir: path.join(args.outputRoot, "guided", taskOutputSegment(evaluationCase.id)),
|
|
145
|
+
});
|
|
146
|
+
if (guided.skipped) {
|
|
147
|
+
return {
|
|
148
|
+
skipped: true,
|
|
149
|
+
error: null,
|
|
150
|
+
context: unavailableContext(guided.warnings, "my-dev-kit-guided retrieval was skipped and produced no context."),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
skipped: false,
|
|
155
|
+
error: null,
|
|
156
|
+
context: {
|
|
157
|
+
status: "available",
|
|
158
|
+
characterCount: guided.totalChars,
|
|
159
|
+
estimatedTokens: guided.totalEstimatedTokens,
|
|
160
|
+
tokenCountMethod: guided.tokenCountMethod,
|
|
161
|
+
observedFiles: [...guided.filesRead],
|
|
162
|
+
warnings: [...guided.warnings],
|
|
163
|
+
reason: null,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
169
|
+
return {
|
|
170
|
+
skipped: false,
|
|
171
|
+
error: { code: "context-construction-failed", message },
|
|
172
|
+
context: unavailableContext([], message),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function unavailableContext(warnings, reason) {
|
|
177
|
+
return {
|
|
178
|
+
status: "unavailable",
|
|
179
|
+
characterCount: null,
|
|
180
|
+
estimatedTokens: null,
|
|
181
|
+
tokenCountMethod: null,
|
|
182
|
+
observedFiles: null,
|
|
183
|
+
warnings: [...warnings],
|
|
184
|
+
reason,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
export { tokenCountMethod as CONTEXT_WINDOW_SCALING_TOKEN_COUNT_METHOD };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const CONTEXT_WINDOW_SCALING_EXECUTION_ARTIFACT_FILE = "context-window-scaling-execution.json";
|
|
2
|
+
export const CONTEXT_WINDOW_SCALING_EXECUTION_SCHEMA_VERSION = "my-dev-kit-lab-context-window-scaling-execution-v1";
|
|
3
|
+
export function buildContextWindowScalingExecutionArtifact(args) {
|
|
4
|
+
return {
|
|
5
|
+
schemaVersion: CONTEXT_WINDOW_SCALING_EXECUTION_SCHEMA_VERSION,
|
|
6
|
+
runId: args.runId,
|
|
7
|
+
pluginId: args.pluginId,
|
|
8
|
+
pluginSchemaVersion: args.pluginSchemaVersion,
|
|
9
|
+
startedAt: args.startedAt,
|
|
10
|
+
completedAt: args.completedAt,
|
|
11
|
+
estimator: { tokenCountMethod: args.tokenCountMethod },
|
|
12
|
+
contextBudgets: [...args.contextBudgets],
|
|
13
|
+
cases: structuredClone([...args.cases]),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { validateContextBudgets } from "./config.js";
|
|
2
|
+
import { CONTEXT_WINDOW_SCALING_EXECUTION_SCHEMA_VERSION, } from "./executionArtifact.js";
|
|
3
|
+
import { CONTEXT_WINDOW_SCALING_PLUGIN_ID, CONTEXT_WINDOW_SCALING_TREATMENT_IDS } from "./metadata.js";
|
|
4
|
+
const MAX_REPORTED_PROBLEMS = 8;
|
|
5
|
+
const RUN_STATUSES = ["completed", "partial", "failed", "skipped"];
|
|
6
|
+
const AVAILABILITY = ["available", "unavailable"];
|
|
7
|
+
const EVALUATION_STATUSES = ["evaluated", "not-evaluated-no-fitting-budget", "unavailable"];
|
|
8
|
+
const RELEVANT_STATUSES = ["available", "unavailable", "not-applicable"];
|
|
9
|
+
const FIT_STATUSES = ["fits", "context-too-large", "unavailable"];
|
|
10
|
+
const CELL_EVALUATION_STATUSES = ["evaluated", "not-evaluated-context-too-large", "unavailable"];
|
|
11
|
+
const SUCCESS_REASONS = ["correctness-pass", "correctness-fail", "context-too-large", "evaluation-unavailable", "context-unavailable"];
|
|
12
|
+
const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
13
|
+
const isStr = (v) => typeof v === "string";
|
|
14
|
+
const isStrOrNull = (v) => v === null || typeof v === "string";
|
|
15
|
+
const isCount = (v) => typeof v === "number" && Number.isSafeInteger(v) && v >= 0;
|
|
16
|
+
const isCountOrNull = (v) => v === null || isCount(v);
|
|
17
|
+
const isNumOrNull = (v) => v === null || (typeof v === "number" && Number.isFinite(v));
|
|
18
|
+
const isStrArray = (v) => Array.isArray(v) && v.every((item) => typeof item === "string");
|
|
19
|
+
const isOneOf = (v, allowed) => typeof v === "string" && allowed.includes(v);
|
|
20
|
+
/**
|
|
21
|
+
* Structural validator for the persisted V1 execution artifact. It checks only what aggregation and
|
|
22
|
+
* plotting need (closed enums, types, budget/cell agreement); it never repairs or coerces values.
|
|
23
|
+
* Throws one Error listing bounded problems; returns the input, typed, when valid.
|
|
24
|
+
*/
|
|
25
|
+
export function parseContextWindowScalingExecutionArtifact(value) {
|
|
26
|
+
if (!isObj(value)) {
|
|
27
|
+
throw new Error("Invalid context-window-scaling execution artifact: expected a JSON object.");
|
|
28
|
+
}
|
|
29
|
+
if (value.schemaVersion !== CONTEXT_WINDOW_SCALING_EXECUTION_SCHEMA_VERSION) {
|
|
30
|
+
throw new Error(`Invalid context-window-scaling execution artifact: unsupported schemaVersion ${JSON.stringify(value.schemaVersion)}; expected ${CONTEXT_WINDOW_SCALING_EXECUTION_SCHEMA_VERSION}.`);
|
|
31
|
+
}
|
|
32
|
+
const problems = [];
|
|
33
|
+
const fail = (message) => {
|
|
34
|
+
problems.push(message);
|
|
35
|
+
};
|
|
36
|
+
const checkCorrectness = (correctness, at) => {
|
|
37
|
+
if (!isObj(correctness) ||
|
|
38
|
+
!isOneOf(correctness.availability, AVAILABILITY) ||
|
|
39
|
+
!isNumOrNull(correctness.score) ||
|
|
40
|
+
!(correctness.pass === null || typeof correctness.pass === "boolean")) {
|
|
41
|
+
fail(`${at} is malformed.`);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
for (const field of ["runId", "pluginSchemaVersion", "startedAt", "completedAt"]) {
|
|
45
|
+
if (!isStr(value[field]))
|
|
46
|
+
fail(`${field} must be a string.`);
|
|
47
|
+
}
|
|
48
|
+
if (value.pluginId !== CONTEXT_WINDOW_SCALING_PLUGIN_ID)
|
|
49
|
+
fail(`pluginId must be ${CONTEXT_WINDOW_SCALING_PLUGIN_ID}.`);
|
|
50
|
+
if (!isObj(value.estimator) || !isStr(value.estimator.tokenCountMethod))
|
|
51
|
+
fail("estimator.tokenCountMethod must be a string.");
|
|
52
|
+
let budgets = [];
|
|
53
|
+
const budgetCheck = validateContextBudgets(value.contextBudgets);
|
|
54
|
+
if (budgetCheck.errors.length > 0) {
|
|
55
|
+
fail(`contextBudgets: ${budgetCheck.errors.join(" ")}`);
|
|
56
|
+
}
|
|
57
|
+
else if (budgetCheck.budgets.some((budget, index) => budget !== value.contextBudgets[index])) {
|
|
58
|
+
fail("contextBudgets must be in ascending order.");
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
budgets = budgetCheck.budgets;
|
|
62
|
+
}
|
|
63
|
+
const cases = value.cases;
|
|
64
|
+
if (!Array.isArray(cases) || cases.length === 0) {
|
|
65
|
+
fail("cases must be a non-empty array.");
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
cases.forEach((caseEvidence, caseIndex) => {
|
|
69
|
+
const at = `cases[${caseIndex}]`;
|
|
70
|
+
if (!isObj(caseEvidence))
|
|
71
|
+
return fail(`${at} must be an object.`);
|
|
72
|
+
for (const field of ["caseId", "caseName", "benchmarkProject", "targetRoot"]) {
|
|
73
|
+
if (!isStr(caseEvidence[field]))
|
|
74
|
+
fail(`${at}.${field} must be a string.`);
|
|
75
|
+
}
|
|
76
|
+
if (!isStrOrNull(caseEvidence.taskLocality))
|
|
77
|
+
fail(`${at}.taskLocality must be a string or null.`);
|
|
78
|
+
const treatments = caseEvidence.treatments;
|
|
79
|
+
if (!Array.isArray(treatments))
|
|
80
|
+
return fail(`${at}.treatments must be an array.`);
|
|
81
|
+
const ids = treatments.map((t) => (isObj(t) ? t.variantId : undefined));
|
|
82
|
+
if (ids.length !== CONTEXT_WINDOW_SCALING_TREATMENT_IDS.length ||
|
|
83
|
+
CONTEXT_WINDOW_SCALING_TREATMENT_IDS.some((id) => ids.filter((x) => x === id).length !== 1)) {
|
|
84
|
+
fail(`${at}.treatments must contain exactly ${CONTEXT_WINDOW_SCALING_TREATMENT_IDS.join(" and ")}.`);
|
|
85
|
+
}
|
|
86
|
+
treatments.forEach((treatment, treatmentIndex) => {
|
|
87
|
+
const tat = `${at}.treatments[${treatmentIndex}]`;
|
|
88
|
+
if (!isObj(treatment))
|
|
89
|
+
return fail(`${tat} must be an object.`);
|
|
90
|
+
if (!isOneOf(treatment.status, RUN_STATUSES))
|
|
91
|
+
fail(`${tat}.status is not a known status.`);
|
|
92
|
+
const context = treatment.context;
|
|
93
|
+
if (!isObj(context)) {
|
|
94
|
+
fail(`${tat}.context must be an object.`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
if (!isOneOf(context.status, AVAILABILITY))
|
|
98
|
+
fail(`${tat}.context.status is not a known status.`);
|
|
99
|
+
if (!isCountOrNull(context.characterCount) || !isCountOrNull(context.estimatedTokens)) {
|
|
100
|
+
fail(`${tat}.context counts must be nonnegative integers or null.`);
|
|
101
|
+
}
|
|
102
|
+
if (!isStrOrNull(context.tokenCountMethod) || !isStrOrNull(context.reason))
|
|
103
|
+
fail(`${tat}.context strings must be strings or null.`);
|
|
104
|
+
if (!(context.observedFiles === null || isStrArray(context.observedFiles)) || !isStrArray(context.warnings)) {
|
|
105
|
+
fail(`${tat}.context file/warning lists are malformed.`);
|
|
106
|
+
}
|
|
107
|
+
if (context.status === "available" && context.estimatedTokens === null)
|
|
108
|
+
fail(`${tat}.context is available without estimatedTokens.`);
|
|
109
|
+
}
|
|
110
|
+
const evaluation = treatment.evaluation;
|
|
111
|
+
if (!isObj(evaluation)) {
|
|
112
|
+
fail(`${tat}.evaluation must be an object.`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
if (!isOneOf(evaluation.status, EVALUATION_STATUSES))
|
|
116
|
+
fail(`${tat}.evaluation.status is not a known status.`);
|
|
117
|
+
if (!(evaluation.agentId === null || evaluation.agentId === "fake-agent"))
|
|
118
|
+
fail(`${tat}.evaluation.agentId must be fake-agent or null.`);
|
|
119
|
+
if (!isStrOrNull(evaluation.agentStatus) || !isStrOrNull(evaluation.reason))
|
|
120
|
+
fail(`${tat}.evaluation strings must be strings or null.`);
|
|
121
|
+
if (!isCount(evaluation.evaluationCount))
|
|
122
|
+
fail(`${tat}.evaluation.evaluationCount must be a nonnegative integer.`);
|
|
123
|
+
if (!isStrArray(evaluation.failureReasons) || !isStrArray(evaluation.warnings))
|
|
124
|
+
fail(`${tat}.evaluation lists must be string arrays.`);
|
|
125
|
+
checkCorrectness(evaluation.correctness, `${tat}.evaluation.correctness`);
|
|
126
|
+
}
|
|
127
|
+
const relevant = treatment.relevantFileEvidence;
|
|
128
|
+
if (!isObj(relevant)) {
|
|
129
|
+
fail(`${tat}.relevantFileEvidence must be an object.`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
if (!isOneOf(relevant.status, RELEVANT_STATUSES))
|
|
133
|
+
fail(`${tat}.relevantFileEvidence.status is not a known status.`);
|
|
134
|
+
if (!isStrArray(relevant.expectedRelevantFiles) || !isStrArray(relevant.omittedRelevantFiles)) {
|
|
135
|
+
fail(`${tat}.relevantFileEvidence file lists must be string arrays.`);
|
|
136
|
+
}
|
|
137
|
+
if (!isCount(relevant.expectedRelevantFileCount))
|
|
138
|
+
fail(`${tat}.relevantFileEvidence.expectedRelevantFileCount must be a nonnegative integer.`);
|
|
139
|
+
if (!isCountOrNull(relevant.observedExpectedFileCount) || !isCountOrNull(relevant.omittedRelevantFileCount)) {
|
|
140
|
+
fail(`${tat}.relevantFileEvidence counts must be nonnegative integers or null.`);
|
|
141
|
+
}
|
|
142
|
+
if (!isStrOrNull(relevant.reason))
|
|
143
|
+
fail(`${tat}.relevantFileEvidence.reason must be a string or null.`);
|
|
144
|
+
}
|
|
145
|
+
const cells = treatment.budgetCells;
|
|
146
|
+
if (!Array.isArray(cells)) {
|
|
147
|
+
fail(`${tat}.budgetCells must be an array.`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
const cellBudgets = cells.map((cell) => (isObj(cell) ? cell.contextBudgetTokens : undefined));
|
|
151
|
+
if (budgets.length > 0 && (cells.length !== budgets.length || budgets.some((b) => cellBudgets.filter((x) => x === b).length !== 1))) {
|
|
152
|
+
fail(`${tat}.budgetCells do not match contextBudgets.`);
|
|
153
|
+
}
|
|
154
|
+
cells.forEach((cell, cellIndex) => {
|
|
155
|
+
const cat = `${tat}.budgetCells[${cellIndex}]`;
|
|
156
|
+
if (!isObj(cell))
|
|
157
|
+
return fail(`${cat} must be an object.`);
|
|
158
|
+
if (!isOneOf(cell.contextFitStatus, FIT_STATUSES))
|
|
159
|
+
fail(`${cat}.contextFitStatus is not a known status.`);
|
|
160
|
+
if (!isNumOrNull(cell.contextBudgetUtilizationPercent))
|
|
161
|
+
fail(`${cat}.contextBudgetUtilizationPercent must be a number or null.`);
|
|
162
|
+
if (!isOneOf(cell.evaluationStatus, CELL_EVALUATION_STATUSES))
|
|
163
|
+
fail(`${cat}.evaluationStatus is not a known status.`);
|
|
164
|
+
checkCorrectness(cell.correctness, `${cat}.correctness`);
|
|
165
|
+
const success = cell.successEvidence;
|
|
166
|
+
if (!isObj(success) ||
|
|
167
|
+
!isOneOf(success.status, AVAILABILITY) ||
|
|
168
|
+
!(success.success === null || typeof success.success === "boolean") ||
|
|
169
|
+
!isOneOf(success.reason, SUCCESS_REASONS)) {
|
|
170
|
+
fail(`${cat}.successEvidence is malformed.`);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (!Array.isArray(treatment.errors) || !treatment.errors.every((e) => isObj(e) && isStr(e.code) && isStr(e.message))) {
|
|
175
|
+
fail(`${tat}.errors must be an array of { code, message }.`);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (problems.length > 0) {
|
|
181
|
+
const shown = problems.slice(0, MAX_REPORTED_PROBLEMS);
|
|
182
|
+
const extra = problems.length - shown.length;
|
|
183
|
+
throw new Error(`Invalid context-window-scaling execution artifact: ${shown.join(" ")}${extra > 0 ? ` (${extra} more problem(s) omitted.)` : ""}`);
|
|
184
|
+
}
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./config.js";
|
|
2
|
+
export * from "./cliBudgets.js";
|
|
3
|
+
export * from "./contextBudget.js";
|
|
4
|
+
export * from "./evaluation.js";
|
|
5
|
+
export * from "./execution.js";
|
|
6
|
+
export * from "./executionArtifact.js";
|
|
7
|
+
export * from "./executionArtifactReader.js";
|
|
8
|
+
export * from "./metadata.js";
|
|
9
|
+
export * from "./metrics.js";
|
|
10
|
+
export * from "./plugin.js";
|
|
11
|
+
export * from "./projectProfile.js";
|
|
12
|
+
export * from "./relevantFiles.js";
|
|
13
|
+
export * from "./successEvidence.js";
|
|
14
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const CONTEXT_WINDOW_SCALING_PLUGIN_ID = "context-window-scaling";
|
|
2
|
+
/** Stable strategy IDs shared with existing plugins; budget is never part of variant identity. */
|
|
3
|
+
export const CONTEXT_WINDOW_SCALING_TREATMENT_IDS = ["raw-full-file", "my-dev-kit-guided"];
|
|
4
|
+
export const contextWindowScalingMetadata = {
|
|
5
|
+
id: CONTEXT_WINDOW_SCALING_PLUGIN_ID,
|
|
6
|
+
name: "Context Window Scaling",
|
|
7
|
+
description: "Measure raw-full-file and my-dev-kit-guided strategies under increasing deterministic estimated-context-token budgets.",
|
|
8
|
+
schemaVersion: "1.0.0",
|
|
9
|
+
status: "experimental",
|
|
10
|
+
supportedTargets: ["self"],
|
|
11
|
+
supportedOutputs: ["json", "text", "html", "plot"],
|
|
12
|
+
};
|