Luigit
repositories / termux-janitor

termux-janitor

Interactive cleanup assistant for Termux: transparent, safe, confirmed disk reclamation.

owned by admin

spec/fixtures/exec/mutation_a.md

Raw
Rendered preview

Root-anchored mutation through the interactive confirmation path

Fixture: fixture-test-exec-mutation-a@4

Given

The built termux-janitor executable starts on a pseudo-terminal with an isolated environment: HOME contains exactly one temporary file a.tmp, PREFIX points at a separate empty directory, XDG_STATE_HOME points at a third directory, and TERM names a non-dumb terminal. The second run replaces the reviewed leaf's content after the scan and before confirmation. The third run nests a.tmp one directory deeper and swaps that ancestor directory for a new one holding the identical leaf after the scan and before confirmation. The fourth and fifth runs give HOME a sub tree containing a.tmp, an empty directory, and a symlink pointing outside the reviewed tree; the fifth replaces the reviewed a.tmp child with a same-name successor before confirmation.

When

Five sessions drive the terminal.

Every session focuses its target through search so the canonical checklist ordering never affects which row receives the keys.

  1. The confirmed session waits for the alternate screen, searches for a.tmp, selects the focused match, enters confirmation, types the exact phrase, and presses Enter.
  2. The drifted session repeats the same interaction after rewriting a.tmp between the scan and the confirmation phrase.
  3. The ancestor-drifted session repeats it against the nested a.tmp after the ancestor swap.
  4. The directory-confirmed session searches for sub, selects the directory, and completes the same confirmation.
  5. The directory-drifted session repeats that interaction after replacing the reviewed child.

Required invariants

  • INV-EXEC-MUTATION-A: The confirmed session exits cleanly without crash markers, unlinks exactly a.tmp from its selected root, and appends adjacent intent and success result frames to the run log.
  • INV-EXEC-ANCESTOR-A: The ancestor-drifted session never mutates: the reviewed leaf itself is unchanged at its path, no success frame is recorded, and the run log records a failure result frame.
  • INV-EXEC-DIRECTORY-A: The directory-confirmed session removes the whole reviewed sub tree, including the empty directory and the symlink, records a success result frame, and the symlink target outside the reviewed tree survives.

Forbidden effects

  • NO-EXEC-MUTATION-A: The drifted session never records a successful mutation: the changed leaf survives and the run log records a failure result frame.
  • NO-EXEC-DIRECTORY-A: The directory-drifted session never records a successful mutation: the replaced child and the directory survive and the run log records a failure result frame.

Instrumentation

try fixture.given_program("termux-janitor");
try fixture.given_isolated_tree();
try fixture.when_run_sessions();
try fixture.then_inv_exec_mutation_a();
try fixture.then_inv_exec_ancestor_a();
try fixture.then_inv_exec_directory_a();
try fixture.forbid_no_exec_mutation_a();
try fixture.forbid_no_exec_directory_a();

Variations

Ancestor-replacement drift, mount changes, and whole-directory child-set comparison are owned by the manifest suite in requirements/manifest_a.md.

Limitations

The sessions observe the final filesystem and run-log state plus the terminal byte stream; they do not trace syscalls, so adjacency of check and mutation is inferred from the recorded frame order and the single final-interval race disclosure in PRODUCT.md section 11.1 remains outside this fixture.

# Root-anchored mutation through the interactive confirmation path

**Fixture:** `fixture-test-exec-mutation-a@4`

## Given

The built `termux-janitor` executable starts on a pseudo-terminal with an isolated environment:
`HOME` contains exactly one temporary file `a.tmp`, `PREFIX` points at a separate empty
directory, `XDG_STATE_HOME` points at a third directory, and `TERM` names a non-dumb terminal.
The second run replaces the reviewed leaf's content after the scan and before confirmation. The
third run nests `a.tmp` one directory deeper and swaps that ancestor directory for a new one
holding the identical leaf after the scan and before confirmation. The fourth and fifth runs give
`HOME` a `sub` tree containing `a.tmp`, an empty directory, and a symlink pointing outside the
reviewed tree; the fifth replaces the reviewed `a.tmp` child with a same-name successor before
confirmation.

## When

Five sessions drive the terminal.

Every session focuses its target through search so the canonical checklist ordering never affects
which row receives the keys.

1. The confirmed session waits for the alternate screen, searches for `a.tmp`, selects the focused
   match, enters confirmation, types the exact phrase, and presses Enter.
2. The drifted session repeats the same interaction after rewriting `a.tmp` between the scan and
   the confirmation phrase.
3. The ancestor-drifted session repeats it against the nested `a.tmp` after the ancestor swap.
4. The directory-confirmed session searches for `sub`, selects the directory, and completes the
   same confirmation.
5. The directory-drifted session repeats that interaction after replacing the reviewed child.

## Required invariants

- **`INV-EXEC-MUTATION-A`:**
  The confirmed session exits cleanly without crash markers, unlinks exactly `a.tmp` from its
  selected root, and appends adjacent intent and success result frames to the run log.
- **`INV-EXEC-ANCESTOR-A`:**
  The ancestor-drifted session never mutates: the reviewed leaf itself is unchanged at its path,
  no success frame is recorded, and the run log records a failure result frame.
- **`INV-EXEC-DIRECTORY-A`:**
  The directory-confirmed session removes the whole reviewed `sub` tree, including the empty
  directory and the symlink, records a success result frame, and the symlink target outside the
  reviewed tree survives.

## Forbidden effects

- **`NO-EXEC-MUTATION-A`:**
  The drifted session never records a successful mutation: the changed leaf survives and the run
  log records a failure result frame.
- **`NO-EXEC-DIRECTORY-A`:**
  The directory-drifted session never records a successful mutation: the replaced child and the
  directory survive and the run log records a failure result frame.

## Instrumentation

```zig tj-test
try fixture.given_program("termux-janitor");
try fixture.given_isolated_tree();
try fixture.when_run_sessions();
try fixture.then_inv_exec_mutation_a();
try fixture.then_inv_exec_ancestor_a();
try fixture.then_inv_exec_directory_a();
try fixture.forbid_no_exec_mutation_a();
try fixture.forbid_no_exec_directory_a();
```

## Variations

Ancestor-replacement drift, mount changes, and whole-directory child-set comparison are owned by
the manifest suite in [`requirements/manifest_a.md`](../requirements/manifest_a.md).

## Limitations

The sessions observe the final filesystem and run-log state plus the terminal byte stream; they do
not trace syscalls, so adjacency of check and mutation is inferred from the recorded frame order
and the single final-interval race disclosure in `PRODUCT.md` section 11.1 remains outside this
fixture.