Skip to content

feat(backend): add task manager retention settings [INFP-507] - #10862

Closed
saltas888 wants to merge 48 commits into
developfrom
task-history-retention-infp-507
Closed

saltas888 wants to merge 48 commits into
developfrom
task-history-retention-infp-507

Conversation

@saltas888

@saltas888 saltas888 commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Superseded by #11289. The six INFP-507 PRs are consolidated there into one commit targeting develop, with the complete design, code-flow diagrams and contract-based review guide. This PR is closed to keep one active review; its branch and previous discussions are preserved.

Stacked PR 1/6 for INFP-507 (task history and activity log retention), in GitHub stack #10873 on develop. Review and merge bottom-up; each PR targets the one below it.

  1. This PR: retention settings applied to Prefect
  2. feat(backend): clean up old task history in the task manager and during the upgrade [INFP-507] #10869: task history cleanup command, and the upgrade's task history hint
  3. fix(backend): keep the Activities page fast with a year of activity log [INFP-507] #10876: Activities page queries
  4. test(backend): guard the Prefect event-type list on the full stack [INFP-507] #10877: guard for Prefect's event types on the full stack
  5. feat(backend): run the task manager background services with the retention settings [INFP-507] #10878: infrahub tasks background-services
  6. docs: document task history and activity log retention [INFP-507] #10879: documentation

Ship with #10869 in the same release. On its own, this PR switches on Prefect's hourly deletion, which works through a large backlog slowly and gives no disk space back; #10869 adds the one-off cleanup command, its table rewrite, and the upgrade's hint that names that command.

Why

The task manager never deletes finished task runs, so task history grows until the disk fills, and the activity log is fixed at Prefect's 7 days with no Infrahub setting. Design doc: Task history and Activity log retention; spec set in dev/specs/infp-507-task-history-retention/.

Goal: one Infrahub setting per kind of record, translated into the Prefect settings that enforce it, so Prefect's built-in hourly cleanup bounds task history from this PR on.

Non-goals here: deleting the existing backlog and giving disk space back (PR 2), the Activities query changes (PR 3).

Closes part of INFP-507.

How retention works

Infrahub defines the retention policy; Prefect's background services enforce it. Task history and activity are kept independently, while Infrahub and Prefect events share the same storage.

flowchart TB
    CONFIG["Infrahub retention settings<br/>Task history · Activity log · Prefect events"]
    TYPES["Infrahub-maintained list<br/>of Prefect event types"]

    subgraph TM["Task manager"]
        APPLY["At startup<br/>Translate Infrahub settings into Prefect settings"]

        subgraph SERVICES["Prefect background services — every hour"]
            TASKS["Task-history cleanup<br/>Remove finished runs older than task_history<br/>together with their logs and artifacts"]
            EVENTS["Event cleanup<br/>Keep Infrahub events for activity_log<br/>Keep listed Prefect events for prefect_own_events"]
        end

        APPLY --> TASKS
        APPLY --> EVENTS
    end

    subgraph DB["Prefect database"]
        RUNS[("Task history<br/>Runs, states, logs and artifacts")]
        LOG[("Shared event storage<br/>Infrahub activity + Prefect internal events")]
    end

    CONFIG --> APPLY
    TYPES --> APPLY
    TASKS -->|"Delete expired task history"| RUNS
    EVENTS -->|"Delete expired events and related resources"| LOG
Loading

Increasing activity-log retention can preserve a year of Infrahub activity without also keeping a year of Prefect's internal events. When background services run in their own deployment, #10878 applies the same settings before starting them.

The operator cleanup in #10869 is a separate recovery step for existing instances: clear the old task-history backlog and recover disk space after an upgrade or retention reduction. The upgrade prints guidance; ongoing retention is handled automatically by the flow above.

What changed

