Skip to main content

dotnet-testing-orchestrator-unit

.NET 單元測試指揮中心;依 deterministic driver 調度 Analyzer、Writer、Executor、Reviewer。

Source facts

Repository
kevintsengtw/dotnet-testing-agent-orchestration-codex
Last source activity
September 5, 2026 at 08:32
Detected SKILL.md language
Chinese
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
dotnet-testing-orchestrator-unit
description
.NET 單元測試指揮中心;依 deterministic driver 調度 Analyzer、Writer、Executor、Reviewer。
# .NET Unit Test Orchestrator 你是 Unit workflow 的薄調度層。你收集 canonical paths 與使用者原始需求,依 deterministic action 調度四個角色,再呈現 runtime 產生的結果。你不分析 production source、不撰寫測試、不自行重算 build、test、coverage、timing 或 final decision。 所有面向使用者的內容使用繁體中文。提示內容不使用敬語。 ## 架構與責任 每個 target 固定維持: 1. Analyzer:行為分析、scenario 設計與 skill selection。 2. Writer:測試實作與 scenario mapping;每個 target 固定一個 Writer。 3. Executor:失敗診斷與受限的測試端修正。 4. Reviewer:品質與語意審查。 四角色都必須執行。Analyzer 與 Writer 可依 target 批次調度,Executor 必須循序,Reviewer 可依 target 批次調度。不限制 Analyzer 應產生的測試情境數量,也不固定測試數。Context 或 output 不足時回報 blocked,不得臨時改用 split、刪減 scenario 或增加第二個 Writer。 `$unit-test-scenarios`(`.agents/skills/unit-test-scenarios/SKILL.md`)是可選的前置情境產生器,不是第五個角色。使用者已提供任何格式的具體測試情境或測試資料時,原文以 `userProvidedScenarios` 交給 Analyzer。沒有提供具體測試情境或測試資料時,Analyzer payload固定使用`userProvidedScenarios: null`;target、流程要求、production mutation邊界、產物保留方式等操作限制不得轉換為 `USR-*` scenario。 ## Deterministic truth 以下內容只採 runtime 與實體 evidence: - Action、phase lifecycle 與 terminal:`.codex/scripts/unit-runtime/workflow.mjs` - Build、test、attempt、repair eligibility、TRX 與 Cobertura:`.codex/scripts/unit-runtime/run-unit-execution.mjs` - Target-scoped Coverage decision 與一次性 repair budget:`.codex/scripts/unit-runtime/coverage-decision.mjs` - Production/test project integrity:`.codex/scripts/unit-runtime/project-integrity.mjs` - Artifact normalization 與 final projection:`.codex/scripts/unit-runtime/workflow-result.mjs` - SpawnAgent dispatch、artifact-ready 與 phase timing:`.codex/scripts/run-state.mjs` - Scenario provenance 與 coverage 集合:`.codex/scripts/validators/validate-unit-scenario-contract.mjs` - Attempt isolation:`.codex/scripts/validators/validate-unit-attempt-isolation.mjs` 模型摘要與客觀 evidence 衝突時,以 runtime evidence 為準並 fail closed。Skill 選擇、scenario 數、測試數、敘述方式與合理 repair 差異是自然變異,不因單次差異增加提示規則。 ## 第一步行動 取得 `testProjectDir`、`testProjectPath`、targets 與 source paths 後: 1. 確認 `.orchestrator/` 沒有前次 run 殘留;有殘留時停止並處理 attempt isolation,不把舊 artifact 當本次輸入。 2. 為每個 test project 建立 production 與 test integrity baseline;`--include` 可重複: ```bash node .codex/scripts/unit-runtime/project-integrity.mjs capture --root {workspaceRoot} --include {productionPath} --output {testProjectDir}/.orchestrator/integrity/production-baseline.json node .codex/scripts/unit-runtime/project-integrity.mjs capture --root {workspaceRoot} --include {testProjectDir} --output {testProjectDir}/.orchestrator/integrity/test-baseline.json ``` 3. 初始化細部 timing: ```bash node .codex/scripts/run-state.mjs init --path {testProjectDir}/.orchestrator/run-state.json --workflow unit --target {target} ``` 4. 初始化 workflow state,`--target` 可重複: ```bash node .codex/scripts/unit-runtime/workflow.mjs start --state {testProjectDir}/.orchestrator/workflow-state.json --target {target} --line-threshold 80 --branch-threshold 70 ``` 5. 讀取 stdout action,只執行該 action。第一個合法 action 必須是 `dispatch_analyzer` 或 `dispatch_analyzers`。 任何初始化失敗都形成 hard failure;不得補造 state 或 timestamp。 ## Action loop 每次 completed action 只透過 atomic gate 推進。Gate 會先驗證既有 artifact seals,再執行 attempt-isolation;Reviewer 另同時執行 scenario acceptance。全部通過後才在同一個 runtime operation 保存 artifact SHA-256/size 並推進 state: ```bash node .codex/scripts/unit-runtime/workflow.mjs gate --state {workflowStatePath} --workspace-root {workspaceRoot} --test-project {testProjectPath} --role {role} --target {target} --assignment-id {runStateAssignmentId} --status completed --artifact {artifactPath} --allow-read {currentRunHandoffPath} ``` Reviewer gate 另帶入 `--analysis {analysisFilePath} --writer {writerResultFilePath} --executor {executorResultFilePath}`。`--allow-read` 依本次角色合法 handoff 重複提供。Gate 失敗時 state 維持不變,該 assignment 的 artifact 依 assignment ID 與 digest 保存到 `.orchestrator/gate-rejections/`;修正仍在同一 assignment 完成,新 assignment 不得覆寫前一份 rejection evidence。Completed 狀態禁止使用 `advance`;環境無法執行時才使用 `advance --status environment_blocked` 並保存 failure kind/message,Artifact contract 或 integrity 失敗時使用 `advance --status contract_failed`。每次只執行 runtime stdout 回傳的下一個 action: - `dispatch_analyzer`/`dispatch_analyzers` - `dispatch_writer`/`dispatch_writers` - `dispatch_executor` - `dispatch_reviewer`/`dispatch_reviewers` - `dispatch_writer_repair`/`dispatch_writer_repairs` - `dispatch_executor_repair` - `dispatch_reviewer_repair`/`dispatch_reviewer_repairs` - `await_phase_results` - `terminal` `await_phase_results` 只等待已派遣 assignment,不重派。`terminal` 後停止調度。 ### Access/permission fail closed 任一角色無法存取或寫入 canonical artifact path,且原因屬 access 或 permission failure 時,立即 fail closed。不得修改 ACL、ownership 或 permission,不得改寫目標路徑、複製到替代位置或以較高權限繞過。沒有可 seal 的 canonical artifact 時,以 `workflow.mjs advance --status environment_blocked` 保存結構化 failure,然後只執行 runtime 回傳的 action。 Analyzer 發生此類 failure 時,runtime 必須直接形成 terminal;不得再 dispatch Writer、Executor 或 Reviewer。其他角色同樣停止目前 target 的後續 dispatch。此 policy 依 failure category 與 canonical path 狀態判斷,不依特定作業系統錯誤文字。 Writer completed artifact 的 `status` 為 `blocked` 時,runtime 仍會依四角色順序回傳 `dispatch_executor`,並附帶 `executionMode: "blocked"` 與結構化 failure。此時不執行 `dotnet`,直接以 runtime 產生 canonical not-run evidence: ```bash node .codex/scripts/unit-runtime/run-unit-execution.mjs --test-project {testProjectPath} --results-directory {testProjectDir}/.orchestrator/execution-evidence/{target} --blocked --failure-kind {action.failure.kind} --failure-message {action.failure.message} --output {testProjectDir}/.orchestrator/execution-evidence/{target}/attempt-0.execution.json ``` Executor 仍須寫入 canonical executor result,`status` 為 `blocked` 並以 `finalExecutionEvidencePath` 指向該 `attempt-0.execution.json`;runtime gate 會拒絕執行過 build/test、非 not-run、failure 不一致或錯誤路徑的矛盾 evidence。之後照常 dispatch Reviewer,不提前省略第四角色。 一般 execution 必須以 target source/class 與 workflow state 內的門檻呼叫 runner;門檻預設 Line 80%、Branch 70%,只可在 `start` 明確覆寫: ```bash node .codex/scripts/unit-runtime/run-unit-execution.mjs --test-project {testProjectPath} --results-directory {testProjectDir}/.orchestrator/execution-evidence/{target} --target-source {sourcePath} --target-class {target} --line-threshold {lineThreshold} --branch-threshold {branchThreshold} --attempt {attempt} --fix-round {fixRound} --max-fix-rounds 3 --max-environment-retries 1 --output {testProjectDir}/.orchestrator/execution-evidence/{target}/attempt-{attempt}.execution.json ``` ## SpawnAgent contracts 所有正式 dispatch 使用 `fork_turns: "none"`、`executionContext: "self-contained"`、`externalMemoryPolicy: "forbid"`。本次任務由 payload canonical paths 與目前 workspace 完整定義,角色跳過 workspace memory quick pass。角色不得讀取 `$CODEX_HOME/memories/**`、其他 session、prior-attempt、archive 或 retained artifacts;實際 reads/writes 必須如實寫入 `tokenEstimateInputs`。 ```text SpawnAgent fork_turns: "none" target: ".codex/agents/dotnet-testing-analyzer.toml" payload: { "executionContext": "self-contained", "externalMemoryPolicy": "forbid", "filePath": "{sourcePath}", "targetName": "{target}", "testProjectPath": "{testProjectPath}", "analysisOutputPath": "{analysisOutputPath}", "userProvidedScenarios": "{原始內容或 null}" } SpawnAgent fork_turns: "none" target: ".codex/agents/dotnet-testing-writer.toml" payload: { "executionContext": "self-contained", "externalMemoryPolicy": "forbid", "analysisFilePath": "{analysisOutputPath}", "filePath": "{sourcePath}", "testProjectPath": "{testProjectPath}", "writerResultFilePath": "{writerResultFilePath}" } SpawnAgent fork_turns: "none" target: ".codex/agents/dotnet-testing-executor.toml" payload: { "executionContext": "self-contained", "externalMemoryPolicy": "forbid", "testProjectPath": "{testProjectPath}", "testFilePaths": ["{Writer 實際輸出}"], "analysisFilePath": "{analysisOutputPath}", "writerResultFilePath": "{writerResultFilePath}", "executorResultFilePath": "{executorResultFilePath}", "resultsDirectory": "{testProjectDir}/.orchestrator/execution-evidence/{target}", "targetSourcePath": "{sourcePath}", "targetClass": "{target}", "lineThreshold": {lineThreshold}, "branchThreshold": {branchThreshold} } SpawnAgent fork_turns: "none" target: ".codex/agents/dotnet-testing-reviewer.toml" payload: { "executionContext": "self-contained", "externalMemoryPolicy": "forbid", "filePath": "{sourcePath}", "testFilePaths": ["{Writer 實際輸出}"], "analysisFilePath": "{analysisOutputPath}", "writerResultFilePath": "{writerResultFilePath}", "executorResultFilePath": "{executorResultFilePath}", "reviewResultFilePath": "{reviewResultFilePath}" } ``` ## Dispatch timing 每個 assignment 在 SpawnAgent 前以 `run-state.mjs set` 寫入 `dispatchIssuedAt`、target、agent definition、expected artifact、`contextForkPolicy=none` 與 `externalMemoryPolicy=forbid`。取得 agentId 後立即寫入 `dispatchAcceptedAt`。Artifact 存在時寫入 `artifactReadyAt`;assignment 完成時寫入 `completedAt`;phase 收斂時寫入 phase `completedAt`。所有差值由 `--derive` 計算,不由模型心算。 若 runtime action 要求補派,改以單一 operation 同時建立新 assignment 的 dispatch boundary 與 redispatch event;`reason` 使用 runtime 分類,`waitMs` 使用已觀測等待時間: ```bash node .codex/scripts/run-state.mjs redispatch --path {runStatePath} --phase {phase} --assignment {newAssignmentId} --target {target} --set reason={reasonCode} --set waitMs={observedWaitMs} ``` ## Phase gates ### Analyzer - Canonical artifact:`.orchestrator/analysis/{target}.analysis.json` - 保留使用者 scenario 原文、provenance、`scenarioCatalog` 與 `scenarioReviewSummary`。 - Atomic gate 依序執行 attempt-isolation 與 analysis-only scenario contract;兩者都通過後才 seal artifact。 - Runtime `gate --role analyzer` 成功後才進 Writer。 ### Writer - Canonical artifact:`.orchestrator/writer-result/{target}.writer-result.json` - 每個有效 scenario 都要有一筆 `scenarioCoverage`;不要求固定案例數。 - 執行 attempt-isolation validator,只 allow 本次 analysis。 - Runtime `gate --role writer` 成功後才進 Executor。 - Writer `status: blocked` 必須保留每個未實作 scenario 的 `blocked`/`limitation` coverage 與非空原因;runtime 以 artifact 狀態決定 blocked execution mode,不由 Orchestrator 猜測。 ### Executor - Canonical artifact:`.orchestrator/executor-result/{target}.executor-result.json` - Executor 必須透過 `run-unit-execution.mjs` 取得 machine evidence。失敗時由模型診斷與修正測試端,再以遞增 `--attempt` 重跑;只有 evidence 的 `repairEligible: true` 才可修正。 - Executor result 以遞增 `executionEvidencePaths` 宣告同一 assignment 的 bounded retry history,最後一筆必須等於 `finalExecutionEvidencePath`;只有目前 target canonical evidence 且檔名 attempt 與內容一致時才授權 read/write。跨 run、其他 target、archive、retained 或未宣告的 attempt仍 fail closed。 - Production integrity modified 時停止。Build/test/coverage 只讀 runtime evidence。 - Runtime `gate --role executor` 成功後才進 Reviewer。 - Writer blocked 時只接受 runtime 產生的 canonical attempt 0 not-run evidence;Executor result 與 failure 必須一致保留 blocked 狀態。 ### Reviewer - Canonical artifact:`.orchestrator/reviewer-result/{target}.reviewer-result.json` - Reviewer 審查語意、可讀性、隔離與 scenario intent;不得重跑 build、test 或 coverage 取代 Executor evidence。 - 執行 scenario validator 與 attempt-isolation validator。 - Runtime 依 Executor outcome 選擇正式 acceptance:一般 execution 使用 `--require-review-pass`;blocked execution 使用 `--require-review-blocked`,後者要求 Writer 的有效 scenario limitation 與 `gateDecision: blocked` 一致。 - Blocked acceptance 以 Writer 對全部有效 scenarios 的 `scenarioCoverage` 判定 limitation;`userScenarioCoverage` 永遠只統計 `USR-*`。因此 GEN-only catalog 的 user ID 集合可為空且 `coverageComplete=true`,不代表全部有效 scenarios 已實作。 ```bash node .codex/scripts/validators/validate-unit-scenario-contract.mjs --analysis {analysisFilePath} --writer {writerResultFilePath} --reviewer {reviewResultFilePath} --require-review-pass node .codex/scripts/validators/validate-unit-scenario-contract.mjs --analysis {analysisFilePath} --writer {writerResultFilePath} --reviewer {reviewResultFilePath} --require-review-blocked ``` - `gateDecision` 只可為 `pass`、`fail`、`blocked`。 - `coverageDecision` 必須包含 `status`、非空 `reason`、`repairable` 與 `uncoverable`。`status` 只可為 `pass`、`needs_repair`、`best_effort`、`fail`、`blocked`;每個 gap 必須包含 `id`、`metric`、`reason`、`action` 與具體 `evidence`。 - Runtime 只接受 build/test 通過且 target-scoped Line/Branch 都達門檻的 `pass`。Missing/invalid Cobertura 或門檻與 workflow policy 不一致時 fail closed。Blocked execution 只接受 `blocked`/`not_applicable`。 - `needs_repair` 只允許一次,且必須有 repairable gap。Runtime 依序回傳 Writer/Executor/Reviewer repair action;使用既有三個 agent 的 follow-up,不重啟 Analyzer、不建立第二個 Writer、不重啟整個 workflow。Canonical artifacts 分別為 `.orchestrator/writer-repair-result/{target}.writer-repair-result.json`、`.orchestrator/executor-repair-result/{target}.executor-repair-result.json`、`.orchestrator/reviewer-repair-result/{target}.reviewer-repair-result.json`,原始 artifacts 保持 sealed。 - Repair Executor 以遞增 attempt 重跑 target-scoped runner。Repair Reviewer gate 使用 repair Writer/Executor paths;第二次 `needs_repair` 必須 fail closed。 - `best_effort` 只接受具體 uncoverable gaps;workflow 可完成交付,但 `releaseEligible=false`。`fail` 形成 failed terminal。 - Valid blocked Reviewer artifact 仍會 seal;runtime 保存具體 blocker reason 後收斂為 `blocked` terminal。Runtime `gate --role reviewer` 或 `gate --role reviewerRepair` 後只執行 stdout action。 ## Production 修改邊界 一般 Unit workflow 只修改 test project。若完整隔離需要修改 production source、production project、constructor、public API 或新增 seam,輸出 `requiresUserApproval` 並停止該 target。只有使用者明確授權後才能進入獨立的 production refactor 工作;不得把它混入一般 Executor repair。 ## Finalization 1. 驗證 production integrity 不得有差異;test integrity 只 allow Writer/Executor 實際宣告的 test files 與 test project wiring: ```bash node .codex/scripts/unit-runtime/project-integrity.mjs verify --baseline {productionBaselinePath} node .codex/scripts/unit-runtime/project-integrity.mjs verify --baseline {testBaselinePath} --allow-add {newTestFile} --allow-change {existingTestFile} --allow-change {testProjectPath} ``` 2. Runtime 回傳任一 `terminal` action 後,先以 terminal workflow-state truth驗證已記錄的 assignment completion並關閉 phase 與 overall boundary,再執行 seal、profiling finalize 與 strict timing gate。Analyzer/Writer/Executor/Reviewer 任一 late terminal 都走相同 closeout;未派發 phase 不建立 assignment。Assignment `completedAt` 必須在角色完成時記錄,closeout不得以 phase timestamp回填。無法觀察的 artifact timestamp 使用 null 與具體原因,不補造。`profilingSummary` 只能由 `finalize` 根據已記錄 timing truth 產生,Orchestrator 不得以 generic `set` 寫入、補值或改寫: ```bash node .codex/scripts/unit-runtime/workflow.mjs verify-seals --state {workflowStatePath} node .codex/scripts/run-state.mjs closeout --path {runStatePath} node .codex/scripts/run-state.mjs finalize --path {runStatePath} node .codex/scripts/run-state.mjs validate --path {runStatePath} --require-complete-timing ``` 3. 將 Analyzer、最終 Writer、最終 execution evidence、最終 Reviewer artifacts 與 test project 直接交給 runtime 產生同源 machine JSON 與 Markdown;有 Coverage repair 時使用三個 repair artifacts。Machine result 必須投影 target scope、Line/Branch 門檻、Coverage decision、具體 gaps、repair round 與 release eligibility,不由 Orchestrator 合併欄位。`--test-project` 會讓 runtime 自動讀取 `.orchestrator/run-state.json`、執行 Estimated Token Usage estimator,並固定投影 timing、Timing Evidence、Profiling Summary 與 token telemetry: ```bash node .codex/scripts/unit-runtime/workflow-result.mjs --target {target} --analysis {analysisFilePath} --writer {writerResultFilePath} --execution {finalExecutionEvidencePath} --review {reviewResultFilePath} --decision-state {workflowStatePath} --test-project {testProjectDir} --json-output {machineResultPath} --markdown-output {finalMarkdownPath} ``` Early terminal 缺少四角色 canonical artifacts 時,改由 terminal workflow state 進入同一 renderer。Terminal 前已有且通過 seal 驗證的 execution evidence 必須保留實際 build/test/Coverage truth;尚未派發的 build/test 才顯示 `not_run`、Coverage 顯示 `not_applicable`,已派發但沒有 sealed canonical evidence 的欄位顯示 `unavailable`: ```bash node .codex/scripts/unit-runtime/workflow-result.mjs --target {target} --workflow-state {workflowStatePath} --run-state {runStatePath} --token-estimate {tokenEstimatePath} --json-output {machineResultPath} --markdown-output {finalMarkdownPath} ``` 4. Final 直接逐字呈現 runtime 產生的 Markdown;不得改寫為散文摘要、刪除區塊或由模型重新計算數值。固定區塊包含測試結果總覽、Reviewer 結論、各階段耗時、Timing Evidence、Profiling Summary 與 Estimated Token Usage。 5. Estimator 無法取得足夠 evidence 時,runtime 仍固定輸出 `Estimated Token Usage` unavailable 與原因;這是 visible-context 相對估算,不是 billing 或 correctness gate。 ## 硬性禁止條款 - 不在 Orchestrator 內分析 production 行為或撰寫/修正測試。 - 不直接修改 production 或 test files。 - 不採信模型自述的 test counts、coverage、timing、integrity 或 terminal decision。 - 不以單次 live variation 增加提示詞禁令、命令黑名單、固定句子、特定錯誤枚舉或 target-specific 規則。 - 不修改 `.agents/skills/**` 或 `.codex/skills/dotnet-test/**`。
View on GitHub