# Maintainer guide

[English](../en/maintainer-guide.md)

## Chạy toàn bộ test

`npm test` chạy tối đa hai file test đồng thời, giống `npm run verify`.
Nhiều file integration dùng SDK, worker sandbox và trình duyệt thật; giới hạn số
file cạnh tranh tránh làm cạn thời gian chờ hiện có. Giới hạn này không đổi danh
sách test hoặc assertion. Đặt tùy chọn Node runner trước đường dẫn file; nối
`--test-concurrency=2` sau `npm test --` không cấu hình được script này.

## Rule đặt code

Trước khi thêm code, cần trả lời một câu hỏi về ownership:

| Câu hỏi | Vị trí |
|---|---|
| Code register Pi hook, command, tool hay session UI? | `packages/piagent-core/runtime/` |
| Code là policy decision hoặc scoring decision deterministic? | Core service module nhỏ, không dùng Pi API và không format UI |
| Code persist local runtime evidence? | State service có owner-only mode và bounded retention |
| Code integrate MCP? | `packages/piagent-core/mcp/` |
| Code resolve profile, pack hay lock? | `packages/piagent-core/capabilities/` |
| Code là CLI command? | `scripts/` chỉ parse argument và gọi package service |
| Code riêng cho một project? | Project profile/adapter, không đưa vào `piagent-core` |

Không tạo folder `utils` để gom code không rõ ownership. Module phải mang tên capability mà nó quản lý.

## Thứ tự tách file hiện tại

### P0: composition root

`packages/piagent-core/extensions/piagent-guard.ts` là architecture debt lớn nhất. Sau đợt tách lifecycle file còn 8.290 dòng và architecture gate chỉ cho phép file nhỏ dần.

Đã tách:

- `runtime/session/message-signals.ts`
- `runtime/session/runtime-state.ts`
- `runtime/session/system-prompt.ts`
- `runtime/session/usage.ts`
- `runtime/session/tool-result-compaction.ts`
- `runtime/input/chat-images.ts`
- `runtime/hooks/session-start-hook.ts`
- `runtime/hooks/session-hooks.ts`
- `runtime/hooks/input-hook.ts`
- `runtime/hooks/agent-start-hook.ts`
- `runtime/hooks/completion-hook.ts`
- `runtime/hooks/tool-call-hook.ts`
- `runtime/hooks/tool-result-hook.ts`
- `runtime/context/adaptive-planner.ts`
- `runtime/context/retrieval-route-policy.ts`
- `runtime/model/capabilities.ts`
- `runtime/model/model-route-types.ts`
- `runtime/model/model-route-policy.ts`
- `runtime/model/model-route-runtime.ts`
- `runtime/model/model-selection-provenance.ts`
- `runtime/tools/tool-groups.ts`
- `runtime/workflows/input-routing.ts`
- `runtime/workflows/task-intake.ts`
- `runtime/runtime-limits.ts`
- `extensions/task-journal.js`
- `extensions/task-runtime-audit.js`
- `extensions/repository-memory.js`
- `extensions/verification-intelligence.js`
- `extensions/execution-backend.js`

Những feature cần tách tiếp theo một khối trọn vẹn:

1. Chuyển phần policy decision body đang được wire qua `runtime/hooks/tool-call-hook.ts` vào core service nhỏ.
2. `runtime/tools/`: policy, task, context, memory, onboarding, profile, document và source tools.
3. `runtime/commands/`: workflow, session, permission, context, MCP, profile, onboarding và compatibility alias.
4. Tiếp tục đưa context, policy, onboarding, profile và source-cache call site về owning service; task audit và verifier selection đã đi qua focused service thay vì nằm trong composition root.

Mục tiêu: composition root dưới 500 dòng, chỉ giữ registration order và một shared runtime state object nhỏ.

### P1: policy engine

Tách `extensions/policy-core.js` theo decision boundary:

- `policy/shell/tokenize.js`
- `policy/shell/expansion.js`
- `policy/path/match.js`
- `policy/path/candidates.js`
- `policy/exec/evaluate.js`

