akm-cli 0.9.16 → 0.9.17-alpha.2
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 +504 -0
- package/dist/assets/prompts/consolidate-system.md +4 -11
- package/dist/assets/prompts/graph-extract-user-prompt.md +5 -5
- package/dist/commands/health/accept-rate.js +6 -0
- package/dist/commands/health/checks.js +54 -0
- package/dist/commands/health/improve-metrics.js +1 -5
- package/dist/commands/health/report-view-model.js +0 -1
- package/dist/commands/health.js +10 -0
- package/dist/commands/improve/consolidate/chunking.js +19 -35
- package/dist/commands/improve/consolidate/merge.js +6 -9
- package/dist/commands/improve/consolidate.js +104 -91
- package/dist/commands/improve/distill/promote-memory.js +40 -2
- package/dist/commands/improve/distill/quality-gate.js +186 -23
- package/dist/commands/improve/distill.js +42 -8
- package/dist/commands/improve/eligibility.js +13 -3
- package/dist/commands/improve/improve-cli.js +32 -9
- package/dist/commands/improve/improve-strategies.js +23 -1
- package/dist/commands/improve/improve.js +121 -84
- package/dist/commands/improve/loop-stages.js +241 -108
- package/dist/commands/improve/preparation.js +50 -17
- package/dist/commands/improve/reflect.js +16 -5
- package/dist/commands/improve/shared.js +0 -10
- package/dist/commands/proposal/drain.js +79 -10
- package/dist/commands/proposal/proposal-types.js +21 -0
- package/dist/commands/proposal/repository.js +108 -29
- package/dist/commands/tasks/tasks.js +19 -2
- package/dist/core/asset/frontmatter.js +106 -1
- package/dist/core/config/config.js +5 -2
- package/dist/core/config/retired-experimental-keys-shim.js +62 -0
- package/dist/core/config/schema/improve-processes.js +29 -2
- package/dist/core/improve-result.js +9 -0
- package/dist/core/paths.js +7 -0
- package/dist/core/write-source.js +10 -2
- package/dist/indexer/ensure-index.js +52 -7
- package/dist/indexer/graph/graph-extraction.js +82 -8
- package/dist/indexer/passes/memory-inference.js +16 -1
- package/dist/llm/client.js +16 -2
- package/dist/llm/graph-extract.js +162 -18
- package/dist/scripts/akm-migrate-node.js +97 -36
- package/dist/scripts/akm-migrate.js +97 -36
- package/dist/storage/repositories/index-entries-repository.js +43 -0
- package/dist/storage/repositories/proposals-repository.js +4 -1
- package/dist/storage/state-db-integrity.js +123 -0
- package/dist/workflows/program/schema.js +1 -0
- package/docs/reference/cli.md +17 -7
- package/docs/reference/data-and-telemetry.md +1 -0
- package/package.json +1 -1
- package/schemas/akm-config.json +44 -0
- package/schemas/akm-workflow.json +1 -0
- package/dist/commands/improve/eval-cases.js +0 -52
|
@@ -25,7 +25,7 @@ import { toErrorMessage } from "../core/common.js";
|
|
|
25
25
|
import { ConfigError } from "../core/errors.js";
|
|
26
26
|
import { parseEmbeddedJsonResponse } from "../core/parse.js";
|
|
27
27
|
import { warn, warnVerbose } from "../core/warn.js";
|
|
28
|
-
import { isContextSizeError } from "./client.js";
|
|
28
|
+
import { isContextSizeError, isTransportFailure, LlmCallError } from "./client.js";
|
|
29
29
|
import { tryLlmFeature } from "./feature-gate.js";
|
|
30
30
|
import { callStructured } from "./structured-call.js";
|
|
31
31
|
/**
|
|
@@ -33,7 +33,7 @@ import { callStructured } from "./structured-call.js";
|
|
|
33
33
|
* Chosen to be visually clear and unlikely to appear verbatim in asset bodies.
|
|
34
34
|
*/
|
|
35
35
|
const BATCH_ASSET_SEPARATOR = "=== ASSET";
|
|
36
|
-
export const GRAPH_EXTRACT_PROMPT_VERSION = "
|
|
36
|
+
export const GRAPH_EXTRACT_PROMPT_VERSION = "v3";
|
|
37
37
|
/** Asset bodies longer than this are chunked instead of truncated. */
|
|
38
38
|
const MAX_CHUNK_BODY_CHARS = 1600;
|
|
39
39
|
/** Bodies longer than this are excluded from multi-asset batch prompts. */
|
|
@@ -44,10 +44,72 @@ const NON_ARRAY_BATCH_DISABLE_THRESHOLD = 2;
|
|
|
44
44
|
const MAX_ENTITIES_PER_ASSET = 32;
|
|
45
45
|
/** Hard cap on relations returned per asset. */
|
|
46
46
|
const MAX_RELATIONS_PER_ASSET = 32;
|
|
47
|
+
/**
|
|
48
|
+
* Default cap on chunks processed per asset (R12b + R20) — overridable via
|
|
49
|
+
* `processes.graphExtraction.maxChunksPerAsset`. Without a cap, one long file
|
|
50
|
+
* chunked at MAX_CHUNK_BODY_CHARS could spend dozens of calls on a single
|
|
51
|
+
* asset (one file spent 21 of 27 run calls this way) before its output was
|
|
52
|
+
* sliced to MAX_ENTITIES_PER_ASSET/MAX_RELATIONS_PER_ASSET anyway.
|
|
53
|
+
*/
|
|
54
|
+
const DEFAULT_MAX_CHUNKS_PER_ASSET = 8;
|
|
47
55
|
const SYSTEM_PROMPT = systemPromptTemplate;
|
|
48
56
|
const USER_PROMPT_PREFIX = userPromptTemplate
|
|
49
57
|
.replace("{{MAX_ENTITIES}}", String(MAX_ENTITIES_PER_ASSET))
|
|
50
58
|
.replace("{{MAX_RELATIONS}}", String(MAX_RELATIONS_PER_ASSET));
|
|
59
|
+
/**
|
|
60
|
+
* Strict JSON Schema for one asset's extraction payload (R12b, compacted for
|
|
61
|
+
* R12). Sent via `responseSchema` to providers that opt into structured
|
|
62
|
+
* output (`runner.connection.supportsJsonSchema` — same lift as
|
|
63
|
+
* memory-infer.ts's `DERIVED_MEMORY_JSON_SCHEMA`); the client silently drops
|
|
64
|
+
* it otherwise. `maxItems` mirrors MAX_ENTITIES_PER_ASSET/MAX_RELATIONS_PER_ASSET
|
|
65
|
+
* so a compliant provider cannot pay for output beyond what
|
|
66
|
+
* parseGraphExtraction keeps. Relations are compact `[from, type, to]`
|
|
67
|
+
* triples (`type` may be `""`) rather than `{"from","to","type"}` objects —
|
|
68
|
+
* the object-keyed form cost 10+ tokens per relation for no signal, and
|
|
69
|
+
* output tokens cost far more than prompt tokens. There is deliberately no
|
|
70
|
+
* relation-level `confidence` in the schema (the prompt never asks for one);
|
|
71
|
+
* `parseGraphExtraction` still reads it from a legacy object-shaped relation
|
|
72
|
+
* for backward compatibility. `confidence` stays at the extraction level —
|
|
73
|
+
* parseGraphExtraction reads it into the merged confidence.
|
|
74
|
+
* `additionalProperties: false` forbids anything else. Reused as the `items`
|
|
75
|
+
* schema of a batch call's array response (see
|
|
76
|
+
* {@link buildBatchResponseSchema}) so a single-asset and a batched call
|
|
77
|
+
* bound entities/relations identically.
|
|
78
|
+
*/
|
|
79
|
+
const GRAPH_EXTRACTION_ITEM_SCHEMA = {
|
|
80
|
+
type: "object",
|
|
81
|
+
properties: {
|
|
82
|
+
entities: { type: "array", items: { type: "string" }, maxItems: MAX_ENTITIES_PER_ASSET },
|
|
83
|
+
relations: {
|
|
84
|
+
type: "array",
|
|
85
|
+
maxItems: MAX_RELATIONS_PER_ASSET,
|
|
86
|
+
items: {
|
|
87
|
+
type: "array",
|
|
88
|
+
items: { type: "string" },
|
|
89
|
+
minItems: 3,
|
|
90
|
+
maxItems: 3,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
confidence: { type: "number" },
|
|
94
|
+
},
|
|
95
|
+
required: ["entities", "relations"],
|
|
96
|
+
additionalProperties: false,
|
|
97
|
+
};
|
|
98
|
+
/** Schema for {@link extractGraphFromBody}'s single-asset `responseSchema`. */
|
|
99
|
+
const GRAPH_EXTRACTION_JSON_SCHEMA = GRAPH_EXTRACTION_ITEM_SCHEMA;
|
|
100
|
+
/**
|
|
101
|
+
* Schema for {@link extractGraphFromBodies}' batch `responseSchema` — an
|
|
102
|
+
* array of exactly `count` {@link GRAPH_EXTRACTION_ITEM_SCHEMA} elements, one
|
|
103
|
+
* per asset in the batch, matching the batch prompt's contract.
|
|
104
|
+
*/
|
|
105
|
+
function buildBatchResponseSchema(count) {
|
|
106
|
+
return {
|
|
107
|
+
type: "array",
|
|
108
|
+
minItems: count,
|
|
109
|
+
maxItems: count,
|
|
110
|
+
items: GRAPH_EXTRACTION_ITEM_SCHEMA,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
51
113
|
const GENERIC_ENTITIES = new Set([
|
|
52
114
|
"agent",
|
|
53
115
|
"application",
|
|
@@ -152,12 +214,14 @@ function mergeGraphExtractions(extractions) {
|
|
|
152
214
|
const relationChunkCounts = new Map();
|
|
153
215
|
let confidence;
|
|
154
216
|
let truncationCount = 0;
|
|
217
|
+
let truncatedChunks = 0;
|
|
155
218
|
let filteredGenericEntities = 0;
|
|
156
219
|
let filteredInvalidRelations = 0;
|
|
157
220
|
let filteredLowConfidenceRelations = 0;
|
|
158
221
|
let firstFailureReason;
|
|
159
222
|
for (const extraction of extractions) {
|
|
160
223
|
truncationCount += extraction.truncationCount ?? 0;
|
|
224
|
+
truncatedChunks += extraction.truncatedChunks ?? 0;
|
|
161
225
|
filteredGenericEntities += extraction.filteredGenericEntities ?? 0;
|
|
162
226
|
filteredInvalidRelations += extraction.filteredInvalidRelations ?? 0;
|
|
163
227
|
filteredLowConfidenceRelations += extraction.filteredLowConfidenceRelations ?? 0;
|
|
@@ -234,6 +298,7 @@ function mergeGraphExtractions(extractions) {
|
|
|
234
298
|
reason,
|
|
235
299
|
chunkCount: extractions.length,
|
|
236
300
|
truncationCount,
|
|
301
|
+
truncatedChunks,
|
|
237
302
|
filteredGenericEntities,
|
|
238
303
|
filteredInvalidRelations,
|
|
239
304
|
filteredLowConfidenceRelations,
|
|
@@ -283,13 +348,36 @@ function parseGraphExtraction(raw) {
|
|
|
283
348
|
let filteredLowConfidenceRelations = 0;
|
|
284
349
|
if (Array.isArray(item.relations)) {
|
|
285
350
|
for (const relation of item.relations) {
|
|
286
|
-
|
|
351
|
+
// Compact triple form `[from, type, to]` (R12) — `type` may be "".
|
|
352
|
+
// Legacy `{"from","to","type","confidence"}` object form still parses
|
|
353
|
+
// for backward compatibility (older cached prompts, other callers).
|
|
354
|
+
let fromRaw;
|
|
355
|
+
let toRaw;
|
|
356
|
+
let typeRaw;
|
|
357
|
+
let confidenceRaw;
|
|
358
|
+
if (Array.isArray(relation)) {
|
|
359
|
+
if (relation.length !== 3 ||
|
|
360
|
+
typeof relation[0] !== "string" ||
|
|
361
|
+
typeof relation[1] !== "string" ||
|
|
362
|
+
typeof relation[2] !== "string") {
|
|
363
|
+
filteredInvalidRelations += 1;
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
fromRaw = normalizeEntityName(relation[0]);
|
|
367
|
+
typeRaw = relation[1];
|
|
368
|
+
toRaw = normalizeEntityName(relation[2]);
|
|
369
|
+
}
|
|
370
|
+
else if (typeof relation === "object" && relation !== null) {
|
|
371
|
+
const rel = relation;
|
|
372
|
+
fromRaw = typeof rel.from === "string" ? normalizeEntityName(rel.from) : "";
|
|
373
|
+
toRaw = typeof rel.to === "string" ? normalizeEntityName(rel.to) : "";
|
|
374
|
+
typeRaw = typeof rel.type === "string" ? rel.type : undefined;
|
|
375
|
+
confidenceRaw = rel.confidence;
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
287
378
|
filteredInvalidRelations += 1;
|
|
288
379
|
continue;
|
|
289
380
|
}
|
|
290
|
-
const rel = relation;
|
|
291
|
-
const fromRaw = typeof rel.from === "string" ? normalizeEntityName(rel.from) : "";
|
|
292
|
-
const toRaw = typeof rel.to === "string" ? normalizeEntityName(rel.to) : "";
|
|
293
381
|
if (!fromRaw || !toRaw) {
|
|
294
382
|
filteredInvalidRelations += 1;
|
|
295
383
|
continue;
|
|
@@ -300,12 +388,12 @@ function parseGraphExtraction(raw) {
|
|
|
300
388
|
filteredInvalidRelations += 1;
|
|
301
389
|
continue;
|
|
302
390
|
}
|
|
303
|
-
const type =
|
|
391
|
+
const type = typeRaw !== undefined ? normalizeRelationType(typeRaw) : undefined;
|
|
304
392
|
if (type !== undefined && GENERIC_RELATION_TYPES.has(type)) {
|
|
305
393
|
filteredInvalidRelations += 1;
|
|
306
394
|
continue;
|
|
307
395
|
}
|
|
308
|
-
const confidence = parseConfidence(
|
|
396
|
+
const confidence = parseConfidence(confidenceRaw);
|
|
309
397
|
if (confidence !== undefined && confidence < MIN_RELATION_CONFIDENCE) {
|
|
310
398
|
filteredLowConfidenceRelations += 1;
|
|
311
399
|
continue;
|
|
@@ -356,8 +444,8 @@ function parseGraphExtraction(raw) {
|
|
|
356
444
|
*
|
|
357
445
|
* Expected model output (valid JSON array, no prose):
|
|
358
446
|
* [
|
|
359
|
-
* {"entities":["ServiceA","ServiceB"],"relations":[
|
|
360
|
-
* {"entities":["Terraform","Prod cluster"],"relations":[
|
|
447
|
+
* {"entities":["ServiceA","ServiceB"],"relations":[["ServiceA","integrates with","ServiceB"]]},
|
|
448
|
+
* {"entities":["Terraform","Prod cluster"],"relations":[["Terraform","provisions","Prod cluster"]]},
|
|
361
449
|
* {"entities":[],"relations":[]}
|
|
362
450
|
* ]
|
|
363
451
|
*
|
|
@@ -389,10 +477,10 @@ function buildBatchUserPrompt(bodies) {
|
|
|
389
477
|
return (`Extract entities and relations from the N=${count} assets below.\n\n` +
|
|
390
478
|
`Rules:\n` +
|
|
391
479
|
`- Output ONLY a JSON array of exactly ${count} objects, one per asset, preserving input order.\n` +
|
|
392
|
-
`- Each object: {"entities": ["Entity One", ...], "relations": [
|
|
480
|
+
`- Each object: {"entities": ["Entity One", ...], "relations": [["A", "uses", "B"], ...]}\n` +
|
|
393
481
|
`- Entities are short, canonical noun phrases (project names, services, tools, people, file/dir names, technical concepts).\n` +
|
|
394
|
-
`- Relations connect two entities that both appear in that asset's entities array.\n` +
|
|
395
|
-
`- "type" is a short verb phrase (e.g. "uses", "depends on", "owns").
|
|
482
|
+
`- Each relation is a 3-element array: [from, type, to]. Relations connect two entities that both appear in that asset's entities array.\n` +
|
|
483
|
+
`- "type" is a short verb phrase (e.g. "uses", "depends on", "owns"). Use "" when unsure.\n` +
|
|
396
484
|
`- Drop pleasantries, meta-commentary, and timestamps.\n` +
|
|
397
485
|
`- Limit to at most ${MAX_ENTITIES_PER_ASSET} entities and ${MAX_RELATIONS_PER_ASSET} relations per asset.\n` +
|
|
398
486
|
`- Use {"entities":[],"relations":[]} for assets with no extractable graph content.\n` +
|
|
@@ -504,12 +592,26 @@ export async function extractGraphFromBodies(llmRunner, bodies, signal, akmConfi
|
|
|
504
592
|
}
|
|
505
593
|
const systemPrompt = buildBatchSystemPrompt();
|
|
506
594
|
const userPrompt = buildBatchUserPrompt(nonEmptyBodies);
|
|
595
|
+
// Same responseSchema lift as extractGraphFromBody (R12b), scoped to this
|
|
596
|
+
// batch's asset count so a compliant provider bounds every element's
|
|
597
|
+
// entities/relations by the same maxItems as the single-asset path.
|
|
598
|
+
const batchResponseSchema = buildBatchResponseSchema(nonEmptyBodies.length);
|
|
507
599
|
const truncatedBodies = nonEmptyBodies.filter((body) => body.length > MAX_BATCH_BODY_CHARS).length;
|
|
508
600
|
if (truncatedBodies > 0) {
|
|
509
601
|
warnVerbose(`graph extraction (batch): ${truncatedBodies}/${nonEmptyBodies.length} asset body/bodies exceed the batch body threshold of ${MAX_BATCH_BODY_CHARS} chars.`);
|
|
510
602
|
}
|
|
511
603
|
let batchContextError = false;
|
|
512
604
|
let nonArrayResponse = false;
|
|
605
|
+
// R2: a dead/erroring provider must not be hammered with a per-asset
|
|
606
|
+
// fallback retry for every body in the batch — that is what turned one
|
|
607
|
+
// outage into 15,453 additional retry attempts. `isTransportFailure`
|
|
608
|
+
// (shared with client.ts's `isRetryable` — see its definition) covers
|
|
609
|
+
// `provider_error`, `network_error`, and `provider_html_error`: the
|
|
610
|
+
// provider itself is failing (a dead endpoint more often raises
|
|
611
|
+
// `network_error` or `provider_html_error` than a plain 5xx), not that this
|
|
612
|
+
// particular response was malformed; skip the fallback and record every
|
|
613
|
+
// asset as failed instead.
|
|
614
|
+
let batchProviderError = false;
|
|
513
615
|
const batchOutcome = await tryLlmFeature("graph_extraction", akmConfig, async () => {
|
|
514
616
|
try {
|
|
515
617
|
const raw = await callGraphLlm(llmRunner, [
|
|
@@ -519,6 +621,7 @@ export async function extractGraphFromBodies(llmRunner, bodies, signal, akmConfi
|
|
|
519
621
|
temperature: 0.1,
|
|
520
622
|
timeoutMs: llmRunner.timeoutMs,
|
|
521
623
|
signal,
|
|
624
|
+
responseSchema: batchResponseSchema,
|
|
522
625
|
onRetryAttempt: () => bumpTelemetry(options.telemetry, "retryAttempts"),
|
|
523
626
|
}, options.lease, options.onNotices);
|
|
524
627
|
if (!raw)
|
|
@@ -535,7 +638,12 @@ export async function extractGraphFromBodies(llmRunner, bodies, signal, akmConfi
|
|
|
535
638
|
const retryRaw = await callGraphLlm(llmRunner, [
|
|
536
639
|
{ role: "system", content: buildBatchRetrySystemPrompt() },
|
|
537
640
|
{ role: "user", content: userPrompt },
|
|
538
|
-
], {
|
|
641
|
+
], {
|
|
642
|
+
temperature: 0,
|
|
643
|
+
timeoutMs: llmRunner.timeoutMs,
|
|
644
|
+
signal,
|
|
645
|
+
responseSchema: batchResponseSchema,
|
|
646
|
+
}, options.lease, options.onNotices);
|
|
539
647
|
parsed = retryRaw ? parseEmbeddedJsonResponse(retryRaw, { expect: "array" }) : undefined;
|
|
540
648
|
}
|
|
541
649
|
if (!Array.isArray(parsed)) {
|
|
@@ -564,6 +672,12 @@ export async function extractGraphFromBodies(llmRunner, bodies, signal, akmConfi
|
|
|
564
672
|
warn(`graph extraction (batch): context size exceeded for ${nonEmptyBodies.length} asset(s); ` +
|
|
565
673
|
`skipping batch. promptChars=${userPrompt.length}${formatContextHint(llmRunner)}`);
|
|
566
674
|
}
|
|
675
|
+
else if (err instanceof LlmCallError && isTransportFailure(err)) {
|
|
676
|
+
batchProviderError = true;
|
|
677
|
+
bumpTelemetry(options.telemetry, "failureCount", nonEmptyBodies.length);
|
|
678
|
+
warn(`graph extraction (batch): provider error (${err.code}) for ${nonEmptyBodies.length} asset(s); ` +
|
|
679
|
+
`skipping per-asset fallback retries. promptChars=${userPrompt.length}${formatContextHint(llmRunner)}: ${errMsg}`);
|
|
680
|
+
}
|
|
567
681
|
else {
|
|
568
682
|
warn(`graph extraction (batch) failed for ${nonEmptyBodies.length} asset(s); ` +
|
|
569
683
|
`promptChars=${userPrompt.length}${formatContextHint(llmRunner)}: ${errMsg}`);
|
|
@@ -581,6 +695,13 @@ export async function extractGraphFromBodies(llmRunner, bodies, signal, akmConfi
|
|
|
581
695
|
if (batchResult !== null) {
|
|
582
696
|
applySuccessfulBatchResults(results, batchResult, nonEmptyBodies, nonEmptyIndices, batchState);
|
|
583
697
|
}
|
|
698
|
+
else if (batchProviderError) {
|
|
699
|
+
// No per-asset fallback against a failing provider — record every asset
|
|
700
|
+
// in this batch as a genuine failure so it is neither silently empty nor
|
|
701
|
+
// retried again below.
|
|
702
|
+
for (const origIdx of nonEmptyIndices)
|
|
703
|
+
results[origIdx] = { entities: [], relations: [], status: "failed", reason: "llm_error" };
|
|
704
|
+
}
|
|
584
705
|
if (batchContextError && nonEmptyBodies.length > 1) {
|
|
585
706
|
const splitAt = Math.ceil(nonEmptyBodies.length / 2);
|
|
586
707
|
const left = await extractGraphFromBodies(llmRunner, nonEmptyBodies.slice(0, splitAt), signal, akmConfig, onFallback, options);
|
|
@@ -601,6 +722,8 @@ export async function extractGraphFromBodies(llmRunner, bodies, signal, akmConfi
|
|
|
601
722
|
const fallbackIndices = nonEmptyIndices.filter((_origIdx, j) => {
|
|
602
723
|
if (batchContextError)
|
|
603
724
|
return false; // skip individual retries on context error
|
|
725
|
+
if (batchProviderError)
|
|
726
|
+
return false; // skip individual retries against a failing provider
|
|
604
727
|
// Result is still empty → needs a fallback call.
|
|
605
728
|
if (batchResult === null)
|
|
606
729
|
return true;
|
|
@@ -653,17 +776,34 @@ export async function extractGraphFromBody(llmRunner, body, signal, akmConfig, o
|
|
|
653
776
|
bumpTelemetry(options.telemetry, "truncationCount", chunked.truncationCount);
|
|
654
777
|
warnVerbose(`graph extraction: split a long asset into ${chunked.chunks.length} chunk(s) with ${chunked.truncationCount} hard split(s).`);
|
|
655
778
|
}
|
|
656
|
-
|
|
779
|
+
// R12b + R20: bound per-asset cost by capping how many chunks of a long
|
|
780
|
+
// asset are ever sent to the LLM. Excess chunks are dropped, never
|
|
781
|
+
// processed — the coverage loss is recorded as truncatedChunks rather than
|
|
782
|
+
// silently absorbed.
|
|
783
|
+
const maxChunksPerAsset = options.maxChunksPerAsset ?? DEFAULT_MAX_CHUNKS_PER_ASSET;
|
|
784
|
+
const cappedChunks = chunked.chunks.length > maxChunksPerAsset ? chunked.chunks.slice(0, maxChunksPerAsset) : chunked.chunks;
|
|
785
|
+
const truncatedChunkCount = chunked.chunks.length - cappedChunks.length;
|
|
786
|
+
if (truncatedChunkCount > 0) {
|
|
787
|
+
bumpTelemetry(options.telemetry, "truncatedChunks", truncatedChunkCount);
|
|
788
|
+
warnVerbose(`graph extraction: capped a long asset to ${cappedChunks.length} of ${chunked.chunks.length} chunk(s) ` +
|
|
789
|
+
`(maxChunksPerAsset=${maxChunksPerAsset}); ${truncatedChunkCount} chunk(s) not processed.`);
|
|
790
|
+
}
|
|
791
|
+
if (cappedChunks.length > 1) {
|
|
657
792
|
const chunkResults = [];
|
|
658
|
-
for (const chunk of
|
|
793
|
+
for (const chunk of cappedChunks) {
|
|
659
794
|
chunkResults.push(await extractGraphFromBody(llmRunner, chunk, signal, akmConfig, onFallback, options));
|
|
660
795
|
}
|
|
661
796
|
const merged = mergeGraphExtractions(chunkResults);
|
|
662
797
|
merged.truncationCount = (merged.truncationCount ?? 0) + chunked.truncationCount;
|
|
798
|
+
merged.truncatedChunks = (merged.truncatedChunks ?? 0) + truncatedChunkCount;
|
|
663
799
|
return merged;
|
|
664
800
|
}
|
|
665
|
-
|
|
666
|
-
|
|
801
|
+
// When capped down to exactly one chunk from a body that originally split
|
|
802
|
+
// into more, that single surviving chunk (not the full trimmedBody) is what
|
|
803
|
+
// must be sent — otherwise the cap would have no effect on prompt size.
|
|
804
|
+
const bodyForCall = truncatedChunkCount > 0 ? (cappedChunks[0] ?? trimmedBody) : trimmedBody;
|
|
805
|
+
const userPrompt = `${USER_PROMPT_PREFIX}${bodyForCall}`;
|
|
806
|
+
const result = await callStructured({
|
|
667
807
|
feature: "graph_extraction",
|
|
668
808
|
akmConfig,
|
|
669
809
|
runner: llmRunner,
|
|
@@ -676,6 +816,7 @@ export async function extractGraphFromBody(llmRunner, body, signal, akmConfig, o
|
|
|
676
816
|
temperature: 0.1,
|
|
677
817
|
timeoutMs: llmRunner.timeoutMs,
|
|
678
818
|
signal,
|
|
819
|
+
responseSchema: GRAPH_EXTRACTION_JSON_SCHEMA,
|
|
679
820
|
onRetryAttempt: () => bumpTelemetry(options.telemetry, "retryAttempts"),
|
|
680
821
|
},
|
|
681
822
|
onNotices: options.onNotices,
|
|
@@ -718,6 +859,9 @@ export async function extractGraphFromBody(llmRunner, body, signal, akmConfig, o
|
|
|
718
859
|
fallback: empty(),
|
|
719
860
|
onFallback,
|
|
720
861
|
});
|
|
862
|
+
if (truncatedChunkCount > 0)
|
|
863
|
+
result.truncatedChunks = (result.truncatedChunks ?? 0) + truncatedChunkCount;
|
|
864
|
+
return result;
|
|
721
865
|
}
|
|
722
866
|
// deduplicateGraph lives in src/indexer/graph/graph-dedup.ts (pure utility, no
|
|
723
867
|
// LLM calls) — import it from there directly. The re-export that used to live
|
|
@@ -12792,6 +12792,7 @@ var init_schema = __esm(() => {
|
|
|
12792
12792
|
content_policy_reject: true,
|
|
12793
12793
|
unsupported_type: true,
|
|
12794
12794
|
no_change: true,
|
|
12795
|
+
quality_rejected: true,
|
|
12795
12796
|
aborted: true
|
|
12796
12797
|
};
|
|
12797
12798
|
PROGRAM_RETRY_REASONS = Object.keys(RETRY_REASON_SET);
|
|
@@ -76098,6 +76099,7 @@ var IMPROVE_PROCESS_BASE_FIELDS = {
|
|
|
76098
76099
|
timeoutMs: exports_external.union([positiveInt, exports_external.null()]).optional()
|
|
76099
76100
|
};
|
|
76100
76101
|
var allowedTypesField = exports_external.array(exports_external.string().min(1)).optional();
|
|
76102
|
+
var excludeRefPrefixesField = exports_external.array(exports_external.string().min(1)).optional();
|
|
76101
76103
|
var processLimitField = positiveInt.optional();
|
|
76102
76104
|
var qualityGateField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
|
|
76103
76105
|
var contradictionDetectionField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
|
|
@@ -76138,6 +76140,7 @@ var antiCollapseField = exports_external.object({
|
|
|
76138
76140
|
}).passthrough().optional();
|
|
76139
76141
|
var REFLECT_PROCESS_FIELDS = {
|
|
76140
76142
|
allowedTypes: allowedTypesField,
|
|
76143
|
+
excludeRefPrefixes: excludeRefPrefixesField,
|
|
76141
76144
|
limit: processLimitField,
|
|
76142
76145
|
qualityGate: qualityGateField,
|
|
76143
76146
|
lowValueFilter: lowValueFilterField
|
|
@@ -76169,7 +76172,8 @@ var GRAPH_EXTRACTION_PROCESS_FIELDS = {
|
|
|
76169
76172
|
topN: positiveInt.optional(),
|
|
76170
76173
|
includeTypes: exports_external.array(exports_external.string().min(1)).min(1).optional(),
|
|
76171
76174
|
batchSize: positiveInt.optional(),
|
|
76172
|
-
fullScan: exports_external.boolean().optional()
|
|
76175
|
+
fullScan: exports_external.boolean().optional(),
|
|
76176
|
+
maxChunksPerAsset: positiveInt.optional()
|
|
76173
76177
|
};
|
|
76174
76178
|
var EXTRACT_PROCESS_FIELDS = {
|
|
76175
76179
|
defaultSince: exports_external.string().min(1).optional(),
|
|
@@ -76220,6 +76224,15 @@ function checkRetiredProcessKeys(value, ctx) {
|
|
|
76220
76224
|
}
|
|
76221
76225
|
}
|
|
76222
76226
|
}
|
|
76227
|
+
function rejectExcludeRefPrefixesOutsideReflect(value, ctx) {
|
|
76228
|
+
if ("excludeRefPrefixes" in value) {
|
|
76229
|
+
ctx.addIssue({
|
|
76230
|
+
code: exports_external.ZodIssueCode.custom,
|
|
76231
|
+
path: ["excludeRefPrefixes"],
|
|
76232
|
+
message: "excludeRefPrefixes is only valid on the reflect process"
|
|
76233
|
+
});
|
|
76234
|
+
}
|
|
76235
|
+
}
|
|
76223
76236
|
var ImproveProcessConfigSchema = exports_external.object({
|
|
76224
76237
|
...IMPROVE_PROCESS_BASE_FIELDS,
|
|
76225
76238
|
...REFLECT_PROCESS_FIELDS,
|
|
@@ -76232,8 +76245,8 @@ var ImproveProcessConfigSchema = exports_external.object({
|
|
|
76232
76245
|
...PROACTIVE_MAINTENANCE_PROCESS_FIELDS
|
|
76233
76246
|
}).passthrough().superRefine(checkRetiredProcessKeys);
|
|
76234
76247
|
var ReflectProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...REFLECT_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
76235
|
-
var DistillProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...DISTILL_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
76236
|
-
var ConsolidateProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...CONSOLIDATE_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
76248
|
+
var DistillProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...DISTILL_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys).superRefine(rejectExcludeRefPrefixesOutsideReflect);
|
|
76249
|
+
var ConsolidateProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...CONSOLIDATE_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys).superRefine(rejectExcludeRefPrefixesOutsideReflect);
|
|
76237
76250
|
var MemoryInferenceProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...MEMORY_INFERENCE_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
76238
76251
|
var GraphExtractionProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...GRAPH_EXTRACTION_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
76239
76252
|
var ExtractProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...EXTRACT_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
@@ -77658,6 +77671,31 @@ function upgradeConfigVersion(raw, sourcePath) {
|
|
|
77658
77671
|
|
|
77659
77672
|
// src/core/config/config.ts
|
|
77660
77673
|
init_legacy_source_shape_shim();
|
|
77674
|
+
|
|
77675
|
+
// src/core/config/retired-experimental-keys-shim.ts
|
|
77676
|
+
init_common();
|
|
77677
|
+
init_warn();
|
|
77678
|
+
var RETIRED_EXPERIMENTAL_KEYS = ["workflowEngine"];
|
|
77679
|
+
function retiredExperimentalKeysIn(raw) {
|
|
77680
|
+
const experimental = raw.experimental;
|
|
77681
|
+
if (!isRecord(experimental))
|
|
77682
|
+
return [];
|
|
77683
|
+
return RETIRED_EXPERIMENTAL_KEYS.filter((key) => (key in experimental));
|
|
77684
|
+
}
|
|
77685
|
+
function stripRetiredExperimentalKeys(raw, sourcePath) {
|
|
77686
|
+
const present = retiredExperimentalKeysIn(raw);
|
|
77687
|
+
if (present.length === 0)
|
|
77688
|
+
return raw;
|
|
77689
|
+
const original = raw.experimental;
|
|
77690
|
+
const experimental = { ...original };
|
|
77691
|
+
for (const key of present)
|
|
77692
|
+
delete experimental[key];
|
|
77693
|
+
const where = sourcePath ? ` at ${sourcePath}` : "";
|
|
77694
|
+
warnOnce(`config:retired-experimental-key${sourcePath ? `:${sourcePath}` : ""}`, `Config${where} uses the retired experimental key(s) ${present.join(", ")} — ignored in memory. Run \`akm migrate apply\` to remove ${present.length === 1 ? "it" : "them"} from the config file and silence this warning.`);
|
|
77695
|
+
return { ...raw, experimental };
|
|
77696
|
+
}
|
|
77697
|
+
|
|
77698
|
+
// src/core/config/config.ts
|
|
77661
77699
|
init_paths();
|
|
77662
77700
|
init_warn();
|
|
77663
77701
|
var DEFAULT_CONFIG = {
|
|
@@ -77717,7 +77755,8 @@ function loadUserConfig() {
|
|
|
77717
77755
|
function runConfigFilePipeline(text, sourcePath) {
|
|
77718
77756
|
const versioned = upgradeConfigVersion(parseConfigText(text, sourcePath), sourcePath);
|
|
77719
77757
|
const parsedRaw = migrateLegacySourceShape(versioned, sourcePath);
|
|
77720
|
-
|
|
77758
|
+
const liftedRaw = liftExtraParamsOrThrow(parsedRaw, sourcePath);
|
|
77759
|
+
return stripRetiredExperimentalKeys(liftedRaw, sourcePath);
|
|
77721
77760
|
}
|
|
77722
77761
|
function liftExtraParamsOrThrow(parsedRaw, sourcePath) {
|
|
77723
77762
|
const where = sourcePath ? ` at ${sourcePath}` : "";
|
|
@@ -86376,8 +86415,11 @@ function assertAkmAssetWrite(source, allowedAdapters = ["akm"]) {
|
|
|
86376
86415
|
return;
|
|
86377
86416
|
throw new UsageError(`Bundle "${source.name}" uses adapter "${source.adapterId}", which does not support AKM asset writes.`, "INVALID_FLAG_VALUE");
|
|
86378
86417
|
}
|
|
86418
|
+
function isWriteCapableSourceKind(kind) {
|
|
86419
|
+
return kind === "filesystem" || kind === "git";
|
|
86420
|
+
}
|
|
86379
86421
|
function adaptConfiguredSource(runtime) {
|
|
86380
|
-
if (runtime.type
|
|
86422
|
+
if (!isWriteCapableSourceKind(runtime.type)) {
|
|
86381
86423
|
throw new ConfigError(`write-source: source "${runtime.name}" has unsupported kind "${runtime.type}" for writes. ` + "Writes are only defined for `filesystem` and `git` sources.", "INVALID_CONFIG_FILE", 'Use `kind: "filesystem"` or `kind: "git"` for writable sources.');
|
|
86382
86424
|
}
|
|
86383
86425
|
const kind = runtime.type;
|
|
@@ -93213,32 +93255,7 @@ var GLOBAL_OUTPUT_ARGS2 = {
|
|
|
93213
93255
|
init_errors();
|
|
93214
93256
|
|
|
93215
93257
|
// scripts/akm-migrate/help.txt
|
|
93216
|
-
var help_default =
|
|
93217
|
-
|
|
93218
|
-
The one migration tool for an akm installation. Every historical shape akm
|
|
93219
|
-
has ever written lives here; the CLI proper reads only current schemas.
|
|
93220
|
-
\`status\` and \`apply\` run every step, in order, and print one combined JSON
|
|
93221
|
-
plan (exit 1 when any step is blocked):
|
|
93222
|
-
|
|
93223
|
-
1. legacy config \`extraParams\` keys lifted onto first-class engine fields
|
|
93224
|
-
2. scheduler grants bound to the configured source installation that was
|
|
93225
|
-
approved (stale grants whose bundle no longer exists are removed)
|
|
93226
|
-
3. pending state.db migrations, historical-destructive ones included,
|
|
93227
|
-
with a verified sibling safety copy (the only path that admits them)
|
|
93228
|
-
4. task-v2 files to task v3, then task-v3 files to task source v4
|
|
93229
|
-
5. superseded pre-0.9.0 \`.akm\` residue and stale filesystem transactions
|
|
93230
|
-
6. live \`.akm\` writers relocated to \`$STATE\`/\`$CACHE\`, for every local
|
|
93231
|
-
bundle (distill-rejected, eval-cases, measurement verdicts, and stale
|
|
93232
|
-
improve-pipeline locks — a lock a live run still holds is left alone)
|
|
93233
|
-
|
|
93234
|
-
\`akm migrate status|apply\` wraps this executable; \`akm upgrade\` runs
|
|
93235
|
-
\`apply\` after its install step, so an image that ships akm can put either
|
|
93236
|
-
in its entrypoint (a current installation is a no-op).
|
|
93237
|
-
|
|
93238
|
-
Commands:
|
|
93239
|
-
status Inspect every pending migration without changing anything.
|
|
93240
|
-
apply [--dry-run] Back up and apply every pending migration.
|
|
93241
|
-
`;
|
|
93258
|
+
var help_default = "Usage: akm-migrate <command> [options]\n\nThe one migration tool for an akm installation. Every historical shape akm\nhas ever written lives here; the CLI proper reads only current schemas.\n`status` and `apply` run every step, in order, and print one combined JSON\nplan (exit 1 when any step is blocked):\n\n 1. legacy config `extraParams` keys lifted onto first-class engine fields\n 2. retired `experimental.*` config keys removed (today `workflowEngine`)\n 3. scheduler grants bound to the configured source installation that was\n approved (stale grants whose bundle no longer exists are removed)\n 4. pending state.db migrations, historical-destructive ones included,\n with a verified sibling safety copy (the only path that admits them)\n 5. source-owned schedule enablement converted to host-local scheduler\n grants\n 6. task-v2 files to task v3, then task-v3 files to task source v4\n 7. superseded pre-0.9.0 `.akm` residue and stale filesystem transactions\n 8. live `.akm` writers relocated to `$STATE`/`$CACHE`, for every local\n bundle (distill-rejected, eval-cases, measurement verdicts, and stale\n improve-pipeline locks — a lock a live run still holds is left alone)\n\n`akm migrate status|apply` wraps this executable; `akm upgrade` runs\n`apply` after its install step, so an image that ships akm can put either\nin its entrypoint (a current installation is a no-op).\n\nCommands:\n status Inspect every pending migration without changing anything.\n apply [--dry-run] Back up and apply every pending migration.\n";
|
|
93242
93259
|
|
|
93243
93260
|
// scripts/akm-migrate/run-migrate.ts
|
|
93244
93261
|
init_common();
|
|
@@ -94774,10 +94791,44 @@ function applyConfigExtraParamsLift(configPath) {
|
|
|
94774
94791
|
return { applied: true, lifted, conflicts: [] };
|
|
94775
94792
|
}
|
|
94776
94793
|
|
|
94794
|
+
// scripts/akm-migrate/migrate/config-retired-experimental-keys.ts
|
|
94795
|
+
function readRawConfig2(configPath) {
|
|
94796
|
+
const text = readConfigText(configPath);
|
|
94797
|
+
if (text === undefined)
|
|
94798
|
+
return;
|
|
94799
|
+
return parseConfigText(text, configPath);
|
|
94800
|
+
}
|
|
94801
|
+
function findConfigRetiredExperimentalKeys(configPath) {
|
|
94802
|
+
const raw = readRawConfig2(configPath);
|
|
94803
|
+
if (!raw)
|
|
94804
|
+
return { removed: [] };
|
|
94805
|
+
return { removed: retiredExperimentalKeysIn(raw).map((key) => `experimental.${key}`) };
|
|
94806
|
+
}
|
|
94807
|
+
function applyConfigRetiredExperimentalKeys(configPath) {
|
|
94808
|
+
const raw = readRawConfig2(configPath);
|
|
94809
|
+
if (!raw)
|
|
94810
|
+
return { applied: false, removed: [] };
|
|
94811
|
+
const retired = retiredExperimentalKeysIn(raw);
|
|
94812
|
+
if (retired.length === 0)
|
|
94813
|
+
return { applied: false, removed: [] };
|
|
94814
|
+
const experimental = { ...raw.experimental };
|
|
94815
|
+
for (const key of retired)
|
|
94816
|
+
delete experimental[key];
|
|
94817
|
+
const config = { ...raw, experimental };
|
|
94818
|
+
const release = acquireConfigLock();
|
|
94819
|
+
try {
|
|
94820
|
+
backupExistingConfig(configPath);
|
|
94821
|
+
writeConfigAtomic(configPath, config);
|
|
94822
|
+
} finally {
|
|
94823
|
+
release();
|
|
94824
|
+
}
|
|
94825
|
+
return { applied: true, removed: retired.map((key) => `experimental.${key}`) };
|
|
94826
|
+
}
|
|
94827
|
+
|
|
94777
94828
|
// scripts/akm-migrate/migrate/config-scheduler-source-ids.ts
|
|
94778
94829
|
init_asset_ref();
|
|
94779
94830
|
init_bundle_id();
|
|
94780
|
-
function
|
|
94831
|
+
function readRawConfig3(configPath) {
|
|
94781
94832
|
const text = readConfigText(configPath);
|
|
94782
94833
|
return text === undefined ? undefined : parseConfigText(text, configPath);
|
|
94783
94834
|
}
|
|
@@ -94832,13 +94883,13 @@ function implicitBundleSourceId(raw, bundleId) {
|
|
|
94832
94883
|
return implicitId === bundleId ? filesystemBundleSourceId(root) : undefined;
|
|
94833
94884
|
}
|
|
94834
94885
|
function findConfigSchedulerSourceIdMigration(configPath) {
|
|
94835
|
-
const raw =
|
|
94886
|
+
const raw = readRawConfig3(configPath);
|
|
94836
94887
|
return Object.freeze({ changes: Object.freeze(raw ? migrationChanges(raw) : []) });
|
|
94837
94888
|
}
|
|
94838
94889
|
function applyConfigSchedulerSourceIdMigration(configPath) {
|
|
94839
94890
|
const release = acquireConfigLock();
|
|
94840
94891
|
try {
|
|
94841
|
-
const raw =
|
|
94892
|
+
const raw = readRawConfig3(configPath);
|
|
94842
94893
|
if (!raw)
|
|
94843
94894
|
return Object.freeze({ applied: false, changes: Object.freeze([]) });
|
|
94844
94895
|
const changes = migrationChanges(raw);
|
|
@@ -97986,7 +98037,7 @@ var GATE_OUTCOMES = {
|
|
|
97986
98037
|
"auto-rejected": true
|
|
97987
98038
|
};
|
|
97988
98039
|
function validatePresentMetadata(meta) {
|
|
97989
|
-
const stringFields = ["sourceRun", "beforeHash", "backupContent"];
|
|
98040
|
+
const stringFields = ["sourceRun", "beforeHash", "beforeHashNormalized", "backupContent"];
|
|
97990
98041
|
for (const field of stringFields) {
|
|
97991
98042
|
if (Object.hasOwn(meta, field) && typeof meta[field] !== "string")
|
|
97992
98043
|
invalidPresentField(field);
|
|
@@ -98066,6 +98117,7 @@ function proposalRowToProposal(row) {
|
|
|
98066
98117
|
changes,
|
|
98067
98118
|
...proposedTarget !== undefined ? { proposedTarget } : {},
|
|
98068
98119
|
...typeof meta.beforeHash === "string" ? { beforeHash: meta.beforeHash } : {},
|
|
98120
|
+
...typeof meta.beforeHashNormalized === "string" ? { beforeHashNormalized: meta.beforeHashNormalized } : {},
|
|
98069
98121
|
...meta.review !== undefined ? { review: meta.review } : {},
|
|
98070
98122
|
...typeof meta.confidence === "number" ? { confidence: meta.confidence } : {},
|
|
98071
98123
|
...meta.gateDecision !== undefined ? { gateDecision: meta.gateDecision } : {},
|
|
@@ -98092,6 +98144,8 @@ function proposalToRowValues(proposal, stashDir) {
|
|
|
98092
98144
|
metaObj.proposedTarget = currentProposalTarget(proposal.proposedTarget);
|
|
98093
98145
|
if (proposal.beforeHash !== undefined)
|
|
98094
98146
|
metaObj.beforeHash = proposal.beforeHash;
|
|
98147
|
+
if (proposal.beforeHashNormalized !== undefined)
|
|
98148
|
+
metaObj.beforeHashNormalized = proposal.beforeHashNormalized;
|
|
98095
98149
|
if (proposal.sourceRun !== undefined)
|
|
98096
98150
|
metaObj.sourceRun = proposal.sourceRun;
|
|
98097
98151
|
if (proposal.review !== undefined)
|
|
@@ -104055,12 +104109,16 @@ async function runMigration(options) {
|
|
|
104055
104109
|
if (apply && configExtraParams.applied)
|
|
104056
104110
|
resetConfigCache();
|
|
104057
104111
|
const pendingLift = apply ? undefined : configExtraParams.pending;
|
|
104112
|
+
const configRetiredExperimentalKeys = apply ? applyConfigRetiredExperimentalKeys(configPath) : { pending: findConfigRetiredExperimentalKeys(configPath) };
|
|
104113
|
+
if (apply && configRetiredExperimentalKeys.applied)
|
|
104114
|
+
resetConfigCache();
|
|
104058
104115
|
if (pendingLift && pendingLift.lifted.length > 0) {
|
|
104059
104116
|
return {
|
|
104060
104117
|
schemaVersion: 1,
|
|
104061
104118
|
status: "blocked",
|
|
104062
104119
|
blockers: pendingLift.lifted,
|
|
104063
104120
|
configExtraParams,
|
|
104121
|
+
configRetiredExperimentalKeys,
|
|
104064
104122
|
stateMigrations: { pending: listPendingStateMigrations() }
|
|
104065
104123
|
};
|
|
104066
104124
|
}
|
|
@@ -104075,6 +104133,7 @@ async function runMigration(options) {
|
|
|
104075
104133
|
blockers: pendingSchedulerBindings.changes.map((change) => `${change.kind === "bind" ? "bind" : "drop"} scheduler activation ${change.ref}` + (change.reason ? `: ${change.reason}` : "")),
|
|
104076
104134
|
configExtraParams,
|
|
104077
104135
|
configSchedulerSourceIds,
|
|
104136
|
+
configRetiredExperimentalKeys,
|
|
104078
104137
|
stateMigrations: { pending: listPendingStateMigrations() }
|
|
104079
104138
|
};
|
|
104080
104139
|
}
|
|
@@ -104094,12 +104153,14 @@ async function runMigration(options) {
|
|
|
104094
104153
|
}
|
|
104095
104154
|
const stateStatus = "pending" in stateMigrations && stateMigrations.pending.length > 0 ? "ready" : "current";
|
|
104096
104155
|
const schedulerStatus = "pending" in schedulerActivation && schedulerActivation.pending.length > 0 ? "ready" : "current";
|
|
104156
|
+
const retiredKeysStatus = "pending" in configRetiredExperimentalKeys && configRetiredExperimentalKeys.pending.removed.length > 0 ? "ready" : "current";
|
|
104097
104157
|
return {
|
|
104098
104158
|
schemaVersion: 1,
|
|
104099
|
-
status: worstStatus(worstStatus(worstStatus(taskV3.status, taskV4.status), stateStatus), schedulerStatus),
|
|
104159
|
+
status: worstStatus(worstStatus(worstStatus(worstStatus(taskV3.status, taskV4.status), stateStatus), schedulerStatus), retiredKeysStatus),
|
|
104100
104160
|
blockers: [...taskV3.blockers, ...taskV4.blockers],
|
|
104101
104161
|
configExtraParams,
|
|
104102
104162
|
configSchedulerSourceIds,
|
|
104163
|
+
configRetiredExperimentalKeys,
|
|
104103
104164
|
stateMigrations,
|
|
104104
104165
|
schedulerActivation,
|
|
104105
104166
|
taskV3Migration: taskV3.taskV3Migration,
|