{"record":{"id":"9b5dd89b45a96268","repo":"deepseek-ai/deepseek-harness","slug":"name-retainratio-retention-retainratio-mu","errorCode":null,"errorMessage":"${name}: retainRatio (${retention.retainRatio}) must be less than the resolved thresholdRatio (${thresholdRatio})","messagePattern":"(.+?): retainRatio \\((.+?)\\) must be less than the resolved thresholdRatio \\((.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/compaction/compaction-basic/src/config.ts","lineNumber":186,"sourceCode":"\n/** Choose an explicit retention form or inherit the already-resolved fallback. */\nfunction resolveRetention(\n  config: CompactionPolicyConfig,\n  fallback: ResolvedRetention,\n): ResolvedRetention {\n  if (config.retainTokens !== undefined) return { retainTokens: config.retainTokens }\n  if (config.retainRatio !== undefined) return { retainRatio: config.retainRatio }\n  return fallback\n}\n\n/** Reject a capacity-independent retention conflict at plugin load. */\nfunction validateRatioRetention(\n  thresholdRatio: number,\n  retention: ResolvedRetention,\n  name: string,\n): void {\n  if (retention.retainRatio !== undefined && retention.retainRatio >= thresholdRatio) {\n    throw new Error(\n      `${name}: retainRatio (${retention.retainRatio}) must be less than `\n      + `the resolved thresholdRatio (${thresholdRatio})`,\n    )\n  }\n}\n\n/** Validate, detach, and reject duplicate exact-target policies. */\nfunction resolveModelPolicies(configured: unknown): ModelCompactPolicyConfig[] {\n  if (configured === undefined) return []\n  if (!Array.isArray(configured)) {\n    throw new Error('BasicCompactionConfig: modelPolicies must be an array')\n  }\n  const seen = new Set<string>()\n  return configured.map((source: unknown, index) => {\n    const name = `BasicCompactionConfig: modelPolicies[${index}]`\n    assertModelPolicy(source, name)\n    const key = `${source.provider}\\u0000${source.model}`\n    if (seen.has(key)) {","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/deepseek-ai/deepseek-harness/blob/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e/packages/compaction/compaction-basic/src/config.ts#L168-L204","documentation":"resolveConfig enforces, at plugin load, that the resolved retainRatio stays strictly below the resolved thresholdRatio — for the top level and for every modelPolicies entry (an override's retainRatio is checked against its own or the inherited thresholdRatio). Otherwise the verbatim tail kept after compaction would meet or exceed the pressure that triggers compaction.","triggerScenarios":"cordis.yml sets retainRatio at or above thresholdRatio directly (thresholdRatio: 0.5, retainRatio: 0.6), or lowers thresholdRatio below the default retainRatio (thresholdRatio: 0.1 with default retainRatio 0.16), or a modelPolicies entry overrides only one side into conflict.","commonSituations":"Tuning for a larger kept tail and forgetting the ordering constraint; lowering thresholdRatio to compact earlier while keeping default retention; per-model overrides that change one ratio only.","solutions":["Keep retainRatio strictly below thresholdRatio (defaults: 0.16 below 0.8).","When lowering thresholdRatio, lower retainRatio in the same change — e.g. thresholdRatio: 0.1 needs retainRatio below 0.1.","If absolute control of the tail is needed, use retainTokens instead — it is mutually exclusive with retainRatio and is validated per target at spec time."],"exampleFix":"# before — default retainRatio 0.16 is not below the lowered threshold\nthresholdRatio: 0.1\n\n# after — move both together\nthresholdRatio: 0.1\nretainRatio: 0.05","handlingStrategy":"validation","validationCode":"const thresholdRatio = config.thresholdRatio ?? 0.8\nconst retainRatio = config.retainRatio ?? 0.16\nif (retainRatio >= thresholdRatio) {\n  throw new Error('retainRatio must be strictly below thresholdRatio before load')\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always change thresholdRatio and retainRatio as a pair.","Remember the defaults (0.8 / 0.16) when overriding only one side.","Ratios live in (0, 1]; absolute tail budgets belong in retainTokens."],"tags":["compaction","config","validation","ratios","cordis-yml"],"backgroundTag":"config-validation-failed","analyzedSha":"b150a551b8d465e31e418e1b2eaf5e79bbb7d28e","analyzedAt":"2026-08-24T18:12:29.105Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}