Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions docs/content/extensibility/adaptive-skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ is disabled by default.
"rollbackImprovementThreshold": 0.05,
"trajectoryCapture": {
"enabledAgentIds": [],
"storeDir": ""
"storeDir": "",
"retentionDays": 365,
"retentionDaysByTenant": {}
}
}
}
Expand All @@ -66,6 +68,10 @@ Key settings:
- `trajectoryCapture.storeDir`: optional trajectory store location; empty uses
a `trajectories/` directory beside the runtime database, absolute paths are
used as-is, and relative paths resolve under the runtime home directory
- `trajectoryCapture.retentionDays`: trajectory JSONL retention window; default
is 365 days and `0` disables trajectory pruning
- `trajectoryCapture.retentionDaysByTenant`: optional per-coworker retention
overrides keyed by tenant ID; trajectory tenants currently map to agent IDs

Legacy `skillCognee` config input is still normalized into `adaptiveSkills` for
backward compatibility.
Expand All @@ -90,12 +96,14 @@ Feedback is attached to the most recent observation for the same session.

## Retention

Observation queries are windowed, but storage is also pruned now. On each
Observation queries are windowed, but storage is also pruned. On each
inspection interval the heartbeat deletes `skill_observations` rows older than
`observationRetentionDays`.
`observationRetentionDays` and removes expired trajectory JSONL files according
to the trajectory retention policy.

This keeps high-traffic skills from accumulating unbounded observation history
while preserving the amendment history table as the durable review log.
This keeps high-traffic skills from accumulating unbounded observation and
trajectory history while preserving the amendment history table as the durable
review log.

## Operator Surfaces

Expand Down
4 changes: 3 additions & 1 deletion docs/content/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ saved revision history directly.
`adaptiveSkills.trajectoryCapture.enabledAgentIds`; when
`adaptiveSkills.trajectoryCapture.storeDir` is empty, trajectories are stored
beside the runtime database, absolute paths are used as-is, and relative paths
resolve under the runtime home directory
resolve under the runtime home directory; trajectory retention defaults to
`adaptiveSkills.trajectoryCapture.retentionDays: 365` and can be overridden
per coworker with `adaptiveSkills.trajectoryCapture.retentionDaysByTenant`
- `imessage.*` for the dual-backend local or BlueBubbles iMessage transport;
prefer storing the BlueBubbles password as `IMESSAGE_PASSWORD` in the
encrypted secret store instead of plaintext config
Expand Down
18 changes: 13 additions & 5 deletions docs/development/extensibility/adaptive-skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ is disabled by default.
"rollbackImprovementThreshold": 0.05,
"trajectoryCapture": {
"enabledAgentIds": [],
"storeDir": ""
"storeDir": "",
"retentionDays": 365,
"retentionDaysByTenant": {}
}
}
}
Expand All @@ -66,6 +68,10 @@ Key settings:
- `trajectoryCapture.storeDir`: optional trajectory store location; empty uses
a `trajectories/` directory beside the runtime database, absolute paths are
used as-is, and relative paths resolve under the runtime home directory
- `trajectoryCapture.retentionDays`: trajectory JSONL retention window; default
is 365 days and `0` disables trajectory pruning
- `trajectoryCapture.retentionDaysByTenant`: optional per-coworker retention
overrides keyed by tenant ID; trajectory tenants currently map to agent IDs

Legacy `skillCognee` config input is still normalized into `adaptiveSkills` for
backward compatibility.
Expand All @@ -90,12 +96,14 @@ Feedback is attached to the most recent observation for the same session.

## Retention

Observation queries are windowed, but storage is also pruned now. On each
Observation queries are windowed, but storage is also pruned. On each
inspection interval the heartbeat deletes `skill_observations` rows older than
`observationRetentionDays`.
`observationRetentionDays` and removes expired trajectory JSONL files according
to the trajectory retention policy.

This keeps high-traffic skills from accumulating unbounded observation history
while preserving the amendment history table as the durable review log.
This keeps high-traffic skills from accumulating unbounded observation and
trajectory history while preserving the amendment history table as the durable
review log.

## Operator Surfaces

Expand Down
4 changes: 3 additions & 1 deletion docs/development/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ leak into the saved revision metadata.
`adaptiveSkills.trajectoryCapture.enabledAgentIds`; when
`adaptiveSkills.trajectoryCapture.storeDir` is empty, trajectories are stored
beside the runtime database, absolute paths are used as-is, and relative paths
resolve under the runtime home directory
resolve under the runtime home directory; trajectory retention defaults to
`adaptiveSkills.trajectoryCapture.retentionDays: 365` and can be overridden
per coworker with `adaptiveSkills.trajectoryCapture.retentionDaysByTenant`
- `imessage.*` for the dual-backend local or BlueBubbles iMessage transport;
prefer storing the BlueBubbles password as `IMESSAGE_PASSWORD` in the
encrypted secret store instead of plaintext config
Expand Down
33 changes: 33 additions & 0 deletions src/config/runtime-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,8 @@ export const DEFAULT_RUNTIME_CONFIG: RuntimeConfig = {
trajectoryCapture: {
enabledAgentIds: [],
storeDir: '',
retentionDays: 365,
retentionDaysByTenant: {},
},
inspectionIntervalMs: 3_600_000,
observationRetentionDays: 30,
Expand Down Expand Up @@ -1733,6 +1735,25 @@ function normalizeStringArray(value: unknown, fallback: string[]): string[] {
return fallback;
}

function normalizeRetentionDaysByTenant(
value: unknown,
fallback: Record<string, number>,
defaultRetentionDays: number,
): Record<string, number> {
if (!isRecord(value)) return { ...fallback };
const normalized: Record<string, number> = {};
for (const [tenantId, rawDays] of Object.entries(value)) {
const normalizedTenantId = tenantId.trim();
if (!normalizedTenantId) continue;
normalized[normalizedTenantId] = normalizeInteger(
rawDays,
fallback[normalizedTenantId] ?? defaultRetentionDays,
{ min: 0 },
);
}
return normalized;
}

function normalizeOptionalBaseUrl(value: unknown, fallback: string): string {
const candidate = normalizeString(value, fallback, { allowEmpty: true });
return candidate ? candidate.replace(/\/+$/, '') : '';
Expand Down Expand Up @@ -4716,6 +4737,11 @@ function normalizeRuntimeConfig(
rawDiscord.commandMode,
legacyCommandModeFallback,
);
const normalizedTrajectoryRetentionDays = normalizeInteger(
rawTrajectoryCapture.retentionDays,
DEFAULT_RUNTIME_CONFIG.adaptiveSkills.trajectoryCapture.retentionDays,
{ min: 0 },
);

return {
version: CONFIG_VERSION,
Expand Down Expand Up @@ -4803,6 +4829,13 @@ function normalizeRuntimeConfig(
DEFAULT_RUNTIME_CONFIG.adaptiveSkills.trajectoryCapture.storeDir,
{ allowEmpty: true },
),
retentionDays: normalizedTrajectoryRetentionDays,
retentionDaysByTenant: normalizeRetentionDaysByTenant(
rawTrajectoryCapture.retentionDaysByTenant,
DEFAULT_RUNTIME_CONFIG.adaptiveSkills.trajectoryCapture
.retentionDaysByTenant,
normalizedTrajectoryRetentionDays,
),
},
inspectionIntervalMs: normalizeInteger(
rawAdaptiveSkills.inspectionIntervalMs,
Expand Down
2 changes: 2 additions & 0 deletions src/skills/adaptive-skills-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ export interface AdaptiveSkillsConfig {
trajectoryCapture: {
enabledAgentIds: string[];
storeDir: string;
retentionDays: number;
retentionDaysByTenant: Record<string, number>;
};
inspectionIntervalMs: number;
observationRetentionDays: number;
Expand Down
Loading
Loading