Giữ một compatibility barrel cho đến khi toàn bộ internal import đã migrate. Differential shell test phải nằm sát parser/matcher boundary.

### P1: Context Engine

Tách `extensions/context-engine.js` thành:

- `context/index/store.js`
- `context/index/policy.js`
- `context/retrieval/search.js`
- `context/retrieval/pack.js`
- `context/telemetry.js`
- `context/test-impact.js`

Index store owner SQLite và secure deletion. Retrieval không tự load policy; nó nhận resolved exclusion policy bắt buộc từ caller.

### P2: capability resolver

Tách `capabilities/capability-core.js` thành manifest validation, dependency resolution, permission projection và lock integrity. Atomic file write thuộc infrastructure module, không thuộc resolver.

### P2: benchmark runner

Tách `scripts/benchmark-runner.mjs` thành CLI mỏng và package module cho suite materialization, surface execution, evidence collection, grading và report rendering. CLI không được tự tính một bản benchmark metric thứ hai.

### P2: docs và test dài

- Tách operator manual theo install, daily workflow, session/usage, MCP, recovery và reporting; stable path cũ trở thành index.
- Tách `piagent-guard-integration.test.mjs` theo từng runtime hook family, vẫn dùng chung harness helper.
- Mỗi source feature được tách phải có một test file tập trung.

## Rule cho runtime composition

- Registration function nhận dependency object rõ ràng, không import mutable state từ composition root.
- Shared session state có một typed owner và được truyền vào hook/tool/command registrar.
- Tool và command alias gọi cùng handler; alias không duplicate behavior.
- UI formatting nằm trong runtime adapter. Policy service trả về structured decision.
- Mọi file trong `packages/piagent-core/runtime/` phải có trong
  `capabilities/runtime-integrity.js`; capability lock phải pin toàn bộ runtime
  code thực thi trước khi release được phép pass.
- Mỗi filesystem write phải khai báo path, mode, retention và source of truth.
- Mỗi derived metric phải nêu input và có unit test tính tay một ví dụ.
- Thay đổi adaptive context phải ghi plan receipt, phase, lane, budget, model,
  thinking level và confidence threshold vào telemetry.
- Thay đổi task recovery phải giữ task contract là operational truth và task
  journal là audit/replay truth; không được để checkpoint derived thay thế ngầm
  một contract hợp lệ.
- Recovery ceiling là invariant xuyên task attempt. Classifier mới không được
  grant mutation; policy vẫn phải kiểm tra riêng source ownership, task scope và
  hook authorization. Handoff/receipt state chỉ lưu bounded reference, không lưu
  raw verifier log hay source.
- Thay đổi resume phải so actual current tree với exact-verifier evidence và
  fail closed khi identity, journal, trajectory, handoff hoặc symlink integrity
  lỗi. Byte của terminal Task Contract phải immutable.
- Thay đổi helper phải giữ pinned parent, one-writer invariant, strict
  RolePolicy/HelperRequest scope intersection, cross-process owned budget và
  digest-only usage receipt. Ở GA, `on` chỉ dispatch read-only role; automatic
  worker delegation vẫn disabled.
- Operator projection phải đọc persisted/observed truth, vẫn dùng được khi
  sidecar cũ bị thiếu, hash session identity và giữ timing/token/cost fact không
  có nguồn ở null. Thay đổi formatting phải giữ structured schema/version và
  ranh giới host-không-phải-sandbox rõ ràng.

## Checklist khi thay đổi

1. Đặt code đúng owning layer.
2. Thêm hoặc update cặp EN/VI nếu behavior là normative.
3. Chạy `npm run architecture:check` trước broad test.
4. Chạy focused test của feature vừa sửa.
5. Chạy `npm run verify` trước release.
6. Khi semantic thay đổi, update hai language file trong cùng commit.

## Definition of done cho architecture migration

- Composition root tối đa 500 dòng.
- `architecture/layers.json` không còn non-growth exception.
- Core policy module không import runtime hay CLI code.
- Mọi maintainer topic normative đều có cặp EN/VI.
- Full verification, package distribution, benchmark schema và published docs gate đều xanh.
