8.1 KiB
Spec: lifecycle-deletion
ADDED Requirements
Requirement: Delete Is True Git Deletion in a Dedicated Hygiene Commit
A lifecycle delete op SHALL perform a true git rm (file or, for a
directory-rule aggregate entry, recursive directory removal) staged into the
same single hygiene commit the run produces. There SHALL be no archive
directory, graveyard branch, or other relocation of the deleted content —
git history SHALL be the sole archive.
Scenario: A deleted file is git-rm'd, not moved
- WHEN a
deleteop is applied to a tracked file - THEN the file is removed via
git rmand staged into the run's single hygiene commit, with no copy relocated anywhere in the working tree
Scenario: A deleted directory-rule entry is removed recursively
- WHEN a
deleteop targets a directory-rule aggregate entry - THEN the entire directory is removed via a recursive
git rmstaged into the same commit
Requirement: Deletion Autonomy Tier Matrix
Deletion autonomy SHALL be determined by evidence quality and recoverability, not file type, per the following matrix:
| Case | Behavior |
|---|---|
| IGNORE surface | never walked, never a delete candidate |
lifetime keep |
scanned + reported, never deleted |
| tracked + delete rule + clean worktree | auto |
| tracked + delete rule + dirty worktree | confirm |
| untracked + delete rule | confirm |
| no rule match | unmanaged, never deleted |
Tracked/clean status SHALL be verified at runtime via git ls-files plus a
dirty check, and SHALL NEVER be trusted from the rule's own claim or from a
cached report field.
Scenario: Tracked and clean deletes automatically
- WHEN a file matches a delete rule, is tracked, and the worktree for that path is clean
- THEN the deletion proceeds without a confirmation prompt
Scenario: Tracked but dirty requires confirmation
- WHEN a file matches a delete rule, is tracked, but has uncommitted changes
- THEN the deletion is escalated to confirm — an uncommitted diff would otherwise be lost with the file
Scenario: Untracked requires confirmation
- WHEN a file matches a delete rule but is untracked
- THEN the deletion is escalated to confirm — there is no git history to recover it from
Scenario: Runtime verification never trusts the rule
- WHEN a delete op is about to be applied
- THEN the applier re-checks tracked/clean status via
git ls-filesand a dirty check at that moment, regardless of what the report or rule previously claimed
Scenario: No rule match is never deleted
- WHEN a file has no lifecycle rule match
- THEN it is never a candidate for deletion on lifecycle grounds
Requirement: Temporary Tier Retention Semantics
The temporary lifetime SHALL use retain-recent-N plus age, not age alone.
retain_recent (default 3) SHALL always keep the N most recent matching
entries for a rule regardless of age. An entry ranked retain_recent + 1 or
older SHALL become eligible for deletion once it exceeds max_age_days
(default 3). The retention unit SHALL be the rule's own match granularity: a
file-rule's unit is the individual file; a directory-rule's unit is the
matched directory as a whole (e.g., a run directory), never files nested
inside one such matched directory.
Scenario: The 3 newest entries are always kept regardless of age
- WHEN a temporary rule has
retain_recent: 3and five matching entries, the three newest exceedingmax_age_days - THEN the three newest are kept and only the two oldest (ranked 4th and 5th) are eligible for deletion
Scenario: An entry younger than max_age_days is kept even if not in the top N
- WHEN a temporary rule's 4th-ranked entry is younger than
max_age_days - THEN it is not deleted this run
Scenario: Directory-rule retention unit is the whole directory
- WHEN a directory rule matches
autoresearch/<run-id>/entries - THEN retain-recent-N and age are computed per matched run directory as a whole, not per file within the newest run
Requirement: Temporary Tier Age Source
Age for the temporary tier SHALL be computed from the git commit time of the
path's most recent commit, falling back to filesystem mtime only when the
path is untracked. There SHALL be no per-rule age_source override field.
Scenario: Tracked file age comes from git commit time
- WHEN age is computed for a tracked file matching a temporary rule
- THEN the age is derived from that file's most recent commit time, not its filesystem mtime
Scenario: Untracked file age falls back to mtime
- WHEN age is computed for an untracked file matching a temporary rule
- THEN the age is derived from the file's filesystem mtime
Scenario: No per-rule age_source field exists
- WHEN a rule in the rulebook is inspected
- THEN it has no
age_sourcefield — the git-commit-time-with-mtime-fallback behavior is fixed, not configurable per rule
Requirement: Untracked Directory Entry Age Uses Directory Inode mtime
For an untracked directory matched by a directory rule, age SHALL be
computed from a single stat() of the directory inode itself, not a
recursive walk computing the maximum mtime of its contents.
Scenario: Directory age is one stat call, not a recursive scan
- WHEN age is computed for an untracked directory matching a directory rule
- THEN the computation reads only the directory inode's own mtime and does not recurse into or stat any file inside it
Requirement: delete-once-served Split by Evidence Quality
The delete-once-served lifetime SHALL support two mutually exclusive served
signals per rule: served_when_path, a deterministic path pattern the
scanner itself can prove satisfied (e.g. a sibling archive directory
existing), and served_when, free text describing a condition the
classifier must judge. A rule with served_when_path satisfied by the
scanner MAY be deleted under the autonomy tier matrix (i.e., auto when
tracked+clean). A rule relying on served_when SHALL ALWAYS be forced to
confirm, regardless of tracked/clean status, because it depends on a model
judgment rather than a provable filesystem fact.
Scenario: Scanner-proven served_when_path may auto-delete
- WHEN a rule's
served_when_pathcondition is satisfied by the filesystem and the matched path is tracked and clean - THEN the deletion may proceed automatically under the tier matrix
Scenario: Classifier-judged served_when always forces confirm
- WHEN a rule uses
served_when(free text) and the classifier judges the condition met - THEN the deletion is always escalated to confirm, even if the matched path is tracked and clean
Scenario: The LLM may propose but never silently destroy on served_when
- WHEN the classifier judges a
served_whencondition satisfied - THEN it produces a proposal for a human to confirm; it never causes an unattended deletion
Requirement: Extract Modifier Routes Through Existing Knowledge Destinations Only
The extract modifier on a deletion SHALL distill durable content before
deleting, routing exclusively through the existing knowledge-routing
destinations: repo-durable residue SHALL be written into an ADR, CLAUDE.md,
or a docs/ file; cross-repo lessons SHALL be written to the SecondBrain
vault via /os-vault:write. No new destination (e.g., a "retired specs"
directory) SHALL be introduced.
Scenario: Repo-durable extraction targets ADR/CLAUDE.md/docs
- WHEN an
extract-then-deleteop is classified as repo-durable - THEN the extracted content is written into an ADR,
CLAUDE.md, or adocs/file, never a new bespoke location
Scenario: Cross-repo extraction routes through /os-vault:write
- WHEN an
extract-then-deleteop is classified as cross-repo - THEN the extracted content is written to the SecondBrain vault via
/os-vault:write, and no other cross-repo destination is used
Scenario: No new destination is introduced
- WHEN extraction routing is implemented
- THEN it reuses only the destinations named above; it does not create a new "retired" or "archive" content store