Files
pi-config/extensions/pi-crew/docs/refactor-tasks-phase6.md

35 KiB
Raw Permalink Blame History

Phase 6 Refactor Plan — Robustness sau test 0.1.27/0.1.29 + nợ kỹ thuật từ source-runtime-refactor-map

Xuất xứ:

  • Test thực tế run team_20260428152644_2ae0dce7 (parallel-research, 10/10 completed) trên pi-crew@0.1.27.
  • Re-read source 28/04/2026 sau bump 0.1.28 (responseTimeoutMs 15s→5m) và 0.1.29 (republish).
  • Findings còn lại từ docs/source-runtime-refactor-map.md (subagent runtime consolidation, model-routing persistence, adaptive planner repair).

Phase 5 đã hoàn tất (UI/footer/select-list/theme hot-reload). Phase 6 tập trung runtime hardening + maintainability, không phá public API.

Quy ước chung (giữ nguyên từ Phase 5)

  • Không phá vỡ public API: tool actions, slash commands, config schema, schema.json.
  • Sau mỗi task: npx tsc --noEmit + npm run test:unit (test:integration khi đụng runtime/spawn/state).
  • Không thêm runtime dependency mới ngoài stdlib + peer deps đã có (pi-coding-agent, pi-ai, pi-agent-core, pi-tui, jiti).
  • Mỗi task = 1 commit độc lập, có thể revert riêng. Test name bám sát hành vi (describe/it đặt theo contract chứ không theo file).
  • Default behavior không đổi (backward-compat); cải tiến hành vi đi qua opt-in env/config khi có nguy cơ regression.
  • Mỗi task có Acceptance + Verification + Risk/Rollback. Trước khi mở PR phải npm run ci (typecheck + test:unit + test:integration + npm pack --dry-run).

Roadmap tổng quan

Tier Workstream Số task Ước tính Ưu tiên
1 Background runner & async robustness T60T62 0.5 ngày P0 — chặn rủi ro silent fail
1 Concurrency hard cap T63 0.25 ngày P0 — chặn user override DoS
2 Resume durability cho synthesize/write T64T66 1 ngày P1 — nâng cao reliability
2 Adaptive planner repair/retry T67 0.5 ngày P1 — giảm block rate
2 Model routing persistence T68T69 0.5 ngày P1 — observability
3 register.ts modularization T70T72 1 ngày P2 — maintainability
3 Subagent runtime consolidation T73T75 1.5 ngày P2 — debt theo refactor map
3 Skills builtin + docs self-contained T76T78 0.5 ngày P3 — polish
4 Tests, smoke, CHANGELOG T79T81 0.5 ngày P0 (cuối phase)

Tổng: 22 task / ~6.25 ngày, có thể ship theo nhiều mini-release (0.1.30, 0.1.31, …).

Tiến độ triển khai