Behavioural changes:

  • New settings task_manager.retention.task_history (30 days), activity_log (7 days, unchanged from today) and prefect_own_events (7 days); env vars INFRAHUB_TASK_MANAGER_RETENTION_*; 30d or ISO 8601; 1 to 36,500 days, or the task manager refuses to start.
  • Finished task runs older than 30 days are now deleted every hour with their logs and artifacts (Prefect's flow-run vacuum is switched on). Previously they were never deleted.
  • Prefect's own events (103 event types from Prefect 3.8.6: run and task-run states, heartbeats, workers, work pools, automations...) follow prefect_own_events; Infrahub events follow activity_log. With the defaults both are 7 days, as today.
  • A PREFECT_* variable already set (under any name Prefect accepts, including legacy aliases) takes precedence, with one warning per variable. The effective values are logged at startup.

Implementation notes:

  • backend/infrahub/prefect_server/retention.py builds the four Prefect variables; create_infrahub_prefect now loads the Infrahub configuration in every mode (it only did in distributed mode), applies them, then refreshes Prefect's global settings context (Prefect reads its settings once at import).
  • The integration-test Prefect container runs the stock Prefect image without the infrahub package, so it now uses create_prefect_app_with_infrahub_routes, which skips the configuration step.
  • The Compose task-manager service does not merge the shared Infrahub anchor, so the three variables are declared on it explicitly (root docker-compose.yml and the dev deps files).
  • tasks/docs.py: the configuration reference showed bare field names for a nested settings model with its own env prefix; it now shows the INFRAHUB_TASK_MANAGER_RETENTION_* names.

What stayed the same: no change to Prefect's database schema; Infrahub events are untouched; the component-test harness still turns the vacuum off (its preset variable wins by design).

How to review

  1. backend/infrahub/config.py (settings and validation), then prefect_server/retention.py and prefect_server/app.py.
  2. Tests: tests/unit/config/test_task_manager_retention_settings.py, tests/unit/prefect_server/ (one test feeds the derived env into Prefect's own settings model, so a format mistake fails CI), tests/component/task_manager/test_event_retention.py (runs Prefect's event vacuum with a 365-day activity log and 7-day own events).
  3. dev/specs/infp-507-task-history-retention/ is the spec set for the whole stack.

Worth extra scrutiny: the event-type list. Overrides match event names exactly, and an unlisted Prefect type is kept for the activity log retention. A unit test covers every built-in state name; PR 4 adds a full-stack guard on a real workload.

How to test

uv run pytest backend/tests/unit/config/test_task_manager_retention_settings.py backend/tests/unit/prefect_server/ -n 0
uv run pytest backend/tests/component/task_manager/test_event_retention.py -n 0

Manual: start the task manager with INFRAHUB_TASK_MANAGER_RETENTION_TASK_HISTORY=1d and look for the Task manager retention: lines; with 0d it refuses to start.

Impact & rollout

  • Backward compatibility: irreversible deletion of finished runs older than the retention starts within an hour of the upgrade. Operators who need older runs set a longer task_history first (changelog says so).
  • Performance: the first hourly passes delete the backlog in Prefect's batches; PR 2 adds the faster one-off cleanup, which operators run once after the upgrade; the upgrade prints the command.
  • Config/env changes: three new settings; PREFECT_* precedence documented.
  • Deployment notes: the Helm chart needs the same three variables on the task-manager deployment (infrahub-helm PR follows the stack).

Validated locally: unit and component tests, ruff, mypy, docs.validate, validate-dockercomposeenv; reviewed with cubic (two passes, findings addressed). Release evidence on restored backups comes from opsmill/infrahub-private-tests, run separately.

Checklist

  • Tests added/updated
  • Changelog entry added
  • External docs updated (PR 6 of this stack)
  • Internal .md docs updated (PR 6 of this stack)
  • I have reviewed AI generated content

🤖 Generated with Claude Code

@saltas888 saltas888 added type/feature New feature or request group/backend API server, GraphQL, task worker (Prefect), database, Python code labels Oct 4, 2026
@github-actions github-actions Bot added type/documentation Improvements or additions to documentation type/spec A specification for an upcoming change to the project labels Oct 4, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 30 files

Confidence score: 2/5

  • spec.md brings Activities query/display performance back into this feature, even though that work moved to INFP-727 and retention must wait for IFC-2933. Align the spec with those dependencies.
  • plan.md allows any caller who can reach the task-manager API to trigger cleanup and request the optional rewrite without authentication. Add authentication or obtain an approved security exception.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="dev/specs/infp-507-task-history-retention/spec.md">

<violation number="1" location="dev/specs/infp-507-task-history-retention/spec.md:22">
P2: According to linked Jira issue INFP-507, Activities query/display performance moved to INFP-727, and retention must not ship ahead of IFC-2933. This sentence brings that work back into this feature; align the spec's scope and delivery order with the current decision.</violation>
</file>

<file name="dev/specs/infp-507-task-history-retention/plan.md">

<violation number="1" location="dev/specs/infp-507-task-history-retention/plan.md:49">
P2: Do not ship this unauthenticated cleanup mutation without an approved security exception: any caller that can reach the task-manager API can trigger cleanup and request the optional rewrite. Add authentication or obtain and record maintainer approval with an enforced network boundary.</violation>
</file>

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic


Product decided that each instance keeps both kinds of records for a configured period, deletes older records automatically without affecting the instance, keeps the activity log for its own retention whatever the task manager keeps of its own records, and gets the disk space back. A year or more of activity log is supported in every edition, built so that long retention can become an Enterprise feature later.

The Activities page gets slower as the activity log grows: with a year of activity log, one page takes minutes today. The Activities page work therefore ships with this feature, ahead of the activity log retention.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: According to linked Jira issue INFP-507, Activities query/display performance moved to INFP-727, and retention must not ship ahead of IFC-2933. This sentence brings that work back into this feature; align the spec's scope and delivery order with the current decision.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At dev/specs/infp-507-task-history-retention/spec.md, line 22:

<comment>According to linked Jira issue INFP-507, Activities query/display performance moved to INFP-727, and retention must not ship ahead of IFC-2933. This sentence brings that work back into this feature; align the spec's scope and delivery order with the current decision.</comment>

<file context>
@@ -0,0 +1,242 @@
+
+Product decided that each instance keeps both kinds of records for a configured period, deletes older records automatically without affecting the instance, keeps the activity log for its own retention whatever the task manager keeps of its own records, and gets the disk space back. A year or more of activity log is supported in every edition, built so that long retention can become an Enterprise feature later.
+
+The Activities page gets slower as the activity log grows: with a year of activity log, one page takes minutes today. The Activities page work therefore ships with this feature, ahead of the activity log retention.
+
+## User Scenarios & Testing *(mandatory)*
</file context>

Comment thread backend/infrahub/config.py Resolved
@codspeed

codspeed Bot commented Oct 4, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 13 untouched benchmarks


Comparing task-history-retention-infp-507 (ff6a8ce) with develop (2ff7c1f)1

Open in CodSpeed

Footnotes

  1. No successful run was found on develop (1920cd1) during the generation of this report, so 2ff7c1f was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

Comment thread backend/infrahub/prefect_server/app.py Resolved
Comment thread backend/infrahub/prefect_server/app.py Resolved
@saltas888
saltas888 force-pushed the task-history-retention-infp-507 branch from b9db2c4 to 938f241 Compare October 14, 2026 13:27
saltas888 and others added 14 commits October 27, 2026 22:50
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ition and removed flags

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cleanup

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
 plan and tasks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… own session

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dd a state-list unit test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a task_manager.retention configuration section with task_history
(30 days), activity_log (7 days) and prefect_own_events (7 days), read
from infrahub.toml or INFRAHUB_TASK_MANAGER_RETENTION_* variables.
Values take a number of days (30d) or an ISO 8601 duration (P30D) and
must be at least 1 day; any other value fails the configuration load
with "Invalid task manager retention: <key> <reason>". An own-event
retention longer than the activity log is accepted.

The section is built when the configuration loads rather than at
import, so an invalid value reaches the friendly load error. The
configuration reference generator now resolves the variable names of
a nested settings model that has its own prefix, and the compose files
declare the new variables.

INFP-507

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The task manager now loads the Infrahub configuration in every mode and
translates task_manager.retention into Prefect's settings before the
app is created:

- PREFECT_SERVER_SERVICES_DB_VACUUM_ENABLED=events,flow_runs
- PREFECT_SERVER_SERVICES_DB_VACUUM_RETENTION_PERIOD from task_history
- PREFECT_SERVER_EVENTS_RETENTION_PERIOD from activity_log
- PREFECT_SERVER_SERVICES_DB_VACUUM_EVENT_RETENTION_OVERRIDES, one
  entry per listed Prefect event type, capped to activity_log

Durations are written as ISO 8601 days (P30D, P1DT43200S), the only
form both of Prefect's timedelta parsers read: the events retention
rejects a number of seconds. A Prefect variable already set in the
environment wins, with one warning per variable, and a capped own-event
retention logs a warning. An invalid retention stops the process with
the configuration error.

Prefect builds its global settings from the environment once, when
prefect.context is imported, so the values only apply after
refresh_global_settings_context(); without it the vacuum keeps
Prefect's defaults.

The stock Prefect image used by the integration test container has no
infrahub package, so it now starts create_prefect_app_with_infrahub_routes,
which builds the app without loading the configuration.

INFP-507

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mark T003-T007 and T047 done and record what landed: the settings test
path under tests/unit/config/, the event types passed to
build_prefect_retention_env, the capped own-event warning returned by
apply_prefect_retention_env, and the Prefect settings refresh.

Correct research R2: Prefect's get_current_settings() returns the
global settings context built when prefect.context is imported, so
environment changes apply only after refresh_global_settings_context().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
saltas888 and others added 4 commits October 27, 2026 22:50
A well-formed duration too large to read was reported as malformed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…retention changelog

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntion

`P` and `PT` matched the duration pattern and were refused as longer than
36500 days.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@saltas888
saltas888 force-pushed the task-history-retention-infp-507 branch from 938f241 to a8c7fc9 Compare October 27, 2026 22:07
claude added 15 commits October 27, 2026 23:59
… in the task manager

The standalone task manager loaded and validated the whole Infrahub
configuration, so a setting it does not use, such as an invalid storage
driver, stopped it. It now reads only the task_manager section of the
configuration file and its INFRAHUB_TASK_MANAGER_* variables. An invalid
retention or an unreadable configuration file still stops it, and
distributed mode loads the whole configuration as before.

The retention settings move to a module that imports nothing else from
Infrahub, and infrahub.config imports them from there. The task manager
still sets up Infrahub's logging before Prefect builds its app, so the
retention lines stay visible.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…round services

With PREFECT__SERVER_WEBSERVER_ONLY set, the task manager runs only the
web server, and the process that runs Prefect's background services
does not read task_manager.retention, so it deletes no task runs. The
task manager now logs a warning at startup that says so, instead of only
logging the retention as if it were in effect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…ity_log

A prefect_own_events longer than activity_log has no effect, because
every event older than activity_log is deleted anyway. Infrahub used to
accept it, cap it at runtime and log a warning, and the cap used
activity_log even when PREFECT_SERVER_EVENTS_RETENTION_PERIOD was set
and activity_log was not in effect. The settings now refuse such a value
at startup, and the per-type overrides carry prefect_own_events as
configured, since Prefect caps each override by the event retention it
uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
A compose or Helm file that passes PREFECT_SERVER_SERVICES_DB_VACUUM_ENABLED
through from an unset host variable gives the task manager an empty value.
Infrahub kept it as an operator setting, and Prefect read it as false, so
finished task runs were never deleted. An empty or blank retention variable
is now removed and replaced with the value derived from the task manager
retention, with no warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
… turns off

A preset PREFECT_SERVER_SERVICES_DB_VACUUM_ENABLED was reported as
overriding task_history, although task_history still set the run
retention, and a value without events silently stopped all event
deletion. The switch is now kept without that warning. After Prefect's
settings are refreshed, the task manager warns when the switch turns off
the deletion of task runs or events, and names the retention that is
not applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…g the values Prefect applies

Prefect also reads its settings from .env, prefect.toml, pyproject.toml
and the active profile, and an environment variable wins over all of
them. A retention set in one of those files was silently replaced by the
value Infrahub wrote. The task manager now writes a variable only when no
Prefect source sets that setting, warns about the ones it leaves, and
logs the values from Prefect's parsed settings after the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…retention

With the default 7-day activity log and own-event retention, the task
manager wrote a per-type override for every listed Prefect event type,
so Prefect ran over 200 delete statements every hour that removed
nothing its general event cleanup does not remove. The overrides are now
written as an empty mapping when the own-event retention equals the
activity log retention and Infrahub sets the event retention. The rows
deleted do not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…list against Prefect's source

Prefect's per-type event retention matches exact names, and the list of
Prefect event types missed the two events that prefect transfer sends.
They are now listed, with the run events of the Rerunning state name
that Prefect's server sets on task runs. New unit tests read the
installed Prefect package and fail when it sends an event name, builds a
name pattern or defines a status, lifecycle record kind or state name
that the list does not cover, so a Prefect upgrade that adds one fails
CI instead of keeping those events for the activity log retention.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
The test ran Prefect's event cleanup on the database that every
component test in the same worker shares, so it deleted any old event
another test had seeded there. It now runs on an empty, migrated SQLite
database in its own temporary directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…ests

The state constructors were typed as returning object, so ty, which CI
runs, reported an invalid argument where their states are added to the
list of Prefect states. They are now typed as returning Prefect's client
or server state.

The test docstring and research.md also said the tests read every name
built from the known patterns. They do not read the lifecycle actions,
the concurrency limit phases, the asset materialization statuses or a
name passed through a helper with another parameter name, so the text
now says so. plan.md now names the unit tests that check the event type
list against Prefect's source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
… an empty retention variable does

An empty PREFECT_SERVER_SERVICES_DB_VACUUM_RETENTION_PERIOD or
PREFECT_SERVER_EVENTS_RETENTION_PERIOD makes the import of prefect.context
fail with a time_delta_parsing error, and an empty
PREFECT_SERVER_SERVICES_DB_VACUUM_EVENT_RETENTION_OVERRIDES with a
SettingsError. Both happen when the task manager app module or the infrahub
command line is imported, before any Infrahub code can remove the variable,
so removing them never took effect. Only the vacuum switch is now removed
when it is empty.

The changelog and the specs now say that an empty vacuum switch gives way to
a value from Prefect's settings files or profile, with the usual warning for
each cleanup it turns off, and otherwise to events,flow_runs, and that an
empty retention variable still stops the task manager at startup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…an activity_log

The refusal said the task manager deletes every event older than
activity_log, which is false when a Prefect setting already sets the
event retention or the vacuum switch turns off the event cleanup. The
message now asks the operator to set prefect_own_events to at most the
activity_log value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
The loader also raises tomllib.TOMLDecodeError, UnicodeDecodeError and
OSError when the configuration file cannot be parsed, decoded or read,
so its Raises section now names them. The configuration contract now
says that an invalid INFRAHUB_LOG_LEVEL or INFRAHUB_PRODUCTION still
stops the standalone task manager, because it reads both variables to
set up its logging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…eady asserts

The equal_retentions case wrote the 30d, 7d and 7d retentions with nothing
preset and checked that the per-type overrides are empty. The test that
applies every missing variable uses the same settings and checks the whole
environment, overrides included, so it already pinned this. Both failed
together when the skip of equal overrides was reverted. The case is
removed and the apply test now says why its overrides are empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
Say that refusing a prefect_own_events longer than activity_log is about the
case where the task manager sets the event retention, that only an empty
vacuum switch in the environment is removed, that an empty retention variable
stops the task manager only under the name Prefect reads, and that the
standalone task manager also reads the two logging variables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
T021 checks that the retention reaches Prefect's background services when
they run in their own container, which only the command of T048 does, and
plan.md already puts that command in part 1. The implementation strategy,
the US1 checkpoint and the delivery order in spec.md now include US4 in
part 1, and step 3 covers only US3.

T048 now lists the steps of apply_infrahub_settings_to_prefect() from T007,
including the refresh of Prefect's global settings, because Prefect reads
its settings from the environment once at import and the vacuum services
would otherwise keep the values from before the command applied the
retention.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
… never started

No command named stuck-runs exists; the command that marks long RUNNING or
PENDING runs as CRASHED is `infrahub tasks flush stale-runs`. data-model.md
and T053 now use that name.

The spec files said that the command does not catch PENDING runs that never
started. In Prefect 3.8.6 the start time filter compares the expected start
time when a run has no start time, and Prefect sets an expected start time
on the first state of every run. A run against a temporary Prefect server
showed that the command's filter matches such a run once that time is older
than the cutoff, and that forcing it to CRASHED gives it an end time. The
edge case, FR-014 and the CLI contract now say this, and the out-of-scope
follow-up is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
- plan.md: the Evidence table said that PR #33's test_activity_log.py had
  landed with its retention override switched, but T037 and T038 are still
  open. The row now says that T037 lands and switches it and T038 extends
  it, before the evidence run.
- contracts/configuration.md: name PREFECT_EVENTS_RETENTION_PERIOD, the only
  legacy name among the four Prefect settings in Prefect 3.8.6, in the
  precedence list and the warning line.
- quickstart.md: step 4 seeds old finished runs that are more than half of
  the runs on the Compose stack (Postgres), because the rewrite runs only
  then, and T013 states the same condition. Part 1 now names the unit test
  that checks Prefect's settings turn on the task run cleanup, and the
  private test from T021 that checks the hourly cleanup.
- research.md R1: Prefect's vacuum_old_flow_runs deletes each batch of runs
  first and their logs and artifacts after, the order R5 follows.
- critique-20261004.md: the correction note names every place that still
  counts E2 and says that E1 and E4 remain, leaving the dated review as
  written.
- spec.md FR-005 says "the task manager's cutoff date", and the checklist
  notes list each technical detail the spec keeps on purpose, and why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…etention tests

The fixture put the earlier values back before pytest undid the tests'
setenv calls, and that undo then deleted them, so a retention variable set
before the tests, such as the vacuum switch that the component, functional
and integration conftests set, was gone after this file ran. The fixture
now clears the variables with monkeypatch.delenv, so pytest restores them,
and at teardown only removes the values the code under test writes
directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
…sts once

test_retention.py pinned the names as literals while test_app_retention.py
imported them from the module under test, and both files declared the
legacy event retention name and the Prefect test mode variables. The names
now live once, as literals, in tests/helpers/task_manager_retention.py, so a
misspelled name in the code under test still fails the tests. The fixture
also uses the constant for PREFECT__SERVER_WEBSERVER_ONLY.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwJNFw8rccyxc4Wp9eZFbH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

group/backend API server, GraphQL, task worker (Prefect), database, Python code type/documentation Improvements or additions to documentation type/feature New feature or request type/spec A specification for an upcoming change to the project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants