@principles/core 1.242.0 → 1.244.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/dist/runtime-v2/feature-flags/__tests__/context-manifest-budget-flag.test.d.ts +12 -0
- package/dist/runtime-v2/feature-flags/__tests__/context-manifest-budget-flag.test.d.ts.map +1 -0
- package/dist/runtime-v2/feature-flags/__tests__/context-manifest-budget-flag.test.js +114 -0
- package/dist/runtime-v2/feature-flags/__tests__/context-manifest-budget-flag.test.js.map +1 -0
- package/dist/runtime-v2/feature-flags/__tests__/progressive-evaluator-flag.test.d.ts +8 -0
- package/dist/runtime-v2/feature-flags/__tests__/progressive-evaluator-flag.test.d.ts.map +1 -0
- package/dist/runtime-v2/feature-flags/__tests__/progressive-evaluator-flag.test.js +56 -0
- package/dist/runtime-v2/feature-flags/__tests__/progressive-evaluator-flag.test.js.map +1 -0
- package/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
- package/dist/runtime-v2/feature-flags/feature-flag-contract.js +14 -0
- package/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
- package/dist/runtime-v2/index.d.ts +2 -0
- package/dist/runtime-v2/index.d.ts.map +1 -1
- package/dist/runtime-v2/index.js +2 -0
- package/dist/runtime-v2/index.js.map +1 -1
- package/dist/runtime-v2/internalization/__tests__/context-manifest.property.test.d.ts +12 -0
- package/dist/runtime-v2/internalization/__tests__/context-manifest.property.test.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/context-manifest.property.test.js +176 -0
- package/dist/runtime-v2/internalization/__tests__/context-manifest.property.test.js.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/progressive-evaluator.property.test.d.ts +11 -0
- package/dist/runtime-v2/internalization/__tests__/progressive-evaluator.property.test.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/progressive-evaluator.property.test.js +154 -0
- package/dist/runtime-v2/internalization/__tests__/progressive-evaluator.property.test.js.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/prompt-budget-manager.property.test.d.ts +12 -0
- package/dist/runtime-v2/internalization/__tests__/prompt-budget-manager.property.test.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/prompt-budget-manager.property.test.js +254 -0
- package/dist/runtime-v2/internalization/__tests__/prompt-budget-manager.property.test.js.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/resolve-injection.property.test.d.ts +15 -0
- package/dist/runtime-v2/internalization/__tests__/resolve-injection.property.test.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/__tests__/resolve-injection.property.test.js +150 -0
- package/dist/runtime-v2/internalization/__tests__/resolve-injection.property.test.js.map +1 -0
- package/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/artificer-runner.js +12 -0
- package/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
- package/dist/runtime-v2/internalization/context-manifest.d.ts +117 -0
- package/dist/runtime-v2/internalization/context-manifest.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/context-manifest.js +156 -0
- package/dist/runtime-v2/internalization/context-manifest.js.map +1 -0
- package/dist/runtime-v2/internalization/context-manifests.d.ts +74 -0
- package/dist/runtime-v2/internalization/context-manifests.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/context-manifests.js +192 -0
- package/dist/runtime-v2/internalization/context-manifests.js.map +1 -0
- package/dist/runtime-v2/internalization/dimension-coverage-policy.d.ts +54 -0
- package/dist/runtime-v2/internalization/dimension-coverage-policy.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/dimension-coverage-policy.js +70 -0
- package/dist/runtime-v2/internalization/dimension-coverage-policy.js.map +1 -0
- package/dist/runtime-v2/internalization/dreamer-runner.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/dreamer-runner.js +13 -1
- package/dist/runtime-v2/internalization/dreamer-runner.js.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-output.d.ts +26 -0
- package/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-output.js +7 -1
- package/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-runner.js +13 -0
- package/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
- package/dist/runtime-v2/internalization/index.d.ts +2 -0
- package/dist/runtime-v2/internalization/index.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/index.js +2 -0
- package/dist/runtime-v2/internalization/index.js.map +1 -1
- package/dist/runtime-v2/internalization/progressive-evaluator.d.ts +115 -0
- package/dist/runtime-v2/internalization/progressive-evaluator.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/progressive-evaluator.js +248 -0
- package/dist/runtime-v2/internalization/progressive-evaluator.js.map +1 -0
- package/dist/runtime-v2/internalization/prompt-budget-manager.d.ts +90 -0
- package/dist/runtime-v2/internalization/prompt-budget-manager.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/prompt-budget-manager.js +149 -0
- package/dist/runtime-v2/internalization/prompt-budget-manager.js.map +1 -0
- package/dist/runtime-v2/internalization/resolve-injection.d.ts +62 -0
- package/dist/runtime-v2/internalization/resolve-injection.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/resolve-injection.js +78 -0
- package/dist/runtime-v2/internalization/resolve-injection.js.map +1 -0
- package/dist/runtime-v2/internalization/scribe-runner.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/scribe-runner.js +10 -0
- package/dist/runtime-v2/internalization/scribe-runner.js.map +1 -1
- package/dist/runtime-v2/internalization/summary-field-reader.d.ts +38 -0
- package/dist/runtime-v2/internalization/summary-field-reader.d.ts.map +1 -0
- package/dist/runtime-v2/internalization/summary-field-reader.js +108 -0
- package/dist/runtime-v2/internalization/summary-field-reader.js.map +1 -0
- package/dist/runtime-v2/runner/base-peer-runner.d.ts +36 -0
- package/dist/runtime-v2/runner/base-peer-runner.d.ts.map +1 -1
- package/dist/runtime-v2/runner/base-peer-runner.js +71 -0
- package/dist/runtime-v2/runner/base-peer-runner.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 2 — Progressive Evaluator: two-stage evaluation with flagged criteria
|
|
3
|
+
* (design §6.5).
|
|
4
|
+
*
|
|
5
|
+
* Pure logic only (Core vs Plugin boundary, `antipattern-core-io`).
|
|
6
|
+
*
|
|
7
|
+
* The progressive evaluator runs Stage 1 (summary-level context) first; only
|
|
8
|
+
* when flagged / undetermined / forced-sample does it trigger Stage 2 (tier2
|
|
9
|
+
* full-contentJson re-evaluation). This keeps daily cost low while enabling
|
|
10
|
+
* deep diagnosis on demand.
|
|
11
|
+
*
|
|
12
|
+
* Key invariants:
|
|
13
|
+
* - Stage 2 output is INDEPENDENT — never merged with Stage 1 (rc-7 /
|
|
14
|
+
* ERR-015 / ERR-018 / ERR-019). `stagesRun === 2` ⟹ `finalOutput` is
|
|
15
|
+
* entirely the Stage 2 result.
|
|
16
|
+
* - flagged criteria read DIMENSION_COVERAGE_POLICY (single source of truth),
|
|
17
|
+
* never inline a dimension-name array. Untrusted LLM input is filtered by
|
|
18
|
+
* the policy table before flagging (rc-1 / rc-4).
|
|
19
|
+
* - Deterministic forced sampling via fnv1a32 (no Math.random, design §4.4).
|
|
20
|
+
*/
|
|
21
|
+
export declare const IMPLEMENTATION_FIDELITY_THRESHOLD = 0.7;
|
|
22
|
+
export declare const FORCED_STAGE2_SAMPLE_MODULUS = 20;
|
|
23
|
+
export type FlaggedReasonCode = 'missing_dimensions' | 'pain_not_fully_covered' | 'implementation_fidelity_below_threshold';
|
|
24
|
+
export interface FlaggedDecision {
|
|
25
|
+
readonly flagged: boolean;
|
|
26
|
+
readonly reasons: readonly FlaggedReasonCode[];
|
|
27
|
+
/** Fields that could not be determined (missing/malformed) — rc-3 + rc-9. */
|
|
28
|
+
readonly undetermined: readonly string[];
|
|
29
|
+
}
|
|
30
|
+
export interface ProgressiveEvaluationOutcome {
|
|
31
|
+
/** Stage 2 ran → entirely Stage 2's result; never merged with Stage 1. */
|
|
32
|
+
readonly finalOutput: unknown;
|
|
33
|
+
readonly stagesRun: 1 | 2;
|
|
34
|
+
readonly stage1Decision: FlaggedDecision;
|
|
35
|
+
readonly forcedStage2: boolean;
|
|
36
|
+
readonly stage1FalseNegative?: {
|
|
37
|
+
readonly newConcernKeys: readonly string[];
|
|
38
|
+
};
|
|
39
|
+
readonly stage2Aborted?: {
|
|
40
|
+
readonly reason: 'lineage_error';
|
|
41
|
+
readonly detail: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* FNV-1a 32-bit hash. Pure, deterministic, no crypto, no Math.random.
|
|
46
|
+
* Supports the full Unicode range in the input string.
|
|
47
|
+
*/
|
|
48
|
+
export declare function fnv1a32(input: string): number;
|
|
49
|
+
/**
|
|
50
|
+
* Deterministic ~5% forced Stage 2 sampling. `fnv1a32(taskId) % modulus === 0`.
|
|
51
|
+
* Never uses Math.random or any non-deterministic source (design §4.4).
|
|
52
|
+
*/
|
|
53
|
+
export declare function isForcedStage2(taskId: string, modulus?: number): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Evaluate the three flagged criteria against Stage 1 output (design §6.5.3).
|
|
56
|
+
*
|
|
57
|
+
* Preconditions: none — `stage1Output` is untrusted LLM output (rc-1), read
|
|
58
|
+
* via `Object.hasOwn` (rc-5 / ERR-013).
|
|
59
|
+
*
|
|
60
|
+
* Postconditions:
|
|
61
|
+
* - `flagged === true` iff `reasons` is non-empty.
|
|
62
|
+
* - Three criteria: required-dimension missing, painCoverage.fullyCovered === false,
|
|
63
|
+
* implementationFidelity.score < 0.7.
|
|
64
|
+
* - Fields missing or wrong type → `undetermined` (rc-3: fail loud, never
|
|
65
|
+
* silently pass).
|
|
66
|
+
*
|
|
67
|
+
* Dimension criterion (§6.5.3, measurement-driven tightening):
|
|
68
|
+
* - Only **required** dimension names in `missingDimensions` count. The LLM
|
|
69
|
+
* may stuff optional/excluded/unknown strings in — all filtered out by
|
|
70
|
+
* `isRequiredDimension` before checking. `optionalUncovered` never enters
|
|
71
|
+
* `reasons`.
|
|
72
|
+
*/
|
|
73
|
+
export declare function evaluateFlaggedCriteria(stage1Output: unknown): FlaggedDecision;
|
|
74
|
+
/**
|
|
75
|
+
* LLM evaluator callback type. The caller injects the actual LLM invocation;
|
|
76
|
+
* this module is pure logic and never calls an LLM directly.
|
|
77
|
+
*/
|
|
78
|
+
export interface ProgressiveEvaluatorLLM {
|
|
79
|
+
/** Evaluate using the provided context fields. Returns the raw LLM output (unknown). */
|
|
80
|
+
evaluate(fields: Readonly<Record<string, string>>): Promise<unknown>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Lineage resolver type (CandidateLineage from Layer 2, injected by caller).
|
|
84
|
+
*/
|
|
85
|
+
export interface ProgressiveEvaluatorLineage {
|
|
86
|
+
resolve(startArtifactId: string): Promise<{
|
|
87
|
+
readonly ok: true;
|
|
88
|
+
readonly value: {
|
|
89
|
+
readonly nodes: readonly unknown[];
|
|
90
|
+
};
|
|
91
|
+
} | {
|
|
92
|
+
readonly ok: false;
|
|
93
|
+
readonly error: {
|
|
94
|
+
readonly kind: string;
|
|
95
|
+
};
|
|
96
|
+
}>;
|
|
97
|
+
}
|
|
98
|
+
export interface ProgressiveEvaluatorDeps {
|
|
99
|
+
readonly taskId: string;
|
|
100
|
+
readonly startArtifactId: string;
|
|
101
|
+
readonly stage1Context: Readonly<Record<string, string>>;
|
|
102
|
+
readonly stage2Context?: Readonly<Record<string, string>>;
|
|
103
|
+
readonly llm: ProgressiveEvaluatorLLM;
|
|
104
|
+
readonly lineage?: ProgressiveEvaluatorLineage;
|
|
105
|
+
readonly emit?: (event: ProgressiveEvaluatorEvent) => void;
|
|
106
|
+
}
|
|
107
|
+
export type ProgressiveEvaluatorEvent = {
|
|
108
|
+
readonly type: 'lineage_data_corrupt';
|
|
109
|
+
readonly detail: string;
|
|
110
|
+
} | {
|
|
111
|
+
readonly type: 'stage1_false_negative';
|
|
112
|
+
readonly newConcernKeys: readonly string[];
|
|
113
|
+
};
|
|
114
|
+
export declare function runProgressiveEvaluation(deps: ProgressiveEvaluatorDeps): Promise<ProgressiveEvaluationOutcome>;
|
|
115
|
+
//# sourceMappingURL=progressive-evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progressive-evaluator.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/progressive-evaluator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 2 — Progressive Evaluator: two-stage evaluation with flagged criteria
|
|
3
|
+
* (design §6.5).
|
|
4
|
+
*
|
|
5
|
+
* Pure logic only (Core vs Plugin boundary, `antipattern-core-io`).
|
|
6
|
+
*
|
|
7
|
+
* The progressive evaluator runs Stage 1 (summary-level context) first; only
|
|
8
|
+
* when flagged / undetermined / forced-sample does it trigger Stage 2 (tier2
|
|
9
|
+
* full-contentJson re-evaluation). This keeps daily cost low while enabling
|
|
10
|
+
* deep diagnosis on demand.
|
|
11
|
+
*
|
|
12
|
+
* Key invariants:
|
|
13
|
+
* - Stage 2 output is INDEPENDENT — never merged with Stage 1 (rc-7 /
|
|
14
|
+
* ERR-015 / ERR-018 / ERR-019). `stagesRun === 2` ⟹ `finalOutput` is
|
|
15
|
+
* entirely the Stage 2 result.
|
|
16
|
+
* - flagged criteria read DIMENSION_COVERAGE_POLICY (single source of truth),
|
|
17
|
+
* never inline a dimension-name array. Untrusted LLM input is filtered by
|
|
18
|
+
* the policy table before flagging (rc-1 / rc-4).
|
|
19
|
+
* - Deterministic forced sampling via fnv1a32 (no Math.random, design §4.4).
|
|
20
|
+
*/
|
|
21
|
+
import { isRequiredDimension } from './dimension-coverage-policy.js';
|
|
22
|
+
// ── Constants ────────────────────────────────────────────────────────────────
|
|
23
|
+
export const IMPLEMENTATION_FIDELITY_THRESHOLD = 0.7;
|
|
24
|
+
export const FORCED_STAGE2_SAMPLE_MODULUS = 20; // ~5%
|
|
25
|
+
// ── Runtime guards (rc-1 / rc-2 / rc-5) ──────────────────────────────────────
|
|
26
|
+
function isRecord(value) {
|
|
27
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
28
|
+
}
|
|
29
|
+
function readNumber(source, key) {
|
|
30
|
+
if (!isRecord(source) || !Object.hasOwn(source, key))
|
|
31
|
+
return null;
|
|
32
|
+
const v = source[key];
|
|
33
|
+
return typeof v === 'number' && Number.isFinite(v) ? v : null;
|
|
34
|
+
}
|
|
35
|
+
function readBoolean(source, key) {
|
|
36
|
+
if (!isRecord(source) || !Object.hasOwn(source, key))
|
|
37
|
+
return null;
|
|
38
|
+
const v = source[key];
|
|
39
|
+
return typeof v === 'boolean' ? v : null;
|
|
40
|
+
}
|
|
41
|
+
function readStringArray(source, key) {
|
|
42
|
+
if (!isRecord(source) || !Object.hasOwn(source, key))
|
|
43
|
+
return null;
|
|
44
|
+
const v = source[key];
|
|
45
|
+
if (!Array.isArray(v))
|
|
46
|
+
return null;
|
|
47
|
+
return v.filter((el) => typeof el === 'string');
|
|
48
|
+
}
|
|
49
|
+
// ── Deterministic forced sampling (design §4.4) ───────────────────────────────
|
|
50
|
+
/**
|
|
51
|
+
* FNV-1a 32-bit hash. Pure, deterministic, no crypto, no Math.random.
|
|
52
|
+
* Supports the full Unicode range in the input string.
|
|
53
|
+
*/
|
|
54
|
+
export function fnv1a32(input) {
|
|
55
|
+
let hash = 0x811c9dc5;
|
|
56
|
+
for (let i = 0; i < input.length; i++) {
|
|
57
|
+
hash ^= input.charCodeAt(i);
|
|
58
|
+
// FNV prime multiplication with 32-bit overflow wrapping.
|
|
59
|
+
hash = Math.imul(hash, 0x01000193);
|
|
60
|
+
}
|
|
61
|
+
// Convert to unsigned 32-bit.
|
|
62
|
+
return hash >>> 0;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Deterministic ~5% forced Stage 2 sampling. `fnv1a32(taskId) % modulus === 0`.
|
|
66
|
+
* Never uses Math.random or any non-deterministic source (design §4.4).
|
|
67
|
+
*/
|
|
68
|
+
export function isForcedStage2(taskId, modulus = FORCED_STAGE2_SAMPLE_MODULUS) {
|
|
69
|
+
if (modulus <= 0)
|
|
70
|
+
return false;
|
|
71
|
+
return fnv1a32(taskId) % modulus === 0;
|
|
72
|
+
}
|
|
73
|
+
// ── Flagged criteria (design §6.5.3) ─────────────────────────────────────────
|
|
74
|
+
/**
|
|
75
|
+
* Evaluate the three flagged criteria against Stage 1 output (design §6.5.3).
|
|
76
|
+
*
|
|
77
|
+
* Preconditions: none — `stage1Output` is untrusted LLM output (rc-1), read
|
|
78
|
+
* via `Object.hasOwn` (rc-5 / ERR-013).
|
|
79
|
+
*
|
|
80
|
+
* Postconditions:
|
|
81
|
+
* - `flagged === true` iff `reasons` is non-empty.
|
|
82
|
+
* - Three criteria: required-dimension missing, painCoverage.fullyCovered === false,
|
|
83
|
+
* implementationFidelity.score < 0.7.
|
|
84
|
+
* - Fields missing or wrong type → `undetermined` (rc-3: fail loud, never
|
|
85
|
+
* silently pass).
|
|
86
|
+
*
|
|
87
|
+
* Dimension criterion (§6.5.3, measurement-driven tightening):
|
|
88
|
+
* - Only **required** dimension names in `missingDimensions` count. The LLM
|
|
89
|
+
* may stuff optional/excluded/unknown strings in — all filtered out by
|
|
90
|
+
* `isRequiredDimension` before checking. `optionalUncovered` never enters
|
|
91
|
+
* `reasons`.
|
|
92
|
+
*/
|
|
93
|
+
export function evaluateFlaggedCriteria(stage1Output) {
|
|
94
|
+
const reasons = [];
|
|
95
|
+
const undetermined = [];
|
|
96
|
+
if (!isRecord(stage1Output)) {
|
|
97
|
+
// Entire output is malformed — all criteria undetermined.
|
|
98
|
+
return { flagged: false, reasons: [], undetermined: ['output_not_object'] };
|
|
99
|
+
}
|
|
100
|
+
// Criterion 1: required dimension missing (filtered, §6.5.3).
|
|
101
|
+
const compressionFidelity = Object.hasOwn(stage1Output, 'compressionFidelity')
|
|
102
|
+
? stage1Output.compressionFidelity
|
|
103
|
+
: undefined;
|
|
104
|
+
if (isRecord(compressionFidelity)) {
|
|
105
|
+
const missingDims = readStringArray(compressionFidelity, 'missingDimensions');
|
|
106
|
+
if (missingDims === null) {
|
|
107
|
+
undetermined.push('compressionFidelity.missingDimensions');
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// rc-4: filter untrusted input through the policy table.
|
|
111
|
+
const requiredMissing = missingDims.filter((d) => isRequiredDimension(d));
|
|
112
|
+
if (requiredMissing.length > 0) {
|
|
113
|
+
reasons.push('missing_dimensions');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
undetermined.push('compressionFidelity');
|
|
119
|
+
}
|
|
120
|
+
// Criterion 2: painCoverage.fullyCovered === false.
|
|
121
|
+
const painCoverage = Object.hasOwn(stage1Output, 'painCoverage')
|
|
122
|
+
? stage1Output.painCoverage
|
|
123
|
+
: undefined;
|
|
124
|
+
if (isRecord(painCoverage)) {
|
|
125
|
+
const fullyCovered = readBoolean(painCoverage, 'fullyCovered');
|
|
126
|
+
if (fullyCovered === null) {
|
|
127
|
+
undetermined.push('painCoverage.fullyCovered');
|
|
128
|
+
}
|
|
129
|
+
else if (fullyCovered === false) {
|
|
130
|
+
reasons.push('pain_not_fully_covered');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
undetermined.push('painCoverage');
|
|
135
|
+
}
|
|
136
|
+
// Criterion 3: implementationFidelity.score < threshold.
|
|
137
|
+
const implFidelity = Object.hasOwn(stage1Output, 'implementationFidelity')
|
|
138
|
+
? stage1Output.implementationFidelity
|
|
139
|
+
: undefined;
|
|
140
|
+
if (isRecord(implFidelity)) {
|
|
141
|
+
const score = readNumber(implFidelity, 'score');
|
|
142
|
+
if (score === null) {
|
|
143
|
+
undetermined.push('implementationFidelity.score');
|
|
144
|
+
}
|
|
145
|
+
else if (score < IMPLEMENTATION_FIDELITY_THRESHOLD) {
|
|
146
|
+
reasons.push('implementation_fidelity_below_threshold');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
undetermined.push('implementationFidelity');
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
flagged: reasons.length > 0,
|
|
154
|
+
reasons,
|
|
155
|
+
undetermined,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Run the two-stage progressive evaluation (design §6.5).
|
|
160
|
+
*
|
|
161
|
+
* Stage 1: evaluate with summary-level context → flagged criteria.
|
|
162
|
+
* If not flagged AND not forced AND no undetermined → return Stage 1 result.
|
|
163
|
+
* Otherwise → Stage 2: resolve tier2 lineage, evaluate independently.
|
|
164
|
+
*
|
|
165
|
+
* Stage 2 output is INDEPENDENT (rc-7 / ERR-015 / ERR-018 / ERR-019):
|
|
166
|
+
* - Stage 1 output is NOT injected into Stage 2 context.
|
|
167
|
+
* - Stage 2 concerns are NOT merged with Stage 1.
|
|
168
|
+
* - `stagesRun === 2` → `finalOutput` is entirely Stage 2's result.
|
|
169
|
+
*
|
|
170
|
+
* Forced sampling (~5%) serves as a false-negative check: if Stage 1 passed
|
|
171
|
+
* but Stage 2 finds new concerns, emit `stage1_false_negative`.
|
|
172
|
+
*/
|
|
173
|
+
/**
|
|
174
|
+
* Extract concern identifiers from an evaluator output (best-effort).
|
|
175
|
+
* The evaluator schema (evaluator-output.ts) defines `evaluation.concerns` as
|
|
176
|
+
* a `string[]` — each concern is a plain string. This function returns those
|
|
177
|
+
* strings directly, filtering out any non-string elements defensively.
|
|
178
|
+
* (CodeRabbit PR #1277: previously assumed concerns were objects with key/
|
|
179
|
+
* description fields, but the schema is string[] — the mismatch meant
|
|
180
|
+
* diffConcernKeys always returned empty, disabling false-negative detection.)
|
|
181
|
+
*/
|
|
182
|
+
function extractConcernKeys(output) {
|
|
183
|
+
if (!isRecord(output))
|
|
184
|
+
return [];
|
|
185
|
+
const evaluation = Object.hasOwn(output, 'evaluation') ? output.evaluation : undefined;
|
|
186
|
+
if (!isRecord(evaluation))
|
|
187
|
+
return [];
|
|
188
|
+
const concerns = Object.hasOwn(evaluation, 'concerns') ? evaluation.concerns : undefined;
|
|
189
|
+
if (!Array.isArray(concerns))
|
|
190
|
+
return [];
|
|
191
|
+
return concerns.filter((c) => typeof c === 'string' && c !== '');
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Compute the set difference of concern keys between Stage 2 and Stage 1.
|
|
195
|
+
* Returns keys present in Stage 2 but not in Stage 1.
|
|
196
|
+
*/
|
|
197
|
+
function diffConcernKeys(stage2Output, stage1Output) {
|
|
198
|
+
const keys1 = extractConcernKeys(stage1Output);
|
|
199
|
+
const keys2 = extractConcernKeys(stage2Output);
|
|
200
|
+
const set1 = new Set(keys1);
|
|
201
|
+
return keys2.filter((k) => !set1.has(k));
|
|
202
|
+
}
|
|
203
|
+
export async function runProgressiveEvaluation(deps) {
|
|
204
|
+
const emit = deps.emit ?? (() => undefined);
|
|
205
|
+
// Stage 1: summary-level evaluation.
|
|
206
|
+
const out1 = await deps.llm.evaluate(deps.stage1Context);
|
|
207
|
+
const d1 = evaluateFlaggedCriteria(out1);
|
|
208
|
+
const forced = isForcedStage2(deps.taskId);
|
|
209
|
+
// No Stage 2 needed.
|
|
210
|
+
if (!d1.flagged && !forced && d1.undetermined.length === 0) {
|
|
211
|
+
return { finalOutput: out1, stagesRun: 1, stage1Decision: d1, forcedStage2: false };
|
|
212
|
+
}
|
|
213
|
+
// Stage 2 triggered. Resolve tier2 lineage first.
|
|
214
|
+
if (deps.lineage !== undefined) {
|
|
215
|
+
const tier2 = await deps.lineage.resolve(deps.startArtifactId);
|
|
216
|
+
if (!tier2.ok) {
|
|
217
|
+
emit({ type: 'lineage_data_corrupt', detail: tier2.error.kind });
|
|
218
|
+
return {
|
|
219
|
+
finalOutput: out1,
|
|
220
|
+
stagesRun: 1,
|
|
221
|
+
stage1Decision: d1,
|
|
222
|
+
forcedStage2: forced,
|
|
223
|
+
stage2Aborted: { reason: 'lineage_error', detail: tier2.error.kind },
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Stage 2: independent re-evaluation with tier2 context.
|
|
228
|
+
// rc-7: do NOT inject out1, d1, or Stage 1 concerns into Stage 2.
|
|
229
|
+
const stage2Ctx = deps.stage2Context ?? deps.stage1Context;
|
|
230
|
+
const out2 = await deps.llm.evaluate(stage2Ctx);
|
|
231
|
+
// False-negative check (forced sample only, Stage 1 not flagged).
|
|
232
|
+
let falseNeg;
|
|
233
|
+
if (forced && !d1.flagged) {
|
|
234
|
+
const newKeys = diffConcernKeys(out2, out1);
|
|
235
|
+
if (newKeys.length > 0) {
|
|
236
|
+
falseNeg = { newConcernKeys: newKeys };
|
|
237
|
+
emit({ type: 'stage1_false_negative', newConcernKeys: newKeys });
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
finalOutput: out2,
|
|
242
|
+
stagesRun: 2,
|
|
243
|
+
stage1Decision: d1,
|
|
244
|
+
forcedStage2: forced,
|
|
245
|
+
stage1FalseNegative: falseNeg,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=progressive-evaluator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progressive-evaluator.js","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/progressive-evaluator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 1 — PromptBudgetManager: budgeted context allocation (design §6.3).
|
|
3
|
+
*
|
|
4
|
+
* Pure logic only (Core vs Plugin boundary, `antipattern-core-io`).
|
|
5
|
+
*
|
|
6
|
+
* `allocateContext` takes a manifest + the available field values (as a
|
|
7
|
+
* `ReadonlyMap<string, unknown>`, rc-1) and produces an `AllocatedContext`:
|
|
8
|
+
* which fields fit the budget, which were truncated, which were dropped, and
|
|
9
|
+
* which were absent. It is a PURE allocation function — it does NOT decide
|
|
10
|
+
* whether to fall back to full-predecessor injection; that decision lives in
|
|
11
|
+
* `resolveInjection` (resolve-injection.ts, task 5.10).
|
|
12
|
+
*
|
|
13
|
+
* Key correctness properties (design §6.3 postconditions):
|
|
14
|
+
* - `usedTokens <= budgetTokens`
|
|
15
|
+
* - every dropped/truncated field has a TruncationRecord AND emits a
|
|
16
|
+
* `context_truncated` event (rc-9 — never silently lose a field; the base
|
|
17
|
+
* proposal `break`ed on budget exhaustion, dropping remaining fields
|
|
18
|
+
* without record — ERR-002)
|
|
19
|
+
* - identical input always yields identical output (total order by
|
|
20
|
+
* (rank ASC, path ASC), no randomness, no time dependency)
|
|
21
|
+
* - unknown values go through `safeStringifyPreview` (rc-8) before token
|
|
22
|
+
* estimation
|
|
23
|
+
*
|
|
24
|
+
* budgetTokens scope (design §6.2.1 / §6.3 — MUST be reflected in comments):
|
|
25
|
+
* covers ONLY manifest-declared injection fields (tier0/tier1/tier2). Does NOT
|
|
26
|
+
* include core grounding, runner base instructions, or output-schema
|
|
27
|
+
* descriptions. `usedTokens <= budgetTokens` is an injection-field budget
|
|
28
|
+
* ceiling, NOT a prompt-total-length hard cap.
|
|
29
|
+
*/
|
|
30
|
+
import type { ContextManifest } from './context-manifest.js';
|
|
31
|
+
import type { SummaryRunnerKind } from './artifact-summary.js';
|
|
32
|
+
/** char/4 heuristic; no tokenizer dependency. Monotonically non-decreasing, pure. */
|
|
33
|
+
export declare function estimateTokens(text: string): number;
|
|
34
|
+
/** Max chars of a single field's serialized preview before token estimation. */
|
|
35
|
+
export declare const FIELD_PREVIEW_MAX_CHARS = 600;
|
|
36
|
+
/**
|
|
37
|
+
* Below this remaining budget, a field is dropped whole rather than
|
|
38
|
+
* partially truncated — a partial slice shorter than this carries too little
|
|
39
|
+
* signal to be worth the slot. Expressed in tokens (≈ 4 chars each).
|
|
40
|
+
*/
|
|
41
|
+
export declare const MIN_USEFUL_TOKENS = 8;
|
|
42
|
+
/** Appended to partially-truncated field text so truncation is explicit (rc-9). */
|
|
43
|
+
export declare const TRUNCATION_MARKER = "\u2026[budget-truncated]";
|
|
44
|
+
export interface TruncationRecord {
|
|
45
|
+
readonly fieldPath: string;
|
|
46
|
+
readonly reason: 'budget_exceeded' | 'partially_truncated';
|
|
47
|
+
readonly remainingBudgetTokens: number;
|
|
48
|
+
readonly keptChars: number;
|
|
49
|
+
readonly droppedChars: number;
|
|
50
|
+
}
|
|
51
|
+
export interface AllocatedContext {
|
|
52
|
+
readonly manifestId: string;
|
|
53
|
+
/** Fields that fit (fully or partially) into the budget. */
|
|
54
|
+
readonly fields: Readonly<Record<string, string>>;
|
|
55
|
+
/** Fields dropped/truncated, each with a reason (rc-9). */
|
|
56
|
+
readonly truncated: readonly TruncationRecord[];
|
|
57
|
+
/** Manifest-declared paths not present in the available map. */
|
|
58
|
+
readonly absent: readonly string[];
|
|
59
|
+
readonly usedTokens: number;
|
|
60
|
+
readonly budgetTokens: number;
|
|
61
|
+
}
|
|
62
|
+
export interface ContextTruncatedEvent {
|
|
63
|
+
readonly type: 'context_truncated';
|
|
64
|
+
readonly runnerKind: SummaryRunnerKind;
|
|
65
|
+
readonly manifestId: string;
|
|
66
|
+
readonly fieldPath: string;
|
|
67
|
+
readonly reason: TruncationRecord['reason'];
|
|
68
|
+
readonly remainingBudgetTokens: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Allocate manifest-declared fields into the token budget (design §6.3).
|
|
72
|
+
*
|
|
73
|
+
* Preconditions: `manifest.budgetTokens > 0`; `available` values are `unknown`
|
|
74
|
+
* (rc-1) and are narrowed only via `safeStringifyPreview`.
|
|
75
|
+
*
|
|
76
|
+
* Postconditions:
|
|
77
|
+
* - `usedTokens <= budgetTokens`
|
|
78
|
+
* - every dropped/truncated field has a TruncationRecord and emitted a
|
|
79
|
+
* `context_truncated` event (rc-9)
|
|
80
|
+
* - identical input → identical output (total order, deterministic)
|
|
81
|
+
*
|
|
82
|
+
* Loop invariant while traversing: `usedTokens + remainingBudget === budgetTokens`
|
|
83
|
+
* (until a partial truncate zeroes remaining).
|
|
84
|
+
*
|
|
85
|
+
* NOTE: this function does NOT perform the information-floor fallback (design
|
|
86
|
+
* §6.2.2). The fallback is decided by `resolveInjection` after reading this
|
|
87
|
+
* function's `absent` array.
|
|
88
|
+
*/
|
|
89
|
+
export declare function allocateContext(manifest: ContextManifest, available: ReadonlyMap<string, unknown>, emit: (event: ContextTruncatedEvent) => void): AllocatedContext;
|
|
90
|
+
//# sourceMappingURL=prompt-budget-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-budget-manager.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/prompt-budget-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,6BAAwB,CAAC;AAEvD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,qBAAqB,CAAC;IAC3D,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAChD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC5C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;CACxC;AASD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,EACvC,IAAI,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,GAC3C,gBAAgB,CAsFlB"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 1 — PromptBudgetManager: budgeted context allocation (design §6.3).
|
|
3
|
+
*
|
|
4
|
+
* Pure logic only (Core vs Plugin boundary, `antipattern-core-io`).
|
|
5
|
+
*
|
|
6
|
+
* `allocateContext` takes a manifest + the available field values (as a
|
|
7
|
+
* `ReadonlyMap<string, unknown>`, rc-1) and produces an `AllocatedContext`:
|
|
8
|
+
* which fields fit the budget, which were truncated, which were dropped, and
|
|
9
|
+
* which were absent. It is a PURE allocation function — it does NOT decide
|
|
10
|
+
* whether to fall back to full-predecessor injection; that decision lives in
|
|
11
|
+
* `resolveInjection` (resolve-injection.ts, task 5.10).
|
|
12
|
+
*
|
|
13
|
+
* Key correctness properties (design §6.3 postconditions):
|
|
14
|
+
* - `usedTokens <= budgetTokens`
|
|
15
|
+
* - every dropped/truncated field has a TruncationRecord AND emits a
|
|
16
|
+
* `context_truncated` event (rc-9 — never silently lose a field; the base
|
|
17
|
+
* proposal `break`ed on budget exhaustion, dropping remaining fields
|
|
18
|
+
* without record — ERR-002)
|
|
19
|
+
* - identical input always yields identical output (total order by
|
|
20
|
+
* (rank ASC, path ASC), no randomness, no time dependency)
|
|
21
|
+
* - unknown values go through `safeStringifyPreview` (rc-8) before token
|
|
22
|
+
* estimation
|
|
23
|
+
*
|
|
24
|
+
* budgetTokens scope (design §6.2.1 / §6.3 — MUST be reflected in comments):
|
|
25
|
+
* covers ONLY manifest-declared injection fields (tier0/tier1/tier2). Does NOT
|
|
26
|
+
* include core grounding, runner base instructions, or output-schema
|
|
27
|
+
* descriptions. `usedTokens <= budgetTokens` is an injection-field budget
|
|
28
|
+
* ceiling, NOT a prompt-total-length hard cap.
|
|
29
|
+
*/
|
|
30
|
+
import { rankOf, declaredFields } from './context-manifest.js';
|
|
31
|
+
import { safeStringifyPreview } from '../adapter/output-repair-contract.js';
|
|
32
|
+
/** char/4 heuristic; no tokenizer dependency. Monotonically non-decreasing, pure. */
|
|
33
|
+
export function estimateTokens(text) {
|
|
34
|
+
return Math.ceil(text.length / 4);
|
|
35
|
+
}
|
|
36
|
+
/** Max chars of a single field's serialized preview before token estimation. */
|
|
37
|
+
export const FIELD_PREVIEW_MAX_CHARS = 600;
|
|
38
|
+
/**
|
|
39
|
+
* Below this remaining budget, a field is dropped whole rather than
|
|
40
|
+
* partially truncated — a partial slice shorter than this carries too little
|
|
41
|
+
* signal to be worth the slot. Expressed in tokens (≈ 4 chars each).
|
|
42
|
+
*/
|
|
43
|
+
export const MIN_USEFUL_TOKENS = 8;
|
|
44
|
+
/** Appended to partially-truncated field text so truncation is explicit (rc-9). */
|
|
45
|
+
export const TRUNCATION_MARKER = '…[budget-truncated]';
|
|
46
|
+
/**
|
|
47
|
+
* Allocate manifest-declared fields into the token budget (design §6.3).
|
|
48
|
+
*
|
|
49
|
+
* Preconditions: `manifest.budgetTokens > 0`; `available` values are `unknown`
|
|
50
|
+
* (rc-1) and are narrowed only via `safeStringifyPreview`.
|
|
51
|
+
*
|
|
52
|
+
* Postconditions:
|
|
53
|
+
* - `usedTokens <= budgetTokens`
|
|
54
|
+
* - every dropped/truncated field has a TruncationRecord and emitted a
|
|
55
|
+
* `context_truncated` event (rc-9)
|
|
56
|
+
* - identical input → identical output (total order, deterministic)
|
|
57
|
+
*
|
|
58
|
+
* Loop invariant while traversing: `usedTokens + remainingBudget === budgetTokens`
|
|
59
|
+
* (until a partial truncate zeroes remaining).
|
|
60
|
+
*
|
|
61
|
+
* NOTE: this function does NOT perform the information-floor fallback (design
|
|
62
|
+
* §6.2.2). The fallback is decided by `resolveInjection` after reading this
|
|
63
|
+
* function's `absent` array.
|
|
64
|
+
*/
|
|
65
|
+
export function allocateContext(manifest, available, emit) {
|
|
66
|
+
const paths = declaredFields(manifest);
|
|
67
|
+
const scored = [];
|
|
68
|
+
const absent = [];
|
|
69
|
+
// Score every present path; record absent ones.
|
|
70
|
+
for (const p of paths) {
|
|
71
|
+
if (!available.has(p)) {
|
|
72
|
+
absent.push(p);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const text = safeStringifyPreview(available.get(p), FIELD_PREVIEW_MAX_CHARS);
|
|
76
|
+
scored.push({
|
|
77
|
+
path: p,
|
|
78
|
+
text,
|
|
79
|
+
tokens: estimateTokens(text),
|
|
80
|
+
rank: rankOf(p, manifest),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// Total order: (rank ASC, path ASC). Deterministic regardless of map
|
|
84
|
+
// insertion order or tier declaration order.
|
|
85
|
+
scored.sort((a, b) => a.rank - b.rank || (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
86
|
+
const fields = {};
|
|
87
|
+
const truncated = [];
|
|
88
|
+
let remaining = manifest.budgetTokens;
|
|
89
|
+
for (const f of scored) {
|
|
90
|
+
if (f.tokens <= remaining) {
|
|
91
|
+
// Fits fully.
|
|
92
|
+
fields[f.path] = f.text;
|
|
93
|
+
remaining -= f.tokens;
|
|
94
|
+
}
|
|
95
|
+
else if (remaining > MIN_USEFUL_TOKENS) {
|
|
96
|
+
// Partial truncate: keep a prefix that fits, mark explicitly.
|
|
97
|
+
const keptChars = Math.max(0, remaining * 4 - TRUNCATION_MARKER.length);
|
|
98
|
+
const kept = f.text.slice(0, keptChars) + TRUNCATION_MARKER;
|
|
99
|
+
fields[f.path] = kept;
|
|
100
|
+
const rec = {
|
|
101
|
+
fieldPath: f.path,
|
|
102
|
+
reason: 'partially_truncated',
|
|
103
|
+
remainingBudgetTokens: remaining,
|
|
104
|
+
keptChars: kept.length,
|
|
105
|
+
droppedChars: f.text.length - kept.length,
|
|
106
|
+
};
|
|
107
|
+
truncated.push(rec);
|
|
108
|
+
emit({
|
|
109
|
+
type: 'context_truncated',
|
|
110
|
+
runnerKind: manifest.runnerKind,
|
|
111
|
+
manifestId: manifest.manifestId,
|
|
112
|
+
fieldPath: f.path,
|
|
113
|
+
reason: rec.reason,
|
|
114
|
+
remainingBudgetTokens: remaining,
|
|
115
|
+
});
|
|
116
|
+
remaining = 0;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Drop whole: remaining budget too small for a useful partial. Do NOT
|
|
120
|
+
// break — keep traversing so every remaining field is recorded (rc-9 /
|
|
121
|
+
// ERR-002: the base proposal broke here, silently losing the rest).
|
|
122
|
+
const rec = {
|
|
123
|
+
fieldPath: f.path,
|
|
124
|
+
reason: 'budget_exceeded',
|
|
125
|
+
remainingBudgetTokens: remaining,
|
|
126
|
+
keptChars: 0,
|
|
127
|
+
droppedChars: f.text.length,
|
|
128
|
+
};
|
|
129
|
+
truncated.push(rec);
|
|
130
|
+
emit({
|
|
131
|
+
type: 'context_truncated',
|
|
132
|
+
runnerKind: manifest.runnerKind,
|
|
133
|
+
manifestId: manifest.manifestId,
|
|
134
|
+
fieldPath: f.path,
|
|
135
|
+
reason: rec.reason,
|
|
136
|
+
remainingBudgetTokens: remaining,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
manifestId: manifest.manifestId,
|
|
142
|
+
fields,
|
|
143
|
+
truncated,
|
|
144
|
+
absent,
|
|
145
|
+
usedTokens: manifest.budgetTokens - remaining,
|
|
146
|
+
budgetTokens: manifest.budgetTokens,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=prompt-budget-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-budget-manager.js","sourceRoot":"","sources":["../../../src/runtime-v2/internalization/prompt-budget-manager.ts"],"names":[],"mappings":"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"}
|