FN-5731: require confirmation before archiving near-duplicate tasks

Stop silent near-duplicate auto-archive by routing duplicates through explicit user confirmation in API, engine, and dashboard flows.

- add new near-duplicate confirmation metadata/types and preserve duplicate task rows until confirmation
- update workflow routes and triage logic to return confirmation-required outcomes instead of immediate archive
- add TaskCard and TaskDetailModal UI/actions plus styling and hook updates for confirming or rejecting duplicate handling
- expand dashboard and engine tests and task-management docs to cover the new confirmation path

Files changed:
docs/task-management.md                            | 14 ++++-
packages/core/src/types.ts                         |  4 ++
packages/dashboard/app/api/legacy.ts               |  1 +
packages/dashboard/app/components/TaskCard.css     | 59 ++++++++++++++++++
packages/dashboard/app/components/TaskCard.tsx     | 46 +++++++++++++-
packages/dashboard/app/components/TaskDetailModal.css   | 34 +++++++++++
packages/dashboard/app/components/TaskDetailModal.tsx   | 71 +++++++++++++++++++++-
packages/dashboard/app/components/__tests__/TaskCard.test.tsx     | 71 ++++++++++++++++++++++
packages/dashboard/app/components/__tests__/TaskDetailModal.rendering.test.tsx   | 68 +++++++++++++++++++++
packages/dashboard/app/hooks/useTasks.ts           |  2 +-
packages/dashboard/src/__tests__/routes-tasks-near-duplicate.test.ts  | 45 ++++++++++++++
packages/dashboard/src/routes/register-task-workflow-routes.ts    |  9 ++-
packages/engine/src/__tests__/reliability-interactions/near-duplicate-intake.test.ts                  | 16 +++--
packages/engine/src/triage.ts                      | 19 +++---
14 files changed, 433 insertions(+), 26 deletions(-)

Fusion-Task-Id: FN-5731

Fusion-Task-Lineage: fa004129-7bce-4457-b8c3-ceb9fb953319
This commit is contained in:
gsxdsm
2026-05-30 15:52:46 -07:00
parent 784c58f5c3
commit 24e0c44b4a
14 changed files with 433 additions and 26 deletions

View File

@@ -87,12 +87,20 @@ Layer 1 persists `source.sourceMetadata.intentSignature` on created tasks so lat
CLI `fn task create` now runs the same near-duplicate intent guard after the FN-4918 deterministic fingerprint guard, using shared `extractIntentSignature` / `findNearDuplicates` helpers from `@fusion/core`. Thresholds and the 7-day comparison window match the dashboard layer exactly. `--no-dedup` remains the single bypass across both duplicate layers: it skips the comparison but still stamps `source.sourceMetadata.intentSignature` when high-signal tokens were extracted. When a near-duplicate is detected, interactive TTY runs prompt `Create anyway? [y/N]`; non-interactive runs refuse creation with exit code 1 and instruct the caller to re-run with `--no-dedup`. The guard is still fail-open: extraction/list/query errors log a warning and continue. `fn task import` (GitHub import) and `fn task plan` intentionally continue to skip both duplicate guards per the FN-5060 same-content-sibling contract.
Layer 2 runs in triage `finalizeApprovedTask` after `PROMPT.md` is written and parses `## File Scope` as an additional backstop. If the new spec overlaps an older active task on concrete File Scope / intent tokens and still clears the title threshold, the newer task is auto-archived instead of moved to `todo`.
Layer 2 runs in triage `finalizeApprovedTask` after `PROMPT.md` is written and parses `## File Scope` as an additional backstop. If the new spec overlaps an older active task on concrete File Scope / intent tokens and still clears the title threshold, the newer task is flagged for user confirmation instead of being silently auto-archived.
Near-duplicate archival is reversible and leaves lineage markers behind:
Near-duplicate flagging now keeps the task in its normal flow column (`todo` / approval flow) and records metadata for UI warnings:
- `source.sourceMetadata.nearDuplicateOf = <canonicalTaskId>`
- activity event `task:auto-archived-near-duplicate`
- `source.sourceMetadata.nearDuplicateScore = <number>`
- `source.sourceMetadata.nearDuplicateSharedTokens = <string[]>`
- optional `source.sourceMetadata.nearDuplicateDismissed = true` after user chooses Keep
- activity event `task:near-duplicate-flagged`
Dashboard surfaces this as a yellow Duplicate chip plus modal actions:
- **Archive** (user-initiated archive path)
- **Keep** (dismisses the warning by setting `nearDuplicateDismissed: true`)
This layer complements, rather than replaces, FN-4829 similarity detection, FN-4918 deterministic deduplication, and FN-4892 same-agent intake heuristics.