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
|
@@ -12791,6 +12791,7 @@ var init_schema = __esm(() => {
|
|
|
12791
12791
|
content_policy_reject: true,
|
|
12792
12792
|
unsupported_type: true,
|
|
12793
12793
|
no_change: true,
|
|
12794
|
+
quality_rejected: true,
|
|
12794
12795
|
aborted: true
|
|
12795
12796
|
};
|
|
12796
12797
|
PROGRAM_RETRY_REASONS = Object.keys(RETRY_REASON_SET);
|
|
@@ -75426,6 +75427,7 @@ var IMPROVE_PROCESS_BASE_FIELDS = {
|
|
|
75426
75427
|
timeoutMs: exports_external.union([positiveInt, exports_external.null()]).optional()
|
|
75427
75428
|
};
|
|
75428
75429
|
var allowedTypesField = exports_external.array(exports_external.string().min(1)).optional();
|
|
75430
|
+
var excludeRefPrefixesField = exports_external.array(exports_external.string().min(1)).optional();
|
|
75429
75431
|
var processLimitField = positiveInt.optional();
|
|
75430
75432
|
var qualityGateField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
|
|
75431
75433
|
var contradictionDetectionField = exports_external.object({ enabled: exports_external.boolean().optional() }).passthrough().optional();
|
|
@@ -75466,6 +75468,7 @@ var antiCollapseField = exports_external.object({
|
|
|
75466
75468
|
}).passthrough().optional();
|
|
75467
75469
|
var REFLECT_PROCESS_FIELDS = {
|
|
75468
75470
|
allowedTypes: allowedTypesField,
|
|
75471
|
+
excludeRefPrefixes: excludeRefPrefixesField,
|
|
75469
75472
|
limit: processLimitField,
|
|
75470
75473
|
qualityGate: qualityGateField,
|
|
75471
75474
|
lowValueFilter: lowValueFilterField
|
|
@@ -75497,7 +75500,8 @@ var GRAPH_EXTRACTION_PROCESS_FIELDS = {
|
|
|
75497
75500
|
topN: positiveInt.optional(),
|
|
75498
75501
|
includeTypes: exports_external.array(exports_external.string().min(1)).min(1).optional(),
|
|
75499
75502
|
batchSize: positiveInt.optional(),
|
|
75500
|
-
fullScan: exports_external.boolean().optional()
|
|
75503
|
+
fullScan: exports_external.boolean().optional(),
|
|
75504
|
+
maxChunksPerAsset: positiveInt.optional()
|
|
75501
75505
|
};
|
|
75502
75506
|
var EXTRACT_PROCESS_FIELDS = {
|
|
75503
75507
|
defaultSince: exports_external.string().min(1).optional(),
|
|
@@ -75548,6 +75552,15 @@ function checkRetiredProcessKeys(value, ctx) {
|
|
|
75548
75552
|
}
|
|
75549
75553
|
}
|
|
75550
75554
|
}
|
|
75555
|
+
function rejectExcludeRefPrefixesOutsideReflect(value, ctx) {
|
|
75556
|
+
if ("excludeRefPrefixes" in value) {
|
|
75557
|
+
ctx.addIssue({
|
|
75558
|
+
code: exports_external.ZodIssueCode.custom,
|
|
75559
|
+
path: ["excludeRefPrefixes"],
|
|
75560
|
+
message: "excludeRefPrefixes is only valid on the reflect process"
|
|
75561
|
+
});
|
|
75562
|
+
}
|
|
75563
|
+
}
|
|
75551
75564
|
var ImproveProcessConfigSchema = exports_external.object({
|
|
75552
75565
|
...IMPROVE_PROCESS_BASE_FIELDS,
|
|
75553
75566
|
...REFLECT_PROCESS_FIELDS,
|
|
@@ -75560,8 +75573,8 @@ var ImproveProcessConfigSchema = exports_external.object({
|
|
|
75560
75573
|
...PROACTIVE_MAINTENANCE_PROCESS_FIELDS
|
|
75561
75574
|
}).passthrough().superRefine(checkRetiredProcessKeys);
|
|
75562
75575
|
var ReflectProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...REFLECT_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
75563
|
-
var DistillProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...DISTILL_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
75564
|
-
var ConsolidateProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...CONSOLIDATE_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
75576
|
+
var DistillProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...DISTILL_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys).superRefine(rejectExcludeRefPrefixesOutsideReflect);
|
|
75577
|
+
var ConsolidateProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...CONSOLIDATE_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys).superRefine(rejectExcludeRefPrefixesOutsideReflect);
|
|
75565
75578
|
var MemoryInferenceProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...MEMORY_INFERENCE_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
75566
75579
|
var GraphExtractionProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...GRAPH_EXTRACTION_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
75567
75580
|
var ExtractProcessConfigSchema = exports_external.object({ ...IMPROVE_PROCESS_BASE_FIELDS, ...EXTRACT_PROCESS_FIELDS }).passthrough().superRefine(checkRetiredProcessKeys);
|
|
@@ -76986,6 +76999,31 @@ function upgradeConfigVersion(raw, sourcePath) {
|
|
|
76986
76999
|
|
|
76987
77000
|
// src/core/config/config.ts
|
|
76988
77001
|
init_legacy_source_shape_shim();
|
|
77002
|
+
|
|
77003
|
+
// src/core/config/retired-experimental-keys-shim.ts
|
|
77004
|
+
init_common();
|
|
77005
|
+
init_warn();
|
|
77006
|
+
var RETIRED_EXPERIMENTAL_KEYS = ["workflowEngine"];
|
|
77007
|
+
function retiredExperimentalKeysIn(raw) {
|
|
77008
|
+
const experimental = raw.experimental;
|
|
77009
|
+
if (!isRecord(experimental))
|
|
77010
|
+
return [];
|
|
77011
|
+
return RETIRED_EXPERIMENTAL_KEYS.filter((key) => (key in experimental));
|
|
77012
|
+
}
|
|
77013
|
+
function stripRetiredExperimentalKeys(raw, sourcePath) {
|
|
77014
|
+
const present = retiredExperimentalKeysIn(raw);
|
|
77015
|
+
if (present.length === 0)
|
|
77016
|
+
return raw;
|
|
77017
|
+
const original = raw.experimental;
|
|
77018
|
+
const experimental = { ...original };
|
|
77019
|
+
for (const key of present)
|
|
77020
|
+
delete experimental[key];
|
|
77021
|
+
const where = sourcePath ? ` at ${sourcePath}` : "";
|
|
77022
|
+
warnOnce(`config:retired-experimental-key${sourcePath ? `:${sourcePath}` : ""}`, `Config${where} uses the retired experimental key(s) ${present.join(", ")} \u2014 ignored in memory. Run \`akm migrate apply\` to remove ${present.length === 1 ? "it" : "them"} from the config file and silence this warning.`);
|
|
77023
|
+
return { ...raw, experimental };
|
|
77024
|
+
}
|
|
77025
|
+
|
|
77026
|
+
// src/core/config/config.ts
|
|
76989
77027
|
init_paths();
|
|
76990
77028
|
init_warn();
|
|
76991
77029
|
var DEFAULT_CONFIG = {
|
|
@@ -77045,7 +77083,8 @@ function loadUserConfig() {
|
|
|
77045
77083
|
function runConfigFilePipeline(text, sourcePath) {
|
|
77046
77084
|
const versioned = upgradeConfigVersion(parseConfigText(text, sourcePath), sourcePath);
|
|
77047
77085
|
const parsedRaw = migrateLegacySourceShape(versioned, sourcePath);
|
|
77048
|
-
|
|
77086
|
+
const liftedRaw = liftExtraParamsOrThrow(parsedRaw, sourcePath);
|
|
77087
|
+
return stripRetiredExperimentalKeys(liftedRaw, sourcePath);
|
|
77049
77088
|
}
|
|
77050
77089
|
function liftExtraParamsOrThrow(parsedRaw, sourcePath) {
|
|
77051
77090
|
const where = sourcePath ? ` at ${sourcePath}` : "";
|
|
@@ -85704,8 +85743,11 @@ function assertAkmAssetWrite(source, allowedAdapters = ["akm"]) {
|
|
|
85704
85743
|
return;
|
|
85705
85744
|
throw new UsageError(`Bundle "${source.name}" uses adapter "${source.adapterId}", which does not support AKM asset writes.`, "INVALID_FLAG_VALUE");
|
|
85706
85745
|
}
|
|
85746
|
+
function isWriteCapableSourceKind(kind) {
|
|
85747
|
+
return kind === "filesystem" || kind === "git";
|
|
85748
|
+
}
|
|
85707
85749
|
function adaptConfiguredSource(runtime) {
|
|
85708
|
-
if (runtime.type
|
|
85750
|
+
if (!isWriteCapableSourceKind(runtime.type)) {
|
|
85709
85751
|
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.');
|
|
85710
85752
|
}
|
|
85711
85753
|
const kind = runtime.type;
|
|
@@ -93169,32 +93211,7 @@ var GLOBAL_OUTPUT_ARGS = {
|
|
|
93169
93211
|
init_errors();
|
|
93170
93212
|
|
|
93171
93213
|
// scripts/akm-migrate/help.txt
|
|
93172
|
-
var help_default =
|
|
93173
|
-
|
|
93174
|
-
The one migration tool for an akm installation. Every historical shape akm
|
|
93175
|
-
has ever written lives here; the CLI proper reads only current schemas.
|
|
93176
|
-
\`status\` and \`apply\` run every step, in order, and print one combined JSON
|
|
93177
|
-
plan (exit 1 when any step is blocked):
|
|
93178
|
-
|
|
93179
|
-
1. legacy config \`extraParams\` keys lifted onto first-class engine fields
|
|
93180
|
-
2. scheduler grants bound to the configured source installation that was
|
|
93181
|
-
approved (stale grants whose bundle no longer exists are removed)
|
|
93182
|
-
3. pending state.db migrations, historical-destructive ones included,
|
|
93183
|
-
with a verified sibling safety copy (the only path that admits them)
|
|
93184
|
-
4. task-v2 files to task v3, then task-v3 files to task source v4
|
|
93185
|
-
5. superseded pre-0.9.0 \`.akm\` residue and stale filesystem transactions
|
|
93186
|
-
6. live \`.akm\` writers relocated to \`$STATE\`/\`$CACHE\`, for every local
|
|
93187
|
-
bundle (distill-rejected, eval-cases, measurement verdicts, and stale
|
|
93188
|
-
improve-pipeline locks \u2014 a lock a live run still holds is left alone)
|
|
93189
|
-
|
|
93190
|
-
\`akm migrate status|apply\` wraps this executable; \`akm upgrade\` runs
|
|
93191
|
-
\`apply\` after its install step, so an image that ships akm can put either
|
|
93192
|
-
in its entrypoint (a current installation is a no-op).
|
|
93193
|
-
|
|
93194
|
-
Commands:
|
|
93195
|
-
status Inspect every pending migration without changing anything.
|
|
93196
|
-
apply [--dry-run] Back up and apply every pending migration.
|
|
93197
|
-
`;
|
|
93214
|
+
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 \u2014 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";
|
|
93198
93215
|
|
|
93199
93216
|
// scripts/akm-migrate/run-migrate.ts
|
|
93200
93217
|
init_common();
|
|
@@ -94730,10 +94747,44 @@ function applyConfigExtraParamsLift(configPath) {
|
|
|
94730
94747
|
return { applied: true, lifted, conflicts: [] };
|
|
94731
94748
|
}
|
|
94732
94749
|
|
|
94750
|
+
// scripts/akm-migrate/migrate/config-retired-experimental-keys.ts
|
|
94751
|
+
function readRawConfig2(configPath) {
|
|
94752
|
+
const text = readConfigText(configPath);
|
|
94753
|
+
if (text === undefined)
|
|
94754
|
+
return;
|
|
94755
|
+
return parseConfigText(text, configPath);
|
|
94756
|
+
}
|
|
94757
|
+
function findConfigRetiredExperimentalKeys(configPath) {
|
|
94758
|
+
const raw = readRawConfig2(configPath);
|
|
94759
|
+
if (!raw)
|
|
94760
|
+
return { removed: [] };
|
|
94761
|
+
return { removed: retiredExperimentalKeysIn(raw).map((key) => `experimental.${key}`) };
|
|
94762
|
+
}
|
|
94763
|
+
function applyConfigRetiredExperimentalKeys(configPath) {
|
|
94764
|
+
const raw = readRawConfig2(configPath);
|
|
94765
|
+
if (!raw)
|
|
94766
|
+
return { applied: false, removed: [] };
|
|
94767
|
+
const retired = retiredExperimentalKeysIn(raw);
|
|
94768
|
+
if (retired.length === 0)
|
|
94769
|
+
return { applied: false, removed: [] };
|
|
94770
|
+
const experimental = { ...raw.experimental };
|
|
94771
|
+
for (const key of retired)
|
|
94772
|
+
delete experimental[key];
|
|
94773
|
+
const config = { ...raw, experimental };
|
|
94774
|
+
const release = acquireConfigLock();
|
|
94775
|
+
try {
|
|
94776
|
+
backupExistingConfig(configPath);
|
|
94777
|
+
writeConfigAtomic(configPath, config);
|
|
94778
|
+
} finally {
|
|
94779
|
+
release();
|
|
94780
|
+
}
|
|
94781
|
+
return { applied: true, removed: retired.map((key) => `experimental.${key}`) };
|
|
94782
|
+
}
|
|
94783
|
+
|
|
94733
94784
|
// scripts/akm-migrate/migrate/config-scheduler-source-ids.ts
|
|
94734
94785
|
init_asset_ref();
|
|
94735
94786
|
init_bundle_id();
|
|
94736
|
-
function
|
|
94787
|
+
function readRawConfig3(configPath) {
|
|
94737
94788
|
const text = readConfigText(configPath);
|
|
94738
94789
|
return text === undefined ? undefined : parseConfigText(text, configPath);
|
|
94739
94790
|
}
|
|
@@ -94788,13 +94839,13 @@ function implicitBundleSourceId(raw, bundleId) {
|
|
|
94788
94839
|
return implicitId === bundleId ? filesystemBundleSourceId(root2) : undefined;
|
|
94789
94840
|
}
|
|
94790
94841
|
function findConfigSchedulerSourceIdMigration(configPath) {
|
|
94791
|
-
const raw =
|
|
94842
|
+
const raw = readRawConfig3(configPath);
|
|
94792
94843
|
return Object.freeze({ changes: Object.freeze(raw ? migrationChanges(raw) : []) });
|
|
94793
94844
|
}
|
|
94794
94845
|
function applyConfigSchedulerSourceIdMigration(configPath) {
|
|
94795
94846
|
const release = acquireConfigLock();
|
|
94796
94847
|
try {
|
|
94797
|
-
const raw =
|
|
94848
|
+
const raw = readRawConfig3(configPath);
|
|
94798
94849
|
if (!raw)
|
|
94799
94850
|
return Object.freeze({ applied: false, changes: Object.freeze([]) });
|
|
94800
94851
|
const changes = migrationChanges(raw);
|
|
@@ -97942,7 +97993,7 @@ var GATE_OUTCOMES = {
|
|
|
97942
97993
|
"auto-rejected": true
|
|
97943
97994
|
};
|
|
97944
97995
|
function validatePresentMetadata(meta) {
|
|
97945
|
-
const stringFields = ["sourceRun", "beforeHash", "backupContent"];
|
|
97996
|
+
const stringFields = ["sourceRun", "beforeHash", "beforeHashNormalized", "backupContent"];
|
|
97946
97997
|
for (const field of stringFields) {
|
|
97947
97998
|
if (Object.hasOwn(meta, field) && typeof meta[field] !== "string")
|
|
97948
97999
|
invalidPresentField(field);
|
|
@@ -98022,6 +98073,7 @@ function proposalRowToProposal(row) {
|
|
|
98022
98073
|
changes,
|
|
98023
98074
|
...proposedTarget !== undefined ? { proposedTarget } : {},
|
|
98024
98075
|
...typeof meta.beforeHash === "string" ? { beforeHash: meta.beforeHash } : {},
|
|
98076
|
+
...typeof meta.beforeHashNormalized === "string" ? { beforeHashNormalized: meta.beforeHashNormalized } : {},
|
|
98025
98077
|
...meta.review !== undefined ? { review: meta.review } : {},
|
|
98026
98078
|
...typeof meta.confidence === "number" ? { confidence: meta.confidence } : {},
|
|
98027
98079
|
...meta.gateDecision !== undefined ? { gateDecision: meta.gateDecision } : {},
|
|
@@ -98048,6 +98100,8 @@ function proposalToRowValues(proposal, stashDir) {
|
|
|
98048
98100
|
metaObj.proposedTarget = currentProposalTarget(proposal.proposedTarget);
|
|
98049
98101
|
if (proposal.beforeHash !== undefined)
|
|
98050
98102
|
metaObj.beforeHash = proposal.beforeHash;
|
|
98103
|
+
if (proposal.beforeHashNormalized !== undefined)
|
|
98104
|
+
metaObj.beforeHashNormalized = proposal.beforeHashNormalized;
|
|
98051
98105
|
if (proposal.sourceRun !== undefined)
|
|
98052
98106
|
metaObj.sourceRun = proposal.sourceRun;
|
|
98053
98107
|
if (proposal.review !== undefined)
|
|
@@ -104011,12 +104065,16 @@ async function runMigration(options) {
|
|
|
104011
104065
|
if (apply && configExtraParams.applied)
|
|
104012
104066
|
resetConfigCache();
|
|
104013
104067
|
const pendingLift = apply ? undefined : configExtraParams.pending;
|
|
104068
|
+
const configRetiredExperimentalKeys = apply ? applyConfigRetiredExperimentalKeys(configPath) : { pending: findConfigRetiredExperimentalKeys(configPath) };
|
|
104069
|
+
if (apply && configRetiredExperimentalKeys.applied)
|
|
104070
|
+
resetConfigCache();
|
|
104014
104071
|
if (pendingLift && pendingLift.lifted.length > 0) {
|
|
104015
104072
|
return {
|
|
104016
104073
|
schemaVersion: 1,
|
|
104017
104074
|
status: "blocked",
|
|
104018
104075
|
blockers: pendingLift.lifted,
|
|
104019
104076
|
configExtraParams,
|
|
104077
|
+
configRetiredExperimentalKeys,
|
|
104020
104078
|
stateMigrations: { pending: listPendingStateMigrations() }
|
|
104021
104079
|
};
|
|
104022
104080
|
}
|
|
@@ -104031,6 +104089,7 @@ async function runMigration(options) {
|
|
|
104031
104089
|
blockers: pendingSchedulerBindings.changes.map((change) => `${change.kind === "bind" ? "bind" : "drop"} scheduler activation ${change.ref}` + (change.reason ? `: ${change.reason}` : "")),
|
|
104032
104090
|
configExtraParams,
|
|
104033
104091
|
configSchedulerSourceIds,
|
|
104092
|
+
configRetiredExperimentalKeys,
|
|
104034
104093
|
stateMigrations: { pending: listPendingStateMigrations() }
|
|
104035
104094
|
};
|
|
104036
104095
|
}
|
|
@@ -104050,12 +104109,14 @@ async function runMigration(options) {
|
|
|
104050
104109
|
}
|
|
104051
104110
|
const stateStatus = "pending" in stateMigrations && stateMigrations.pending.length > 0 ? "ready" : "current";
|
|
104052
104111
|
const schedulerStatus = "pending" in schedulerActivation && schedulerActivation.pending.length > 0 ? "ready" : "current";
|
|
104112
|
+
const retiredKeysStatus = "pending" in configRetiredExperimentalKeys && configRetiredExperimentalKeys.pending.removed.length > 0 ? "ready" : "current";
|
|
104053
104113
|
return {
|
|
104054
104114
|
schemaVersion: 1,
|
|
104055
|
-
status: worstStatus(worstStatus(worstStatus(taskV3.status, taskV4.status), stateStatus), schedulerStatus),
|
|
104115
|
+
status: worstStatus(worstStatus(worstStatus(worstStatus(taskV3.status, taskV4.status), stateStatus), schedulerStatus), retiredKeysStatus),
|
|
104056
104116
|
blockers: [...taskV3.blockers, ...taskV4.blockers],
|
|
104057
104117
|
configExtraParams,
|
|
104058
104118
|
configSchedulerSourceIds,
|
|
104119
|
+
configRetiredExperimentalKeys,
|
|
104059
104120
|
stateMigrations,
|
|
104060
104121
|
schedulerActivation,
|
|
104061
104122
|
taskV3Migration: taskV3.taskV3Migration,
|
|
@@ -684,6 +684,22 @@ export function getIndexedFilePaths(db) {
|
|
|
684
684
|
.all();
|
|
685
685
|
return new Set(rows.map((r) => r.file_path));
|
|
686
686
|
}
|
|
687
|
+
/**
|
|
688
|
+
* `entries.file_path -> content_hash` for every currently-indexed file that
|
|
689
|
+
* carries a stored hash. Used by per-file staleness detection
|
|
690
|
+
* (`hasNewerIndexableFiles`, R6) to tell "edited after the last build" apart
|
|
691
|
+
* from "already re-indexed with this exact content after the last build" —
|
|
692
|
+
* `indexWrittenAssets` upserts a fresh row (and its `content_hash`) without
|
|
693
|
+
* bumping `builtAt`, so mtime alone cannot distinguish the two cases.
|
|
694
|
+
*/
|
|
695
|
+
export function getIndexedFileHashes(db) {
|
|
696
|
+
const rows = db
|
|
697
|
+
.prepare(`SELECT file_path, content_hash FROM entries
|
|
698
|
+
WHERE file_path IS NOT NULL AND file_path <> ''
|
|
699
|
+
AND content_hash IS NOT NULL`)
|
|
700
|
+
.all();
|
|
701
|
+
return new Map(rows.map((r) => [r.file_path, r.content_hash]));
|
|
702
|
+
}
|
|
687
703
|
/**
|
|
688
704
|
* Resolve a single `entries.file_path` by primary key, or `undefined` if no
|
|
689
705
|
* row matches.
|
|
@@ -732,6 +748,33 @@ export function getEntryByRef(db, ref) {
|
|
|
732
748
|
const id = findEntryIdByRef(db, ref);
|
|
733
749
|
return id === undefined ? null : { id };
|
|
734
750
|
}
|
|
751
|
+
/** Build a {@link LiveRefSnapshot} from the current `entries` table. */
|
|
752
|
+
export function getLiveRefSnapshot(db) {
|
|
753
|
+
const rows = db.prepare("SELECT item_ref FROM entries").all();
|
|
754
|
+
const itemRefs = new Set();
|
|
755
|
+
const conceptIds = new Set();
|
|
756
|
+
for (const { item_ref } of rows) {
|
|
757
|
+
itemRefs.add(item_ref);
|
|
758
|
+
const boundary = item_ref.indexOf("//");
|
|
759
|
+
if (boundary >= 0)
|
|
760
|
+
conceptIds.add(item_ref.slice(boundary + 2));
|
|
761
|
+
}
|
|
762
|
+
return { itemRefs, conceptIds };
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* `getEntryByRef`'s liveness check (bundle-qualified exact match, or bare
|
|
766
|
+
* `//conceptId` suffix match across bundles, each tried with the `.md`
|
|
767
|
+
* toggle {@link withMdVariants} applies) against a prebuilt
|
|
768
|
+
* {@link LiveRefSnapshot} instead of the database — no query per call.
|
|
769
|
+
*/
|
|
770
|
+
export function isRefLiveInSnapshot(snapshot, ref) {
|
|
771
|
+
const parsed = parseBundleRef(ref);
|
|
772
|
+
const conceptVariants = withMdVariants(parsed.conceptId);
|
|
773
|
+
if (parsed.bundle !== undefined) {
|
|
774
|
+
return conceptVariants.some((conceptId) => snapshot.itemRefs.has(`${parsed.bundle}//${conceptId}`));
|
|
775
|
+
}
|
|
776
|
+
return conceptVariants.some((conceptId) => snapshot.conceptIds.has(conceptId));
|
|
777
|
+
}
|
|
735
778
|
/**
|
|
736
779
|
* The fully-qualified `item_ref` (`<bundle>//<conceptId>`, the durable stored
|
|
737
780
|
* spelling — spec §11.1 D-R3) for an entry `id`, or `null` when the row is gone
|
|
@@ -107,7 +107,7 @@ const GATE_OUTCOMES = {
|
|
|
107
107
|
"auto-rejected": true,
|
|
108
108
|
};
|
|
109
109
|
function validatePresentMetadata(meta) {
|
|
110
|
-
const stringFields = ["sourceRun", "beforeHash", "backupContent"];
|
|
110
|
+
const stringFields = ["sourceRun", "beforeHash", "beforeHashNormalized", "backupContent"];
|
|
111
111
|
for (const field of stringFields) {
|
|
112
112
|
if (Object.hasOwn(meta, field) && typeof meta[field] !== "string")
|
|
113
113
|
invalidPresentField(field);
|
|
@@ -224,6 +224,7 @@ export function proposalRowToProposal(row) {
|
|
|
224
224
|
changes,
|
|
225
225
|
...(proposedTarget !== undefined ? { proposedTarget } : {}),
|
|
226
226
|
...(typeof meta.beforeHash === "string" ? { beforeHash: meta.beforeHash } : {}),
|
|
227
|
+
...(typeof meta.beforeHashNormalized === "string" ? { beforeHashNormalized: meta.beforeHashNormalized } : {}),
|
|
227
228
|
...(meta.review !== undefined ? { review: meta.review } : {}),
|
|
228
229
|
...(typeof meta.confidence === "number" ? { confidence: meta.confidence } : {}),
|
|
229
230
|
...(meta.gateDecision !== undefined ? { gateDecision: meta.gateDecision } : {}),
|
|
@@ -274,6 +275,8 @@ export function proposalToRowValues(proposal, stashDir) {
|
|
|
274
275
|
metaObj.proposedTarget = currentProposalTarget(proposal.proposedTarget);
|
|
275
276
|
if (proposal.beforeHash !== undefined)
|
|
276
277
|
metaObj.beforeHash = proposal.beforeHash;
|
|
278
|
+
if (proposal.beforeHashNormalized !== undefined)
|
|
279
|
+
metaObj.beforeHashNormalized = proposal.beforeHashNormalized;
|
|
277
280
|
if (proposal.sourceRun !== undefined)
|
|
278
281
|
metaObj.sourceRun = proposal.sourceRun;
|
|
279
282
|
if (proposal.review !== undefined)
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* state.db integrity + reclaimable-space probes (R0, tier0-0917).
|
|
6
|
+
*
|
|
7
|
+
* `akm health`'s `state-db-integrity` check (src/commands/health/checks.ts)
|
|
8
|
+
* is a pure projection like every other check, so the actual IO lives here:
|
|
9
|
+
* a read-only `PRAGMA quick_check` and a read-only freelist/page-count read.
|
|
10
|
+
* Both open their own short-lived connection via the plain {@link openDatabase}
|
|
11
|
+
* opener — deliberately bypassing `openStateDatabase`'s managed-open/migration
|
|
12
|
+
* machinery (src/core/state-db.ts), since a corrupt database must not need a
|
|
13
|
+
* clean migration-ledger read just to report itself as corrupt.
|
|
14
|
+
*
|
|
15
|
+
* {@link vacuumStateDbIfReclaimable} is the post-purge VACUUM step: given an
|
|
16
|
+
* already-open read-write connection (VACUUM cannot run inside a transaction,
|
|
17
|
+
* and a read-only handle cannot run it at all) and a freelist reading, it
|
|
18
|
+
* VACUUMs only when the freelist ratio crosses {@link STATE_DB_FREELIST_WARN_RATIO}
|
|
19
|
+
* and never throws — a locked/busy database is reported, not raised.
|
|
20
|
+
*
|
|
21
|
+
* @module storage/state-db-integrity
|
|
22
|
+
*/
|
|
23
|
+
import { appendEvent } from "../core/events.js";
|
|
24
|
+
import { openDatabase } from "./database.js";
|
|
25
|
+
import { SQLITE_BUSY_TIMEOUT_MS } from "./sqlite-pragmas.js";
|
|
26
|
+
/** How many corruption errors `PRAGMA quick_check` collects before it stops scanning and returns. */
|
|
27
|
+
const QUICK_CHECK_ERROR_LIMIT = 10;
|
|
28
|
+
/** Above this fraction of free pages, `state-db-integrity` warns and a post-purge pass VACUUMs. */
|
|
29
|
+
export const STATE_DB_FREELIST_WARN_RATIO = 0.5;
|
|
30
|
+
/** Event appended by {@link vacuumStateDbIfReclaimable} after a successful VACUUM. */
|
|
31
|
+
export const STATE_DB_VACUUMED_EVENT = "state_db_vacuumed";
|
|
32
|
+
function firstColumn(row) {
|
|
33
|
+
return row === undefined ? undefined : Object.values(row)[0];
|
|
34
|
+
}
|
|
35
|
+
function openReadonlyStateDb(dbPath) {
|
|
36
|
+
const db = openDatabase(dbPath, { readonly: true, create: false });
|
|
37
|
+
// Read-only handles cannot run journal_mode/foreign_keys (write operations),
|
|
38
|
+
// but busy_timeout is legal — see openReadonlyExistingDatabase's identical
|
|
39
|
+
// rationale in src/storage/repositories/index-connection.ts.
|
|
40
|
+
db.exec(`PRAGMA busy_timeout = ${SQLITE_BUSY_TIMEOUT_MS}`);
|
|
41
|
+
return db;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Run `PRAGMA quick_check(N)` against `dbPath` read-only. Sub-second on a
|
|
45
|
+
* healthy multi-hundred-MB file; on a corrupt one, `N` bounds how many errors
|
|
46
|
+
* SQLite collects before it stops scanning, which keeps the check's runtime
|
|
47
|
+
* bounded even against a badly corrupt file.
|
|
48
|
+
*/
|
|
49
|
+
export function runStateDbQuickCheck(dbPath) {
|
|
50
|
+
let db;
|
|
51
|
+
try {
|
|
52
|
+
db = openReadonlyStateDb(dbPath);
|
|
53
|
+
const rows = db.prepare(`PRAGMA quick_check(${QUICK_CHECK_ERROR_LIMIT})`).all();
|
|
54
|
+
const lines = rows.map((row) => String(firstColumn(row)));
|
|
55
|
+
const ok = lines.length === 1 && lines[0] === "ok";
|
|
56
|
+
return { ok, lines };
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
return { ok: false, lines: [], error: err instanceof Error ? err.message : String(err) };
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
db?.close();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Read `PRAGMA freelist_count` / `PRAGMA page_count` off an already-open
|
|
67
|
+
* connection. Shared by {@link getStateDbFreelistInfo} (which opens its own
|
|
68
|
+
* read-only handle) and the post-purge VACUUM call site, which must read the
|
|
69
|
+
* freelist off the same read-write connection the purge just used rather
|
|
70
|
+
* than open a second one.
|
|
71
|
+
*/
|
|
72
|
+
export function readFreelistInfo(db) {
|
|
73
|
+
const freelistCount = Number(firstColumn(db.prepare("PRAGMA freelist_count").get()) ?? 0);
|
|
74
|
+
const pageCount = Number(firstColumn(db.prepare("PRAGMA page_count").get()) ?? 0);
|
|
75
|
+
return { freelistCount, pageCount, ratio: pageCount > 0 ? freelistCount / pageCount : 0 };
|
|
76
|
+
}
|
|
77
|
+
/** Read `PRAGMA freelist_count` / `PRAGMA page_count` — how much of state.db is reclaimable by VACUUM. */
|
|
78
|
+
export function getStateDbFreelistInfo(dbPath) {
|
|
79
|
+
let db;
|
|
80
|
+
try {
|
|
81
|
+
db = openReadonlyStateDb(dbPath);
|
|
82
|
+
return readFreelistInfo(db);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
return { freelistCount: 0, pageCount: 0, ratio: 0, error: err instanceof Error ? err.message : String(err) };
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
db?.close();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* VACUUM `db` when `freelist.ratio` exceeds {@link STATE_DB_FREELIST_WARN_RATIO},
|
|
93
|
+
* appending a {@link STATE_DB_VACUUMED_EVENT} recording pages before/after.
|
|
94
|
+
* Intended to run immediately after the retention purge, on the same
|
|
95
|
+
* read-write connection the purge just used. Never throws: a locked/busy
|
|
96
|
+
* database (another writer holds the file right now) is reported via
|
|
97
|
+
* `reason: "busy"` rather than raised, since this is opportunistic
|
|
98
|
+
* maintenance and must not fail the purge pass it follows.
|
|
99
|
+
*
|
|
100
|
+
* The event is appended via `appendEvent` (not a direct `insertEvent` on
|
|
101
|
+
* `db`) so it honors the caller's `EventsContext` — `readOnly` suppresses
|
|
102
|
+
* the write and an injected `now` is used for `ts` — the same as every
|
|
103
|
+
* other event `runRetentionPurgePass` appends in this callback.
|
|
104
|
+
*/
|
|
105
|
+
export function vacuumStateDbIfReclaimable(db, freelist, eventsCtx) {
|
|
106
|
+
if (freelist.ratio <= STATE_DB_FREELIST_WARN_RATIO) {
|
|
107
|
+
return { ran: false, reason: "below-threshold", pagesBefore: freelist.pageCount };
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
db.exec("VACUUM");
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
114
|
+
const busy = /busy|locked/i.test(message);
|
|
115
|
+
return { ran: false, reason: busy ? "busy" : "error", pagesBefore: freelist.pageCount, error: message };
|
|
116
|
+
}
|
|
117
|
+
const pagesAfter = Number(firstColumn(db.prepare("PRAGMA page_count").get()) ?? 0);
|
|
118
|
+
appendEvent({
|
|
119
|
+
eventType: STATE_DB_VACUUMED_EVENT,
|
|
120
|
+
metadata: { pagesBefore: freelist.pageCount, pagesAfter, freelistRatioBefore: freelist.ratio },
|
|
121
|
+
}, eventsCtx);
|
|
122
|
+
return { ran: true, pagesBefore: freelist.pageCount, pagesAfter };
|
|
123
|
+
}
|
package/docs/reference/cli.md
CHANGED
|
@@ -387,7 +387,7 @@ Primary result fields:
|
|
|
387
387
|
| Field | Description |
|
|
388
388
|
| --- | --- |
|
|
389
389
|
| `status` | Overall health verdict: `pass`, `warn`, or `fail` |
|
|
390
|
-
| `hardChecks` | Deterministic checks such as `state-db-schema`, `state-db-round-trip`, `state-db-migrations`, `task-log-backing`, `active-runs`, `default-engine`, `model-map-files`, `default-llm-engine`, `configured-engines`, and `active-improve-strategy` |
|
|
390
|
+
| `hardChecks` | Deterministic checks such as `state-db-schema`, `state-db-round-trip`, `state-db-integrity`, `state-db-migrations`, `task-log-backing`, `active-runs`, `default-engine`, `model-map-files`, `default-llm-engine`, `configured-engines`, and `active-improve-strategy` |
|
|
391
391
|
| `advisories` | Non-fatal warnings including `semantic-search-runtime`, `session-extraction` (akmExtract pipeline health), `cli-version` (installed vs latest release), `thinking-control` (an `enableThinking: false` engine whose recorded usage still shows reasoning tokens), and `engine-last-used` (an engine bound to an enabled improve process with no recorded use in 30 days) |
|
|
392
392
|
| `metrics` | Aggregate task/runtime metrics: `taskFailRate`, `agentFailureRate`, `stuckActiveRuns`, `logBackingRate`, `probeRoundTripMs` |
|
|
393
393
|
| `improve` | Recent improve-loop counts derived from `improve_invoked`, `improve_skipped`, and `improve_completed` events |
|
|
@@ -1673,16 +1673,25 @@ in order:
|
|
|
1673
1673
|
|
|
1674
1674
|
1. legacy config `extraParams` keys lifted onto first-class engine fields
|
|
1675
1675
|
(`configExtraParams`);
|
|
1676
|
-
2.
|
|
1676
|
+
2. retired `experimental.*` config keys removed, today `workflowEngine`
|
|
1677
|
+
(`configRetiredExperimentalKeys`) — config loading already ignores them
|
|
1678
|
+
with a one-time warning, so this only cleans the file;
|
|
1679
|
+
3. scheduler grants bound to the configured source installation that was
|
|
1680
|
+
approved, with stale grants for removed bundles dropped
|
|
1681
|
+
(`configSchedulerSourceIds`);
|
|
1682
|
+
4. pending `state.db` migrations, historical-destructive ones included, with
|
|
1677
1683
|
a verified sibling safety copy (`stateMigrations`) — the only path besides
|
|
1678
1684
|
`akm upgrade` that admits released migration 018, which an ordinary
|
|
1679
1685
|
command refuses;
|
|
1680
|
-
|
|
1686
|
+
5. source-owned schedule enablement converted to host-local scheduler grants
|
|
1687
|
+
(`schedulerActivation`);
|
|
1688
|
+
6. task-v2 files to task v3, then task-v3 files to task source v4
|
|
1681
1689
|
(`taskV3Migration`, `taskV4Migration`), each keeping its own lock, backup,
|
|
1682
1690
|
prevalidation, and rollback, so a file blocked in the first generation does
|
|
1683
1691
|
not stop the second from converting files already at `version: 3`;
|
|
1684
|
-
|
|
1685
|
-
(`deadResidue`, `staleTxns`)
|
|
1692
|
+
7. superseded pre-0.9.0 `.akm` residue and stale filesystem transactions
|
|
1693
|
+
(`deadResidue`, `staleTxns`), then live `.akm` writers relocated to
|
|
1694
|
+
`$STATE`/`$CACHE` (`writerRelocation`).
|
|
1686
1695
|
|
|
1687
1696
|
```sh
|
|
1688
1697
|
akm migrate status
|
|
@@ -2459,8 +2468,9 @@ configures a judgment engine. Each row carries `enabled`, the resolved
|
|
|
2459
2468
|
`engine`/`model` (llm-backed processes only) and `engineKind`, this process's
|
|
2460
2469
|
own lowering `notices`, and — for reflect/distill/consolidate only —
|
|
2461
2470
|
`eligibleRefs`, the count of this run's `effectiveRefs` the process would act
|
|
2462
|
-
on (`shouldSkipRef`'s allowedTypes/
|
|
2463
|
-
per-ref matrix, to keep the envelope
|
|
2471
|
+
on (`shouldSkipRef`'s allowedTypes/excludeRefPrefixes (reflect only)/
|
|
2472
|
+
process-disabled check; a count, not a per-ref matrix, to keep the envelope
|
|
2473
|
+
bounded). A row that could not resolve an
|
|
2464
2474
|
engine or credential carries `unavailable: {configKey, reason}` — the same
|
|
2465
2475
|
data behind `skippedProcesses` above, reshaped per process. When the process
|
|
2466
2476
|
resolved a real engine whose credential just isn't reachable here, the row
|
|
@@ -208,6 +208,7 @@ the set of types the code actually emits at HEAD (verified against every
|
|
|
208
208
|
| `events_purged` | Old events deleted by improve maintenance (90-day default retention) | `purgedCount`, `retentionDays` |
|
|
209
209
|
| `improve_runs_purged` | Old `improve_runs` rows deleted by improve maintenance (same retention window as events) | `purgedCount`, `retentionDays` |
|
|
210
210
|
| `improve_cycle_metrics_purged` | Old `improve_cycle_metrics` rows (365-day retention) deleted by improve maintenance | `purgedCount`, `retentionDays` |
|
|
211
|
+
| `state_db_vacuumed` | state.db was VACUUMed after the retention purge because more than half its pages were free | `pagesBefore`, `pagesAfter`, `freelistRatioBefore` |
|
|
211
212
|
| `task_logs_purged` | Old scheduled-task log files purged by improve maintenance | |
|
|
212
213
|
|
|
213
214
|
*Workflows*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akm-cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.17-alpha.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cursor.",
|
|
6
6
|
"keywords": [
|
package/schemas/akm-config.json
CHANGED
|
@@ -796,6 +796,13 @@
|
|
|
796
796
|
"minLength": 1
|
|
797
797
|
}
|
|
798
798
|
},
|
|
799
|
+
"excludeRefPrefixes": {
|
|
800
|
+
"type": "array",
|
|
801
|
+
"items": {
|
|
802
|
+
"type": "string",
|
|
803
|
+
"minLength": 1
|
|
804
|
+
}
|
|
805
|
+
},
|
|
799
806
|
"limit": {
|
|
800
807
|
"type": "integer",
|
|
801
808
|
"exclusiveMinimum": 0
|
|
@@ -1207,6 +1214,10 @@
|
|
|
1207
1214
|
},
|
|
1208
1215
|
"fullScan": {
|
|
1209
1216
|
"type": "boolean"
|
|
1217
|
+
},
|
|
1218
|
+
"maxChunksPerAsset": {
|
|
1219
|
+
"type": "integer",
|
|
1220
|
+
"exclusiveMinimum": 0
|
|
1210
1221
|
}
|
|
1211
1222
|
},
|
|
1212
1223
|
"additionalProperties": true
|
|
@@ -2578,6 +2589,13 @@
|
|
|
2578
2589
|
"minLength": 1
|
|
2579
2590
|
}
|
|
2580
2591
|
},
|
|
2592
|
+
"excludeRefPrefixes": {
|
|
2593
|
+
"type": "array",
|
|
2594
|
+
"items": {
|
|
2595
|
+
"type": "string",
|
|
2596
|
+
"minLength": 1
|
|
2597
|
+
}
|
|
2598
|
+
},
|
|
2581
2599
|
"limit": {
|
|
2582
2600
|
"type": "integer",
|
|
2583
2601
|
"exclusiveMinimum": 0
|
|
@@ -2989,6 +3007,10 @@
|
|
|
2989
3007
|
},
|
|
2990
3008
|
"fullScan": {
|
|
2991
3009
|
"type": "boolean"
|
|
3010
|
+
},
|
|
3011
|
+
"maxChunksPerAsset": {
|
|
3012
|
+
"type": "integer",
|
|
3013
|
+
"exclusiveMinimum": 0
|
|
2992
3014
|
}
|
|
2993
3015
|
},
|
|
2994
3016
|
"additionalProperties": true
|
|
@@ -3755,6 +3777,13 @@
|
|
|
3755
3777
|
"minLength": 1
|
|
3756
3778
|
}
|
|
3757
3779
|
},
|
|
3780
|
+
"excludeRefPrefixes": {
|
|
3781
|
+
"type": "array",
|
|
3782
|
+
"items": {
|
|
3783
|
+
"type": "string",
|
|
3784
|
+
"minLength": 1
|
|
3785
|
+
}
|
|
3786
|
+
},
|
|
3758
3787
|
"limit": {
|
|
3759
3788
|
"type": "integer",
|
|
3760
3789
|
"exclusiveMinimum": 0
|
|
@@ -3883,6 +3912,10 @@
|
|
|
3883
3912
|
"fullScan": {
|
|
3884
3913
|
"type": "boolean"
|
|
3885
3914
|
},
|
|
3915
|
+
"maxChunksPerAsset": {
|
|
3916
|
+
"type": "integer",
|
|
3917
|
+
"exclusiveMinimum": 0
|
|
3918
|
+
},
|
|
3886
3919
|
"defaultSince": {
|
|
3887
3920
|
"type": "string",
|
|
3888
3921
|
"minLength": 1
|
|
@@ -4148,6 +4181,13 @@
|
|
|
4148
4181
|
"minLength": 1
|
|
4149
4182
|
}
|
|
4150
4183
|
},
|
|
4184
|
+
"excludeRefPrefixes": {
|
|
4185
|
+
"type": "array",
|
|
4186
|
+
"items": {
|
|
4187
|
+
"type": "string",
|
|
4188
|
+
"minLength": 1
|
|
4189
|
+
}
|
|
4190
|
+
},
|
|
4151
4191
|
"limit": {
|
|
4152
4192
|
"type": "integer",
|
|
4153
4193
|
"exclusiveMinimum": 0
|
|
@@ -4559,6 +4599,10 @@
|
|
|
4559
4599
|
},
|
|
4560
4600
|
"fullScan": {
|
|
4561
4601
|
"type": "boolean"
|
|
4602
|
+
},
|
|
4603
|
+
"maxChunksPerAsset": {
|
|
4604
|
+
"type": "integer",
|
|
4605
|
+
"exclusiveMinimum": 0
|
|
4562
4606
|
}
|
|
4563
4607
|
},
|
|
4564
4608
|
"additionalProperties": true
|