小橙子 dbeb7750a1
feat(coordinator): worker-continue advisor — recommend SendMessage when a recent worker already loaded the same files (#21)
The roadmap calls for "worker-continue defaulting": coordinator mode
should prefer SendMessage to reuse a previous worker's prompt cache
instead of spawning a fresh one when it would re-load the same files.
This ships the spawn-time advisor that surfaces the recommendation.

What's in this PR
=================
- src/tools/AgentTool/workerContinueAdvisor.ts (new)
  Pure heuristic. Inputs: candidate-prompt + list of recently-completed
  panel agent tasks (with their touched files). Output: best continue
  candidate (most overlap, ties broken by recency) or null. Pure
  ranking — caller materialises the candidate list, this module is
  policy-only.
  - extractFilePathsFromPrompt: path-with-extension + bare known-extension
    filename matching, normalised to lowercase forward slashes for
    cross-OS comparison.
  - extractTouchedFilesFromActivities: pulls file_path (Read/Edit/Write/
    NotebookEdit) and path (Grep/Glob — directory mention as a weaker
    signal) from ProgressTracker.recentActivities. Bash command strings
    deliberately skipped (false-positive risk).
  - findContinueCandidate: scores by overlap size, requires same
    subagent_type (SendMessage to a type-mismatched worker would have it
    executing the wrong specialist's contract), filters out
    non-completed tasks and tasks older than 30 minutes.
- src/tools/AgentTool/workerContinueAdvisor.test.ts (new, 27 cases)
  Covers all four extraction paths, type-mismatch / non-completed /
  too-old filters, tie-breaking by recency, case-insensitive overlap,
  Windows-style path normalisation, env-flag gating, error message
  contract (no key="value" fragments — same rule as specialistRouter).
- src/tools/AgentTool/AgentTool.tsx
  Opt-in coordinator-only enforcement: when CLAUDE_CODE_COORDINATOR_CONTINUE_HINT=1
  and we're in coordinator mode with an explicit subagent_type, we
  collect completed panel tasks (isPanelAgentTask + status === completed
  + evictAfter !== 0), build the candidate list, and throw
  formatContinueHintError if a winner is found. Same opt-in shape as
  CLAUDE_CODE_GP_DEFAULT_STRICT / CLAUDE_CODE_COORDINATOR_SPECIALIST_ROUTER /
  CLAUDE_CODE_COORDINATOR_TASK_SPEC_STRICT for predictable rollback.
  Logged via tengu_agent_continue_hint with shared_files count and
  candidate age for adoption tracking.
- scripts/dev-coordinator-e2e.ps1
  Adds a 7th e2e step asserting:
    - Same-type worker overlap → continuation recommended.
    - Type mismatch → no recommendation.
    - File-free prompt → no recommendation.
    - Error message contract preserved (agentId, SendMessage, env flag).

Why opt-in (not default-on)
===========================
- Lazy-delegation lint and specialist redirect are blacklists: specific
  anti-patterns, near-zero false positives, safe to default on.
- Worker-continue is a positive-space heuristic: "the model could have
  done X better." Hard-failing a fresh spawn when the model legitimately
  wants a clean context (e.g. adversarial verification with no prior-
  approach anchoring) would be more annoying than helpful.
- Same opt-in shape as B2's task-spec strictness for predictable rollback
  and gradual team adoption.

Verification
============
- src/tools/AgentTool/workerContinueAdvisor.test.ts ........ 27/27 pass
- All B1+B2+B3 unit tests ................................. 132/132 pass
- scripts/dev-coordinator-e2e.ps1 ......................... GREEN (7 steps)
- get_diagnostics on changed files ........................ clean

Tested: bun test src/tools/AgentTool/workerContinueAdvisor.test.ts (27/27); all coordinator unit tests (132/132); scripts/dev-coordinator-e2e.ps1 step 7 GREEN
Not-tested: live coordinator session with the hint flag on (covered by the e2e module-level assertion of the throw + error shape; full live-LLM gate intentionally deferred to provider-credentialed runs)
Confidence: high
Scope-risk: narrow
Constraint: must NOT change AgentTool's input schema; must reuse the formatSpecialistRedirectMessage prose style to avoid the textual-tool_use regression; must require subagent_type match (SendMessage to a wrong-type worker would execute the wrong contract)
Rejected: defaulting the hint on (false-positive cost on legitimate fresh-context spawns); using prompt-string equality instead of file-overlap (would miss continuations where wording differs but the work is the same); recording Bash command strings as touched files (false-positive risk — `git status` is not a file touch)
Directive: when ProgressTracker.recentActivities is enlarged past 5 entries, revisit candidate-collection cost (currently linear over panel tasks × constant 5 activities — fine for typical sessions, but a 100-task panel × 50-activity tracker would warrant a memoised set)

Co-authored-by: 你的姓名 <you@example.com>
2026-06-12 04:19:26 +08:00
..