Task Trạng thái Commit / ghi chú
T60 Done bfd9bc8 — jiti loader resolution/fail-fast
T61 Done bfd9bc8 — async early-exit guard
T62 Done bfd9bc8 — async startup marker
T63 Done bfd9bc8 — concurrency hard cap + opt-out
T64 Done checkpoint phases + child-stdout-final/artifact-written resume recovery
T65 Done async notifier marks quiet dead background runners failed with async.died
T66 Done 5e495dc — replay pending mailbox on resume
T67 Done adaptive plan repair for malformed JSON, oversized plans, and role aliases
T68 Done 1f92b8a — persisted model routing metadata
T69 Done 1f92b8a — agent records carry routing metadata
T70 Done register.ts split to ≤200 lines with commands, team tool, subagent tools, artifact cleanup modules
T71 Done team-tool.ts split to ≤300 lines with status/inspect/lifecycle/cancel/plan modules
T72 Done task-runner.ts split to ≤300 lines with prompt/progress/state/live/result helper modules
T73 Done src/subagents/* entrypoints added and runtime call-sites migrated
T74 Done live-session APIs routed through src/subagents/live/* with dynamic task-runner import
T75 Done 1004589 + explicit subagent depth/role spawn tests
T76 Done f6ece8e — built-in coding skills
T77 Done 9e54acd — self-contained architecture docs
T78 Done 9e54acd — runtime flow docs
T79 Done multi-shard, no-wrapper spawn, and async restart recovery smokes covered
T80 Done package snapshot guards docs/skills/jiti/pi manifest packaging
T81 Done changelog release prep notes added; no publish/version bump performed

Tier 1 — Robustness chặn rủi ro silent fail (P0)

Task #60 — background-runner.ts fail-fast nếu jiti loader không tồn tại

Lý do (evidence): src/runtime/background-runner.ts getBackgroundRunnerCommand() xây cứng đường dẫn:

const jitiRegisterPath = path.join(packageRoot, "node_modules", "jiti", "lib", "jiti-register.mjs");
return { args: ["--import", pathToFileURL(jitiRegisterPath).href, runnerPath, ...], loader: "jiti" };

Nếu user xóa node_modules/jiti (npm prune, monorepo hoisting bất thường, broken install), spawn(process.execPath, ...) không fail ở Node parent — child sẽ exit lỗi ngay nhưng parent không capture được vì stdout đã child.unref() + đóng logFd. Background log chỉ chứa [pi-crew] background loader=jiti rồi im lặng. Run sẽ kẹt ở status running cho đến khi process-status.hasStaleAsyncProcess mark stale (>10 phút).

Đích: src/runtime/background-runner.ts

Steps:

  1. Trước khi spawn, kiểm tra fs.existsSync(jitiRegisterPath). Nếu thiếu → throw Error với message rõ ràng:
    pi-crew background runner cannot start: jiti loader not found at
    <jitiRegisterPath>. Reinstall pi-crew (`pi install npm:pi-crew`) or
    ensure node_modules/jiti is present.
    
  2. Caller (team-tool/run.ts qua spawnBackgroundTeamRun) đã có try/catch — đảm bảo error propagate ra notify cho user.
  3. Append error vào events.jsonl qua appendEvent(eventsPath, { type: "async.failed", message }) trước khi throw.
  4. Mở rộng: thêm fallback path tìm jiti trong require.resolve.paths() của parent module (Windows monorepo hoist) — nếu primary path missing thì thử path.join(packageRoot, "..", "..", "node_modules", "jiti", "lib", "jiti-register.mjs") (npm hoisting 2 cấp). Nếu cả hai miss thì mới throw.

Acceptance:

  • Khi node_modules/jiti/lib/jiti-register.mjs thiếu → spawnBackgroundTeamRun throw với message hướng dẫn reinstall.
  • Khi user dùng monorepo hoisting (jiti ở root workspace) → vẫn resolve được.
  • events.jsonl có entry async.failed trước khi spawn.
  • Không regression với case có jiti (path 1 hit).

Tests: test/unit/background-runner.fail-fast.test.ts

  • Stub fs.existsSync để giả lập miss → assert throw với pattern /jiti loader not found/.
  • Stub hoist path tồn tại → assert dùng path thay thế.
  • Cleanup không leak global state (vi-style spy + restore).

Verification:

npx tsc --noEmit
node --experimental-strip-types --test test/unit/background-runner.fail-fast.test.ts

Risk/Rollback: Risk thấp — chỉ thêm sanity check trước spawn. Rollback bằng cách revert commit.

Security/Perf notes: Không I/O bổ sung trong hot path (chỉ 1 stat khi spawn background). Không log đường dẫn đầy đủ ở mức user message để tránh lộ home directory; dùng shortenPath() từ utils/visual.ts nếu có.


Task #61 — Capture early-exit của background runner (drain background.log)

Lý do: Hiện sau child.unref(); fs.closeSync(logFd); parent quên child. Nếu background-runner.ts lỗi cú pháp/import (không phải jiti missing nhưng vẫn fail), log chỉ chứa stderr Node. Status tool báo Async: pid=X alive=false sau khi process exit, nhưng manifest status vẫn running. User phải đợi hasStaleAsyncProcess (10 phút) mới detect.

Đích: src/extension/team-tool/run.ts (caller) và src/runtime/process-status.ts

Steps:

  1. Trong caller, lưu pid ngay sau spawn. Schedule một check sau ~3s (setTimeout + unref) gọi checkProcessLiveness(pid):
    • Nếu alive=false AND manifest vẫn running AND chưa có event async.started → đọc background.log (last 4KB), append event async.failed với log tail và updateRunStatus(manifest, "failed", "Background runner exited within 3s; see background.log").
  2. Cancel setTimeout nếu trong khoảng đó status đã chuyển khác running.
  3. Đảm bảo không double-write status nếu background process đã write async.failed từ catch block.

Acceptance:

  • Background runner exit ngay → run status chuyển failed trong ≤4s với reason có tail log.
  • Background runner chạy bình thường → không có false positive.

Tests: test/integration/background-early-exit.test.ts

  • Mock spawnBackgroundTeamRun với child exit ngay (set PI_TEAMS_MOCK_CHILD_PI=fail-immediate + extend mock branch).

Verification: npm run test:integration -- background-early-exit

Risk/Rollback: Cần test kỹ với case async hợp lệ; rollback bằng feature flag PI_CREW_ASYNC_EARLY_EXIT_GUARD=0.


Task #62 — async.started event timeout & marker file

Lý do: Bổ sung T61. Background runner ghi async.started vào events.jsonl ở dòng đầu main(). Nếu file events.jsonl bị lock (Windows), event không append được. Caller hiện không có cơ chế chờ confirm.

Đích: src/runtime/async-runner.ts + src/runtime/background-runner.ts

Steps:

  1. Background runner ghi marker file state/runs/{runId}/async.pid chứa {pid, startedAt} ngay sau khi appendEvent("async.started") thành công.
  2. Caller (T61) khi healthcheck 3s đọc thêm marker file: nếu marker tồn tại → coi như runner đã start ổn.
  3. Bổ sung process-status.hasAsyncStartMarker(runId).

Acceptance: Marker tồn tại sau khi async runner startup; healthcheck dùng marker khi events.jsonl không khả dụng (Windows lock fallback).

Tests: unit cho hasAsyncStartMarker (file exists/missing/parse error).

Verification: npm run test:unit


Task #63 — Hard cap cho limits.maxConcurrentWorkers

Lý do: src/runtime/concurrency.ts.resolveBatchConcurrency() dùng limits.maxConcurrentWorkers user truyền không cap. User config limits.maxConcurrentWorkers=64 → 64 child Pi process spawn song song → DoS local. parallel-utils.MAX_PARALLEL_CONCURRENCY=4 chỉ áp ở subagent runner cấp thấp, không bảo vệ scheduler.

Đích: src/runtime/concurrency.ts, src/config/defaults.ts, src/config/config.ts

Steps:

  1. Thêm DEFAULT_CONCURRENCY.hardCap = 8 vào defaults.ts.
  2. Trong resolveBatchConcurrency, sau requested = limitMax ?? teamMax ?? workflowMax ?? defaultWorkflowConcurrency:
    const cap = positiveInteger(input.hardCap) ?? DEFAULT_CONCURRENCY.hardCap;
    const effective = Math.min(requested, cap);
    
  3. Khi effective < requested, ghi reason thêm ;capped:${cap} để observability.
  4. Cho phép user opt-out qua config.limits.allowUnboundedConcurrency=true (gated qua warning event limits.unbounded + log dòng đầu run, default false).
  5. Cập nhật schema.json + config-schema.ts cho field mới.

Acceptance:

  • limits.maxConcurrentWorkers=64 (default) → effective=8, reason chứa capped:8.
  • limits.maxConcurrentWorkers=64, allowUnboundedConcurrency=true → effective=64, có event warning.
  • Không regression cho values hợp lý (≤8).

Tests: test/unit/concurrency.cap.test.ts

  • 4 case: requested=2 (no cap), requested=12 (cap=8), unbounded flag (no cap), workflow=parallel-research workflowMax=4 (no cap).

Verification: npx tsc --noEmit && node --experimental-strip-types --test test/unit/concurrency.cap.test.ts

Risk/Rollback: Có thể vô tình giảm throughput cho user power-user. Mitigate bằng allowUnboundedConcurrency flag. Rollback: revert + bump major nếu user đã dựa vào behavior cũ (chưa rõ).

Security/Perf notes: Bảo vệ memory/cpu local; mỗi child Pi consume ~200MB RAM. 8 = 1.6GB worst case, hợp lý cho dev machine.


Tier 2 — Reliability nâng cao (P1)

Task #64 — Resume detection: synthesize/write checkpoint

Lý do: team-runner.executeTeamRun không biết task synthesize/write đã completed một phần khi crash giữa chừng. Khi resume (team resume runId), task synthesize re-run từ đầu, gọi LLM lại tốn cost. Risk #5 trong test report.

Đích: src/runtime/task-runner.ts, src/state/state-store.ts, src/state/types.ts

Steps:

  1. Mở rộng TeamTaskState thêm checkpoint?: { phase: "started" | "child-spawned" | "child-stdout-final" | "artifact-written"; updatedAt: string; childPid?: number }.
  2. runTeamTask ghi checkpoint qua saveRunTasks ở 4 điểm:
    • Trước runChildPi (started)
    • Sau child.pid có (child-spawned + pid)
    • Khi nhận isFinalAssistantEvent (child-stdout-final)
    • Sau writeArtifact (artifact-written)
  3. team-tool.handleResume xét checkpoint:
    • Nếu checkpoint.phase === "artifact-written" mà status vẫn running → mark completed (recovery, không re-run).
    • Nếu checkpoint.phase === "child-stdout-final" → cố parse output từ transcripts/{taskId}.jsonl last lines, nếu có valid message_end thì mark completed mà không re-spawn.
    • Else → re-queue.

Acceptance:

  • Crash sau khi artifact ghi xong → resume mark completed không re-run LLM.
  • Crash giữa stdout streaming → resume cố recover từ transcript; nếu không thành công thì re-run.
  • State migration backward-compat (task cũ không có checkpoint → resume hoạt động như cũ).

Tests: test/integration/resume-checkpoint.test.ts

  • 3 case: pre-spawn crash, mid-stream crash, post-artifact crash.

Verification: npm run test:integration -- resume-checkpoint

Risk/Rollback: Touch durable state shape. Cần migration: nếu task không có checkpoint, treat như chưa start. Rollback: revert + xóa field optional khỏi types.


Task #65 — Resume cho async background run sau parent crash

Lý do: Khi parent Pi session crash, background runner vẫn chạy; manifest cập nhật bình thường. Nhưng nếu background runner crash (ví dụ jiti corrupted, OOM), không có ai mark run failed cho đến hasStaleAsyncProcess 10 phút sau. Status sẽ misleading.

Đích: src/runtime/process-status.ts, src/extension/async-notifier.ts

Steps:

  1. Mở rộng async-notifier.ts.startAsyncRunNotifier: với mỗi run đang running, mỗi notifierIntervalMs (5s) check checkProcessLiveness(async.pid). Nếu alive=false VÀ run status running AND không có event nào trong 30s gần nhất → updateRunStatus(manifest, "failed", "Background runner died unexpectedly; check background.log").
  2. Bổ sung guard: chỉ thực hiện nếu chưa có event async.completed/async.failed (avoid double-write).

Acceptance: Background runner kill -9 → trong ≤30s status chuyển failed, có event async.died.

Tests: test/integration/async-died.test.ts (mock spawn process exit ngẫu nhiên).

Verification: npm run test:integration -- async-died

Risk/Rollback: False positive khi event log chậm flush. Mitigate: chỉ trigger khi không alive AND last event > 30s. Rollback: revert async-notifier hook.


Task #66 — Mailbox replay khi resume

Lý do: state/mailbox có inbox/outbox JSONL nhưng resume không re-deliver pending messages. Risk #5 mở rộng.

Đích: src/state/mailbox.ts, src/extension/team-tool/api.ts

Steps:

  1. Khi resume, đọc mailbox/delivery.json. Mọi message direction=inbox chưa acked=true → re-emit trong batch đầu.
  2. Add validate-mailbox repair=true vào doctor checks để cleanup stale messages > 7 ngày.

Acceptance: Resume sau crash giữa khi mailbox có 3 message pending → 3 message được redelivered.

Tests: test/unit/mailbox-replay.test.ts

Verification: npm run test:unit


Task #67 — Adaptive planner repair/retry trước khi block

Lý do: team-runner.injectAdaptivePlanIfReady block ngay khi __test__parseAdaptivePlan fail (oversize >12 task / JSON malformed / role không hợp lệ). User phải re-run từ đầu. Refactor map đã ghi nhận: "Add adaptive planner repair/retry for invalid JSON instead of immediate block when safe."

Đích: src/runtime/team-runner.ts, agents/planner.md

Steps:

  1. Khi parse fail, thay vì return missingPlan: true ngay, thử repair:
    • Nếu JSON malformed → spawn 1 child Pi tiny (planner role, model rẻ — Haiku/gpt-5-nano) với prompt: Fix the following JSON to comply with the adaptive plan schema. Return only ADAPTIVE_PLAN_JSON_START ... ADAPTIVE_PLAN_JSON_END.\n<failed_text>. Cap retry = 1, timeout 60s.
    • Nếu oversize (>12 task) → tự trim phases tail tới ≤12 task, ghi event adaptive.plan_trimmed.
    • Nếu role không hợp lệ → map sang role gần nhất (reviewercode-reviewer nếu team có) hoặc skip task đó nếu phase không trống.
  2. Nếu repair fail → mới block (giữ behavior hiện tại). Ghi event adaptive.plan_repair_failed.
  3. Persist repair attempt vào metadata/adaptive-repair.json để debug.

Acceptance:

  • Plan JSON malformed nhỏ (thiếu }) → repair fix → run tiếp.
  • Plan 15 task → trim còn 12, run tiếp với warning.
  • Plan với role lạ → map hoặc skip task; nếu không cứu được thì block với explain rõ ràng.

Tests: test/unit/adaptive-repair.test.ts (3 fixture: malformed, oversize, invalid-role).

Verification: npm run test:unit -- adaptive-repair

Risk/Rollback: Có thể ăn thêm 1 model call. Mitigate: chỉ retry khi cost < 0.001 USD ước tính (Haiku tier). Rollback: env PI_CREW_ADAPTIVE_REPAIR=0.


Task #68 — Persist model routing (requested → selected → fallback chain → reason)

Lý do: Refactor map: "Move model routing transparency into persisted task/subagent records: requested model, selected model, fallback chain, fallback reason." Hiện task state chỉ có modelAttempts: ModelAttemptSummary[] (model + success + error) nhưng không persist requestedModel ban đầu user/agent yêu cầu, cũng như reason vì sao chuyển fallback.

Đích: src/runtime/model-fallback.ts, src/state/types.ts, src/runtime/task-runner.ts

Steps:

  1. Mở rộng TeamTaskState.modelRouting?: { requested?: string; resolved: string; fallbackChain: string[]; reason?: string; usedAttempt: number }.
  2. buildConfiguredModelCandidates trả thêm requestedModel (model agent.md / step.model trước fallback).
  3. runTeamTask write modelRouting cùng modelAttempts.
  4. team-tool.handleStatus render section Model routing: nếu có. Dashboard agent rows hiển thị model · ≥requested:claude-sonnet-4-5 → openai-codex/gpt-5.5 (rate-limit).

Acceptance:

  • Task chạy thành công lần 1 → usedAttempt=0, fallbackChain chứa chain config (không cần markFallback).
  • Task fallback từ A → B vì rate-limit → reason: "rate-limit", usedAttempt=1.
  • Status output có dòng Model routing cho mỗi task có routing data.

Tests: test/unit/model-routing.test.ts

Verification: npm run test:unit

Risk/Rollback: Task state shape mở rộng — backward-compat (field optional). Rollback: revert types + hide UI.


Task #69 — Subagent records lưu model routing

Lý do: Liên quan T68 nhưng cho crew-agent-records (file-backed agent status hiển thị ở dashboard). Hiện chỉ có model field (latest selected); cần requestedModel + fallbackChain.

Đích: src/runtime/crew-agent-records.ts

Steps:

  1. Mở rộng CrewAgentRecord thêm routing?: TeamTaskState["modelRouting"].
  2. recordFromTask map từ task.modelRouting.
  3. live-run-sidebar render routing ở chỗ model row.

Tests: snapshot trong test/unit/crew-agent-records.test.ts.

Verification: npm run test:unit


Tier 3 — Maintainability & debt cleanup (P2)

Task #70 — Tách register.ts thành sub-modules theo lifecycle

Lý do: src/extension/register.ts ~38KB trộn: lifecycle, RPC, manifest cache, foreground controller, sidebar, widget, mascot, command parsing, subagent manager, viewers. Quy tắc AGENTS.md "Keep index.ts minimal; register functionality from src/extension/register.ts. Prefer small modules over large orchestrator files." Đã có sub-folders registration/ + team-tool/ nhưng register.ts vẫn lớn.

Đích: src/extension/register.ts → split

Steps:

  1. Tách thành 5 module:
    • src/extension/registration/lifecycle.ts — session_start/session_before_switch/session_shutdown handlers + cleanupRuntime.
    • src/extension/registration/widget-loop.ts — widget interval, sidebar lifecycle (openLiveSidebar, liveSidebarTimer).
    • src/extension/registration/foreground-runner.tsstartForegroundRun + foregroundControllers.
    • src/extension/registration/subagent-tools.ts — Agent/get_subagent_result/steer_subagent + crew_* aliases.
    • src/extension/registration/commands.ts — đăng ký toàn bộ slash command (/teams, /team-run, …).
  2. register.ts còn lại chỉ là wiring (≤200 dòng): tạo state, gọi các module.
  3. Giữ public API (export registerPiTeams, __test__subagentSpawnParams).

Acceptance:

  • register.ts ≤200 dòng.
  • Mỗi module mới ≤300 dòng.
  • Tests cũ pass không thay đổi.
  • Thêm test snapshot cho commands list (đảm bảo không drop command nào).

Tests: test/unit/registration.commands-coverage.test.ts (assert 25 commands đăng ký).

Verification: npx tsc --noEmit && npm run test

Risk/Rollback: Refactor lớn — risk regression. Mitigate: tách từng commit nhỏ (1 module / commit). Rollback: revert lần lượt.


Task #71 — Tách team-tool.ts actions còn lại

Lý do: src/extension/team-tool.ts ~32KB. Đã có team-tool/{api,run,doctor}.ts. Còn handleStatus, handleEvents, handleArtifacts, handleWorktrees, handleResume, handleCancel, handleSummary, handleCleanup, handleForget, handlePrune, handleExport, handleImport, handleImports ở file chính.

Đích: src/extension/team-tool.ts → split

Steps:

  1. Tạo src/extension/team-tool/{status,events,artifacts,resume,lifecycle-actions}.ts.
  2. team-tool.ts chỉ giữ router (handleTeamTool) + handleList/handleGet (đã ngắn).

Acceptance: team-tool.ts ≤300 dòng. Mỗi sub-module ≤300 dòng.

Tests: existing pass.

Verification: npm run test


Task #72 — Tách task-runner.ts

Lý do: src/runtime/task-runner.ts ~28KB chứa: prompt building, child-pi orchestration, artifact writing, verification evidence, transcripts, retry logic, mailbox bridge.

Đích: split thành:

  • task-runner/prompt-builder.ts (renderTaskPrompt + readOnlyRoleInstructions + coordinationBridgeInstructions).
  • task-runner/artifact-writer.ts (writeTaskInputs/Outputs/Transcripts/Diff).
  • task-runner/retry.ts (model fallback retry loop).
  • task-runner/index.ts exports runTeamTask.

Acceptance: Mỗi module ≤300 dòng. Public function signature không đổi.

Tests: existing pass + snapshot prompt cho mỗi role (4 role).

Verification: npm run test:integration -- task-runner


Task #73 — Consolidate child-pi + async-runner + subagent-manager thành src/subagents/

Lý do: Refactor map (đã ghi nhận từ Phase 0): "Consolidate subagent runtime into src/subagents/* or equivalent durable-first module." Hiện 3 file rải rác:

  • src/runtime/child-pi.ts (435 dòng) — spawn pi CLI con
  • src/runtime/async-runner.ts (~50 dòng) — entrypoint background
  • src/runtime/subagent-manager.ts (~290 dòng) — Agent tool backend

Đích: tạo folder src/subagents/ chứa:

  • src/subagents/spawn.ts (lift từ child-pi.ts)
  • src/subagents/observer.ts (ChildPiLineObserver + compactor)
  • src/subagents/manager.ts (lift từ subagent-manager.ts)
  • src/subagents/async-entry.ts (lift từ async-runner.ts)
  • src/subagents/index.ts re-export public API

Để các file runtime/child-pi.ts thành thin re-export (deprecated path) cho 12 release rồi xóa.

Acceptance:

  • Import paths cũ vẫn hoạt động (re-export shim).
  • Không thay đổi logic; chỉ move + group.
  • Tests cũ pass.

Tests: existing.

Verification: npm run ci

Risk/Rollback: Nhiều file đổi import. Mitigate: làm bằng IDE rename/move chứ không edit thủ công. Rollback: revert.


Task #74 — Tách live-session runtime khỏi child-process

Lý do: src/runtime/live-session-runtime.ts (~14KB) gating sau cờ experimental, nhưng vẫn import từ task-runner chính. Nếu mai có người bật PI_CREW_ENABLE_EXPERIMENTAL_LIVE_SESSION, code path xen lẫn dễ break.

Đích: di chuyển live-session-runtime.ts + live-agent-control/manager + live-agent-control-realtime.ts vào src/subagents/live/ (subdirectory mới của T73).

Acceptance: runtime/runtime-resolver.ts chỉ phụ thuộc qua subagents/live. Default flow (child-process) không import live module.

Tests: existing.


Task #75 — Subagent depth/permission hardening

Lý do: pi-args.checkCrewDepth đã check PI_CREW_DEPTH env. Cần test thêm: subagent gọi recursive (Agent tool trong agent) > maxDepth → block + clear message.

Đích: src/subagents/manager.ts, src/runtime/pi-args.ts

Steps:

  1. Add explicit test cho recursive spawn.
  2. Bổ sung role-permission.ts để chặn agent có role read_only không được gọi tool Agent/crew_agent.

Tests: test/unit/subagent-depth.test.ts, test/unit/role-permission.spawn.test.ts.

Verification: npm run test:unit


Tier 3 — Polish (P3)

Task #76 — Skills builtin: extract từ Source/awesome-agent-skills + adapt

Lý do: pi.skills trong package.json khai báo ./skills nhưng folder chỉ có .gitkeep. Có thể adapt 510 skill cốt lõi từ Source/awesome-agent-skills/README.md, Source/oh-my-claudecode/skills/, Source/superpowers/.

Đích: skills/

Steps:

  1. Chọn 5 skill phù hợp coding:
    • safe-bash (gate dangerous commands)
    • verify-evidence (final assistant must include changed files + verification)
    • git-master (commit hygiene + Conventional Commits)
    • read-only-explorer (forbid edits when role is explorer/analyst)
    • task-packet (enforce scope/inputs/outputs section)
  2. Mỗi skill là file .md trong skills/{name}/SKILL.md + optional helper scripts.
  3. Adapt mà không copy nguyên văn (giữ MIT compliance + ghi nguồn trong NOTICE.md).
  4. Reference từ agents/*.md qua skills: safe-bash, verify-evidence frontmatter.

Acceptance:

  • 5 skill files ≤500 dòng mỗi file.
  • NOTICE.md cập nhật source attribution.
  • Test discovery: discover-skills.ts (có chưa? — bổ sung nếu chưa có) trả về 5.

Tests: test/unit/skills.discovery.test.ts.

Verification: npm run test:unit -- skills.discovery

Risk/Rollback: Có thể inflate package size. Mitigate: skills nhỏ ≤4KB mỗi cái.


Task #77 — docs/architecture.md self-contained

Lý do: pi-teams/docs/architecture.md hiện trỏ ra ../docs/pi-crew-source-review-and-lessons.md, ../docs/pi-crew-architecture.md, ../docs/pi-crew-mvp-plan.md — các file nằm ngoài package, sẽ broken khi npm publish.

Đích: pi-teams/docs/architecture.md

Steps:

  1. Inline nội dung kiến trúc cốt lõi (3 layer: extension/runtime/state, lifecycle diagram, durable run state, autonomous routing).
  2. Bỏ reference ra file workspace bên ngoài.
  3. Thêm sequence diagram ASCII cho run flow (extension → team-runner → task-runner → child-pi → state).
  4. Liên kết tới usage.md, resource-formats.md, live-mailbox-runtime.md, publishing.md (đều trong package).

Acceptance:

  • File ≤600 dòng, không link out-of-package.
  • npm pack --dry-run ship đầy đủ docs/.

Verification: manual review + npm pack --dry-run.


Task #78 — docs/runtime-flow.md (mới) + sequence diagram

Lý do: Onboarding contributor cần một biểu đồ/text mô tả full flow. Hiện rải rác giữa architecture.md, source-runtime-refactor-map.md, refactor-tasks.md.

Đích: tạo mới pi-teams/docs/runtime-flow.md

Steps:

  1. ASCII sequence diagram: user → handleTeamTool(run) → executeTeamRun → resolveBatchConcurrency → runTeamTask → runChildPi → child stdout → ChildPiLineObserver → onJsonEvent → updateRunStatus → notify.
  2. Bảng "trigger → handler" cho mỗi action (run, resume, cancel, ...).
  3. Liệt kê env var ảnh hưởng (PI_TEAMS_*, PI_CREW_*, PI_CODING_AGENT_DIR).

Acceptance: Document ≤400 dòng, tự đứng được không cần đọc thêm.


Tier 4 — Tests, smoke, release (P0 cuối phase)

Task #79 — Integration smoke: Windows process visibility + multi-shard fanout

Lý do: Refactor map: "Add real integration smoke scripts for Windows process visibility, async restart recovery, and multi-shard fanout." Test report user vừa gửi đã chứng minh fanout chạy được, nhưng cần script lặp lại được.

Đích: test/integration/

Steps:

  1. test/integration/windows-no-blank-console.test.ts: spawn pi --version qua pi-spawn.getPiSpawnCommand với windowsHide:true → assert process spawned, no console window (heuristic: child.spawnargs không chứa cmd /c start).
  2. test/integration/multi-shard-fanout.test.ts: dùng expandParallelResearchWorkflow với fixture Source/pi-* mock (5 thư mục dummy) → assert 4 shard sinh ra, mỗi shard có ≥1 path, dependency synthesize đúng tất cả shard.
  3. test/integration/async-restart-recovery.test.ts: spawn background, kill -9, gọi team status → mark failed trong ≤30s (T65 dependency).

Acceptance: 3 test pass trên Windows runner CI.

Verification: npm run test:integration


Task #80 — Update npm pack --dry-run snapshot + schema.json

Lý do: Sau khi thêm config field (T63 allowUnboundedConcurrency), schema.json exported và config-schema.ts cần đồng bộ.

Đích: schema.json, src/schema/config-schema.ts

Steps:

  1. Regenerate schema.json từ TypeBox schema (script scripts/generate-schema.ts nếu có; nếu không thì update manually + diff review).
  2. npm pack --dry-run capture file list, snapshot vào test (test/unit/package-files.test.ts).

Acceptance: schema.json reflect mọi field config; snapshot test verify không drop file ship.


Task #81 — CHANGELOG + release prep

Lý do: Theo AGENTS.md global Section 2, mỗi PR cần Files & Rationale + Tests + Risks/Rollback. Phase 6 sẽ ship qua nhiều mini-release.

Đích: CHANGELOG.md

Steps:

  1. Thêm sections theo nhóm Tier:
    • ## 0.1.30 — async/concurrency hardening (T60T63, T79).
    • ## 0.1.31 — resume durability + adaptive repair (T64T67).
    • ## 0.1.32 — model routing observability (T68T69).
    • ## 0.2.0 — refactor: subagent runtime + register split (T70T75) — minor bump vì internal API thay đổi.
    • ## 0.2.1 — skills + docs (T76T78).
  2. Mỗi entry follow format: ### Added / Changed / Fixed / Breaking Changes.

Acceptance: CHANGELOG đầy đủ; npm version script chạy clean.


Phụ lục A — Acceptance gate cho mỗi mini-release

Trước khi tag/publish:

# Hard gate
npm run typecheck
npm run test:unit
npm run test:integration
npm pack --dry-run

# Soft gate (manual)
/team-doctor    # in Pi smoke session
/team-validate
/team-autonomy status

# Cross-platform
# Trigger CI ubuntu/windows/macos workflow trước khi tag

Phụ lục B — Bảng phụ thuộc giữa task

T60 ──► T61 ──► T62
                ▲
T63 (độc lập) ──┘
T64 ──► T65 ──► T66
T67 (độc lập)
T68 ──► T69
T70 ──► T71 ──► T72
T73 ──► T74 ──► T75 (cần T70 ổn định trước)
T76 (độc lập)
T77 ──► T78
T79 phụ thuộc T63 (concurrency cap), T65 (async-died)
T80 phụ thuộc T63
T81 sau cùng

Phụ lục C — Ánh xạ mỗi task ↔ rủi ro/follow-up đã nêu

Task Nguồn yêu cầu
T60T62 Test report risk #2 + Phase analysis "fail-fast nếu jiti fail"
T63 Test report risk #4
T64T66 Test report risk #5 + refactor map "async restart recovery"
T67 refactor-map "adaptive planner repair/retry"
T68T69 refactor-map "model routing transparency persisted"
T70T72 AGENTS.md "small modules" + analysis "register.ts/team-tool.ts/task-runner.ts cồng kềnh"
T73T75 refactor-map "consolidate subagent runtime into src/subagents/*"
T76 analysis "skills/ trống"
T77T78 analysis "doc kiến trúc trỏ ra ngoài package" + onboarding
T79 refactor-map "real integration smoke scripts"
T80T81 release hygiene

Phụ lục D — "Reply with" template cho mỗi PR

Mỗi PR Phase 6 phải tuân thủ AGENTS.md Section 10:

Summary: <1 dòng impact>
Plan:
- <bước 1>
- <bước 2>

Files & Rationale:
- src/.../...: <lý do>

Tests:
- <test name>: <kịch bản>

Verification:
- npx tsc --noEmit → Passed
- npm run test:unit → 0 failed / N passed
- npm run test:integration → 0 failed / N passed
- npm pack --dry-run → file list match snapshot

Risks & Rollback:
- <rủi ro>
- <feature flag / revert plan>

Security & Perf Notes:
- <OWASP / RAM / IO>

Khuyến nghị triển khai:

  1. Đi theo thứ tự Tier (P0 → P3); không pha trộn refactor lớn (T70T75) với hardening (T60T67).
  2. Mỗi Tier ship 1 mini-release để có baseline ổn định trước Tier kế.
  3. Trước Tier 3 (T70T75) chạy full test trên CI Windows + macOS để bắt regression cross-platform.
  4. Sau mỗi task: chạy /team-doctor trong Pi session để smoke; mở dashboard /team-dashboard xác nhận không stale.