Skip to content

refactor(tasks): give comment, restore and field rules one home - #69

Closed
HecFranco wants to merge 4 commits into
mainfrom
refactor/213-s1-shared-moves
Closed

HecFranco wants to merge 4 commits into
mainfrom
refactor/213-s1-shared-moves

Conversation

@HecFranco

@HecFranco HecFranco commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Second slice of spec 213. Stacked on #67. No behaviour change for hosts; audit status re-verification pending.

A write path other than the UI's forms must apply the same rules, so they get one home. Only TaskBoardManageController and six form types change.

Moved From To
Who may comment, edit, delete private methods in the controller Service\TaskCommentPolicy
Restore: limit, restore, history restoreTask() TaskManager::restore(), throwing TaskReopenRefusedException
Field rules inline in six form types Validation\TaskConstraints

Flash, redirect, panel fragment, status and log calls stay in the controller. TaskBoardConnectionController is untouched.

Also removes the controller's $syncLimits argument: TaskManager already gets the same SyncLimitCheckerInterface by autowiring (the restore characterization tests, with TestSyncLimitChecker, prove it).

New, no caller yet (the UI has no equivalent): TaskBoardEraser::eraseTask(), TaskBoardEditor, TaskManager::archive(), TaskDependencyManager::findBetween(), TaskFormData::fromTask(), BOARD_UPDATED.

Proof that the UI's output stayed the same

  • tests/Functional/Characterization from test(ui): characterize UI writes before spec 213 moves them #67 is unchanged and passes: git diff f7ea333 -- tests/Functional/Characterization is empty.
  • Byte comparison, same vendor, PHP 8.2: the 9 pages the tests write (task page for editor and readers, panel fragment, board, list, index, import), ids and dates masked, have no difference before and after this change. Two runs of the baseline are also identical, so the method is stable.
  • No existing test or fixture changed.

For the auditor

  • eraseTask(): parent_id is ON DELETE CASCADE, so it erases leaf-first through Doctrine; testEraseTaskRemovesTheSubtreeLeafFirstAndKeepsEveryMinute covers time on a child and a grandchild.
  • eraseTask() emits TaskErasedEvent with no storage refs: a task with stored provider files follows a provider, so it is refused.
  • The existing UI bug in TaskManager::update() (column change without completion sync or reopen limit) is deliberately not touched here.

Gates run locally

Full PHPUnit, PHPStan, cs-check.

Not for merge until the coordinator's audit step.

Audit IA fixes

  • IA-M1: eraseTask() names the stored files of the subtree in each TaskErasedEvent and removes their rows. Proof test SyncEraseTaskRefsTest (ported from the auditor), run on SQLite and PostgreSQL 16; it fails without the fix.
  • IA-I1: $syncLimits is back in its place, deprecated and ignored; TaskBoardManageControllerSignatureTest pins the 2.1 constructor order.
  • Takes main (2.1.1, fix(index): one New board, always primary, Views buttons at the end #68) and the 1G PHPUnit ceiling, which this branch now needs too.

…pec 213 S0)

Pins what the UI answers before the rules behind it move in the next slice:
status, Location, flashes, log lines, events and history for the comment and
restore routes, and the constraints of the six write forms. No src change.

With TASK_BOARD_CHARACTERIZE_DIR set the tests also write the pages with ids and
dates masked, so two checkouts on one vendor can be compared byte by byte.
… 213 S1)

A write path other than the UI's forms must apply the same rules, so they leave
the controller and the form types: TaskCommentPolicy, TaskManager::restore() and
Validation\TaskConstraints. tests/Functional/Characterization from the previous
commit is unchanged and passes, and the rendered pages are byte-identical.

Adds what the UI does not have and the API will need, with no caller yet:
TaskBoardEraser::eraseTask() (leaf-first, so PreRemove keeps every minute; refuses
a task that follows a provider), TaskBoardEditor, TaskManager::archive(),
TaskDependencyManager::findBetween(), TaskFormData::fromTask().
@HecFranco
HecFranco changed the base branch from test/213-s0-ui-characterization to main November 7, 2026 21:07
@HecFranco HecFranco closed this Nov 7, 2026
@HecFranco HecFranco reopened this Nov 7, 2026
…d-moves

# Conflicts:
#	docs/CHANGELOG.md
#	docs/UPGRADING.md
…audit IA)

IA-M1: eraseTask() handed the host no stored-file refs. After an unlink the
sync's attachment rows outlive the link (GWd-M1), so the files were never named
again; on SQLite the rows stayed orphaned. The refs of the subtree are read
first, passed per task in TaskErasedEvent, and the rows removed. Proof test
ported from the auditor; run on SQLite and PostgreSQL 16.

IA-I1: TaskBoardManageController keeps $syncLimits in its place, deprecated
and ignored, so positional arguments do not move in a minor release.

Also takes main (2.1.1) and the 1G PHPUnit ceiling the coverage report needs.
@HecFranco

Copy link
Copy Markdown
Contributor Author

Included in #76 (squash ebbd373), released in v2.2.0.

@HecFranco HecFranco closed this Nov 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant