diff --git a/.gitnexus/lbug b/.gitnexus/lbug
index 40e91616..0629677a 100644
Binary files a/.gitnexus/lbug and b/.gitnexus/lbug differ
diff --git a/.gitnexus/meta.json b/.gitnexus/meta.json
index e68f9865..e4a9d335 100644
--- a/.gitnexus/meta.json
+++ b/.gitnexus/meta.json
@@ -1,13 +1,13 @@
{
- "repoPath": "/Users/a86198/Desktop/Wiki/AI/3-Application/FrontAgent-app",
- "lastCommit": "487f612790679bd467d0987667bb9ee697658222",
- "indexedAt": "2026-06-12T05:13:12.706Z",
- "remoteUrl": "https://github.com/FrontAgent/FrontAgent",
+ "repoPath": "/Users/a86198/Desktop/FrontAgent",
+ "lastCommit": "51fd4bbaf69ea926cd670f6708dbbbc6b5b52327",
+ "indexedAt": "2026-07-12T08:26:27.526Z",
+ "remoteUrl": "https://github.com/ceilf6/FrontAgent",
"stats": {
- "files": 473,
- "nodes": 5084,
- "edges": 12429,
- "communities": 377,
+ "files": 566,
+ "nodes": 5716,
+ "edges": 13719,
+ "communities": 469,
"processes": 300,
"embeddings": 0
},
@@ -32,13 +32,15 @@
"turbo.json": "0b46c401b4149e562e9408c92f023f0c75c1427af4ceff629e9b215c9d4e3d5a",
"tsconfig.json": "6c2753eea1c2f2be8d7fa1f4702cc4ccc279bbc314440c2dd38f708208ef9b01",
"pnpm-workspace.yaml": "37c662a036df6d96bccc32a64ba6535de9f6c87e3057f69d32caa5f25d306a91",
- "package.json": "4baec0d5c09c701b6b6b82a1a47e342888900fa246e56c50bfd531ce8981aee3",
+ "package.json": "464af1784c1a5566f2e4158fd0f267f4089eaa1de6cbb3a9ec0393c82163632a",
"build.mjs": "d0a0528a37280d0f969e03452e92b59f877cbdb9825b570568c5e4d415c0f57b",
"biome.json": "8c12a7577f38f158aac3b53136b63e20f85a0ad4690a7c38a9ba8c123bf37de9",
- "README.md": "52a3a7cf58aed71415516c354d597964ee5b238ab488d2995eadc5442eb68b64",
+ "README.md": "eead4fb3635bb87bb01eea3b10c24f4a60af479c7e209329de56a75177fdf775",
"CLAUDE.md": "03ba21d21c48a8226d5d3660b69ca02f5d788b4ff9162c28d0388380dec0d8ad",
"AGENTS.md": "03ba21d21c48a8226d5d3660b69ca02f5d788b4ff9162c28d0388380dec0d8ad",
"scripts/sync-vscode-version.mjs": "fb86db0dcbf95a72963748dcb09e2b36aeda5a698c62668a8b96e9ce1c55c3a3",
+ "benchmarks/frontagent-flow-benchmark.mjs": "916f10ec40ff6445a83862e534147609cc801d3b6d4222301d9cc0487df4f730",
+ "benchmarks/frontagent-agent-flow-benchmark.mjs": "81874bfa525b61c2fd3476630bff42238c666ca138d697fce840d400ba8887b2",
"docs/极其规范的审计型.md": "80185dda160d2c081e3c33112d9b9a5c1949337388871b951993951ae8aaf412",
"docs/workflow.md": "3a55a54fb8dc432402d920c7eeddfc3cfd0b720f733a3fb3a7ceb8670d4cd780",
"docs/oss-harness-engineering-workflow.md": "a31368c6faf91f657e15bb280e2f44e97e45510697ca5b903b4cb1b1175e5159",
@@ -50,14 +52,12 @@
"docs/design.md": "90e5ed4f77914d01b65a05b2bf3fda6c191725b35a931142d69813c0cf643b3d",
"docs/architecture.md": "965fd96466620145251ee668495e4c9b150b6584faea2ff077e59520c52a5b45",
"docs/TWO_STAGE_ARCHITECTURE.md": "b3c364f1e9f7bc403c54ecc1dd4575d3cfb4349fa68d750bf61cda220c8495e5",
- "docs/README-CN.md": "1d4314f6b32c5221d22ff309d10c64369f7c7684a6b09bab63573ccc45ca589b",
+ "docs/README-CN.md": "f691a15ad2fcf91f231d0cbaf4ee023944711ca7559e97e3bb2d1e41b4e61bfa",
"docs/QUICKSTART.md": "c2ecca75ef0968084fa2c54cb2b92e12dc90147233837c074c0c06f5fa13b381",
"docs/FrontAgent-Skill-Structure-Proposal-CN.md": "1be549d2ec996f095a1cb0cda346dcb3a7b3aac8b9db1415918bba9b84d766d0",
"docs/FrontAgent-Skill-Patterns-Analysis-CN.md": "ccc8267d64a1b2e04ee60e9a368a53c23624938db04cd811ad824a50f94779ba",
"docs/FrontAgent-Introduction.md": "40eb84caa868d334463c5e32e831b502457f4aefc810376803a7e41bd8d4a49b",
"docs/CHANGELOG-CN.md": "916f6d591bf787c93e5ba448233905a68d9c545eb70fc1d082f644beb7643392",
- "benchmarks/frontagent-flow-benchmark.mjs": "916f10ec40ff6445a83862e534147609cc801d3b6d4222301d9cc0487df4f730",
- "benchmarks/frontagent-agent-flow-benchmark.mjs": "81874bfa525b61c2fd3476630bff42238c666ca138d697fce840d400ba8887b2",
"skills/skill-lifecycle/SKILL.md": "9cd76f1fa8230f7b99b65f76e8d8373b18b3201dc1077489362aa6d18ac37957",
"skills/skill-lifecycle/ADAPTATION.md": "d11e68afa39643bc872a22c6c18d46c55d9715acf5be94446762ae821be1fd6b",
"skills/requirement-interviewer/SKILL.md": "424a38059feedc835057babefe074a93ae0df5ffe1d42fa2ba9772f25b29ba5c",
@@ -67,13 +67,23 @@
"scripts/workflows/install-hooks.mjs": "0aba80b136682117476fbf9a3e454cdd56af6de541fa70be0138dd438320c8ff",
"scripts/workflows/contract-rules.mjs": "4c094cd0eb820d23b7ffc07503566d0957d3caf02c98f86399e48499b8bb813a",
"scripts/workflows/contract-check.mjs": "590d05b63a6817223e1428596d543ea6df89464076a118c4c1578e21ec1101d4",
- "scripts/tests/workflow-rules.test.mjs": "e83514d42c202ad9711c767cafaf944c96f47f4a263e9f60f0806d85ff4398a4",
+ "scripts/tests/workflow-rules.test.mjs": "630784a69cdae2cc837a8165b7c89932e676e53703fa6633442dbe4e47e219c9",
+ "models/frontagent-planner/train_mlx.py": "b9fe515dadde8449b711b561fb0ac5c32bec6762829128f83af7878a5341f217",
+ "models/frontagent-planner/train.py": "31dd7aac03cddc0347d9ed9b696fda8c5e459da8b4d8f5777f6642269dbf5812",
+ "models/frontagent-planner/publish.py": "9f430e5a2ae1db40b9130340f0fc881fe85b9f038c38e1e1a8c428d3e03327cf",
+ "models/frontagent-planner/plan.md": "e4daff3197bf0f63f396d616dab3166db55a5ab0c2d16b70387be4fbadce0945",
+ "models/frontagent-planner/eval.py": "faebd2f049efa3f4f49756747dfd7a11b183637b6152f6d52064b5208d5012e6",
+ "models/frontagent-planner/colab_train.ipynb": "a59956575aa9d1b84939fcf09024269451811109472be31968aa153b87be51ac",
+ "models/frontagent-planner/README.md": "7742f3c6b6b556ba69095f128b2ef27e5ef959aae8a095ccb6fbe4aa9402cb06",
"packages/shared/tsconfig.json": "e4ed044d99005d1d36c726849468ff721d4fd6ed12967cc420470a4d9f690004",
"packages/shared/package.json": "c769ce47b0d355923ef1ec07102efbac795d0cd818918f3234f9826bc239b505",
"packages/sdd/tsconfig.json": "e4ed044d99005d1d36c726849468ff721d4fd6ed12967cc420470a4d9f690004",
"packages/sdd/package.json": "16a5bead536e2eec66cffc18ada2fc8cee9e55f1eb4bfef5194dabde637e77b5",
"packages/runtime-node/tsconfig.json": "069c50abf7c771629212bdd8057211886843d3d0c95beb5bad0c061990e9634b",
- "packages/runtime-node/package.json": "e17e892b8b6e0c20e7d752f5184b870817274bbbfbc47bcf6122dc0d1ec29ce0",
+ "packages/runtime-node/package.json": "85c580bb6d7fac07e0e5d6d29a9926fa9fecfd9d09ae6edba8274a3471c96663",
+ "packages/mcp-web-fetch/vitest.config.ts": "cf0b3263b2ded3747c8cd6139fb005c1ec49fc894f3f983c4e2e4dd5e004e660",
+ "packages/mcp-web-fetch/tsconfig.json": "8cec1d1a079b2b5c4f113fa566fb30800a65a530b920f0375f076a9dd1565402",
+ "packages/mcp-web-fetch/package.json": "a3a15aa9c4849689e5417753e53beb10c1cad00f6d708b77b7738623a9aa82f0",
"packages/mcp-web/tsconfig.json": "5a925cf30a676237351af85a2da9e65440839ade260be6d7a1945843af1fef63",
"packages/mcp-web/package.json": "dc0ab5559a649c895d062bcf681eadf066b5db0108c6b156b5034a216db80c62",
"packages/mcp-shell/tsconfig.json": "658b1f1615d30e66c1cb846e0dc7b6975b162d534ee0597e70ceb165dfff17a9",
@@ -84,18 +94,19 @@
"packages/mcp-filesense/tsconfig.json": "8cec1d1a079b2b5c4f113fa566fb30800a65a530b920f0375f076a9dd1565402",
"packages/mcp-filesense/package.json": "7f8ee91b670b5efd8da6a2ae6086292f1a072eaded9fa444b71b7b9e55ad532a",
"packages/mcp-file/tsconfig.json": "658b1f1615d30e66c1cb846e0dc7b6975b162d534ee0597e70ceb165dfff17a9",
- "packages/mcp-file/package.json": "81c0388a6786f74e4f1e215b6dc30f3f4f567c01ebaf3580817ad3ecc7442304",
+ "packages/mcp-file/package.json": "b02da70d84a45be3145b1c720a23f6dbdcbfa7203b02f6636c728350136665d7",
"packages/hallucination-guard/tsconfig.json": "e4ed044d99005d1d36c726849468ff721d4fd6ed12967cc420470a4d9f690004",
"packages/hallucination-guard/package.json": "1a4f3a9597a8e28b5128a9a9fa27ac076d4537bf1b1ff3012e7e2f81c0e051f1",
"packages/core/tsconfig.json": "658b1f1615d30e66c1cb846e0dc7b6975b162d534ee0597e70ceb165dfff17a9",
- "packages/core/package.json": "def3a5d9305c6049ae5658b471fa03672e8f7332bc12929d864e148bbab1c504",
- "models/frontagent-planner/train_mlx.py": "b9fe515dadde8449b711b561fb0ac5c32bec6762829128f83af7878a5341f217",
- "models/frontagent-planner/train.py": "31dd7aac03cddc0347d9ed9b696fda8c5e459da8b4d8f5777f6642269dbf5812",
- "models/frontagent-planner/publish.py": "9f430e5a2ae1db40b9130340f0fc881fe85b9f038c38e1e1a8c428d3e03327cf",
- "models/frontagent-planner/plan.md": "e4daff3197bf0f63f396d616dab3166db55a5ab0c2d16b70387be4fbadce0945",
- "models/frontagent-planner/eval.py": "faebd2f049efa3f4f49756747dfd7a11b183637b6152f6d52064b5208d5012e6",
- "models/frontagent-planner/colab_train.ipynb": "a59956575aa9d1b84939fcf09024269451811109472be31968aa153b87be51ac",
- "models/frontagent-planner/README.md": "7742f3c6b6b556ba69095f128b2ef27e5ef959aae8a095ccb6fbe4aa9402cb06",
+ "packages/core/package.json": "fd42f86bb485c2a8b201237f2c8eb26edb67cbee8d769dd6de6b4982431ca86d",
+ "benchmarks/results/full.jsonl": "5f559a51159f5e06406c3320c6e90699012f212e5dd75bf8ef467dd5e169565c",
+ "benchmarks/results/ablation.jsonl": "c1d650a79f0241d8d01b99b538f3bdfa254e5c95518f45624ba9ac88a1accd84",
+ "benchmarks/results/2026-07-12-sdd-ablation.md": "140b5a71e8adc25ea55fcdac97df945c34e7dce64ef1dca832ebd82dd7a50ad1",
+ "benchmarks/eval/tasks.json": "debb0756e46464a343004c8e462931b7e21c6184dfd42261253660bf7ccb7b58",
+ "benchmarks/eval/run-eval.mjs": "f5e1ba3fe2dc62ad82a32b57e2f522bf2a3b8f66289f8dc9b053fbbfac715354",
+ "benchmarks/eval/report.mjs": "f86887d8d3e593bdaef69320732e232b878642c92809de79585453ea4fa6cdc8",
+ "benchmarks/eval/claude-cli-backend.mjs": "d5ddc7e37a5588ad19e07094818851221596c58099ed725f3d8a9ce0668da9a7",
+ "benchmarks/eval/checks.mjs": "b91a6b91072a6de582fb7f9a53ee16ca5ec46f903647eb08778d5f9f17378484",
"docs/releases/v2.1.1.md": "d5655a64fe45287c5c7d53a12d938cbef6d7f4a421717afe7208e51c9c90969b",
"docs/releases/v2.1.0.md": "0ee3a55c007dc6f0013d51f5f5ebe055131ab66c904c48a33e04ad43d1b2a674",
"docs/releases/v1.0.1.md": "9fe4ecd85ac40e5eabcb1ad85d80d0f29206f902eba5fffd32c835d31f2b69dd",
@@ -104,6 +115,13 @@
"apps/vscode/package.json": "a3f4cb18ccfa3c2c616cb388b90169aca55a49ea20a07665285ac12c954c671b",
"apps/vscode/build.mjs": "b5ec637148141150dce57c3873b93c81dcbebcfba4492dca79b9b1f130198285",
"apps/vscode/README.md": "0f23c00c7fe764be2a634cb65919311bfb1c7d8eec0174afc61e6aa708942376",
+ "apps/desktop/vite.config.ts": "e00df58cc72667d847b73a65502addc92188692789d0cd9ca0c2d2ea21b83b2e",
+ "apps/desktop/tsconfig.json": "c7c055335c3bc71b0ab8b792b210a4773b07b7672d50be0338c3639d1b78ebc6",
+ "apps/desktop/package.json": "5350eb7ad979b9abfd061442f150f10199b4b33569eb03d6872b30680e134648",
+ "apps/desktop/index.html": "ba8721f782879628852bde1c757346af81fe7b875ef612b1b12517dda1d499ba",
+ "apps/desktop/electron.build.mjs": "fcbc16da735fd10599b891aecd4c4d74b803532c61e06509f2dc39d312cdc1b0",
+ "apps/desktop/electron-builder.yml": "26dccd84550211248330a932c37ae43ae08f2c429cc4346ecb97f5b361c9549a",
+ "apps/desktop/README.md": "14e8a75a695c049763a7a351a0e4a21d8f069f44fd798d361767737da588bc98",
"apps/cli/tsconfig.json": "0953a70e0a34454b7b2fb91379ec781fee970b356df4fcf10c46c283ae12df44",
"apps/cli/package.json": "580bd1869f4ef8ee395777abb42e5f74f2904a5d371ed9bde9d61655c823d976",
"skills/skill-lifecycle/references/workflow.md": "9bbfb6603ebdb9e8a0ee07df56d2d3ec98145533b40736faa97419694224c414",
@@ -113,15 +131,29 @@
"skills/requirement-interviewer/references/gating-rules.md": "9cd78087187e516b332356e8efe57e57f5a6fd83dafe826aec07712f53e80ae9",
"skills/requirement-interviewer/references/answer-completeness.md": "dc9bdae3e5b2152d812a33e5afa32c3ec8f4eaef00438b7149d93c9470defe8a",
"skills/requirement-interviewer/agents/openai.yaml": "e2c34847985eca7237dfb05c775b838057847dfd82f24eae4292ddd62794fbd1",
+ "skills/frontend-reviewer/agents/openai.yaml": "7d5402e7b2bb02f6516d6cb6b6716873ac4531bd89253b419158af1dfe5c0a9c",
"skills/frontend-reviewer/references/severity-rubric.md": "ba20153f6c37c0c78934247a9f78a27f2ee93ef24afe458462a63a732666c737",
"skills/frontend-reviewer/references/review-checklist.md": "07336b379eba82caf3ccbc87e0f6902a0fe056c806e0c64c052824a82603fcbe",
"skills/frontend-reviewer/references/frontend-quality-rules.md": "c847613b52fa1ad897fef2fcae3b7839a6b61c590f4d476d332afabecad4bebc",
- "skills/frontend-reviewer/agents/openai.yaml": "7d5402e7b2bb02f6516d6cb6b6716873ac4531bd89253b419158af1dfe5c0a9c",
"skills/frontend-design/references/integration-guardrails.md": "220fe5770347cef846d35161f8984c121d6954ab62649413c8694e763cca120a",
"skills/frontend-design/references/design-direction.md": "317cea721742b1047dbc994c0fe2407aef3ac3dcf5671d8afae345cf0c26057f",
"skills/frontend-design/references/delivery-checks.md": "6b2e604844693e5ae47a53c529bc7b3e9193a347985ec8148cfd99314ae8a9c8",
"skills/frontend-design/references/aesthetics-guidelines.md": "4d9adf4fc0d2f0ed8fc56a3d42647040b691233008a9ef99269ddb2ee61cbb34",
"skills/frontend-design/agents/openai.yaml": "00e5faccdd684676a87b3da9ad8e17760f43c929d66c097fcdfe18d6668fbe53",
+ "models/frontagent-planner/test/05-10.py": "7641412379b14a6118fa9692d85ef0d01818d6fc31beb5ca77d0744d73e8047a",
+ "models/frontagent-planner/prompts/schema.json": "4d2734ebc225963ff770dc1cd8e255bbb94c2c340e539a5d33aba03c64486689",
+ "models/frontagent-planner/prompts/planner-prompt.md": "2059bc8238f85ca74c2af0ed305fd0289f59b1ce0a69cfebbc4278043d4204ca",
+ "models/frontagent-planner/prompts/error-recovery-prompt.md": "a7d547bb87277a0aa4af404960449eb4888d7d22b57ff7b597b0f527cbbfac98",
+ "models/frontagent-planner/hf-release-14b/adapter_config.json": "538e2560e452ecfddb184b51c03e6a9745cd79a10ab210c4233070d6962232cb",
+ "models/frontagent-planner/hf-release-14b/README.md": "34effd563d8f79ad356883e877c779b25d665e9c0da7d2544c6746388eb5d178",
+ "models/frontagent-planner/hf-release-14b/EVAL_RESULTS.md": "9795f9df99cb5aa51a2bcb1d3174078cecdc661093660190ccf5ff4d95bd7b13",
+ "models/frontagent-planner/hf-release/tokenizer_config.json": "f38df2b424046acfd6bca1a712900bffa2a8a5e1690d10b1566da92eb2dc0bc3",
+ "models/frontagent-planner/hf-release/chat_template.jinja": "3e3e4ccd01b95ae100e861475e34dd42d044d15858f876bb73fe2934fe1603db",
+ "models/frontagent-planner/hf-release/adapter_config.json": "52098a437e9746f43e18e54a7aaa610e3f5953640937fc9d9abffd9fb46fca4b",
+ "models/frontagent-planner/hf-release/README.md": "5d23189b40ee100941e0ab2adf37fc81effe8a73ebf18d7d3bf4d91cdfabc941",
+ "models/frontagent-planner/hf-release/EVAL_RESULTS.md": "e05d09d123972ef6da8aa96e6af2ed39f8aa79ef7c27c792e5c6931d58c7d957",
+ "models/frontagent-planner/data/generate_data.py": "e38c6d8b8081200dc93e3ca1efdb728cbd872c25aef1efbadc82b587f46a25dc",
+ "models/frontagent-planner/data/eval_v2.json": "d1a0d6d1ce8dfea26e3fca620fe784fa4948916804c74f5dde5c70e738e373ae",
"packages/shared/src/utils.ts": "f0b6d5a6a8a05199e2918f450f088978eb8e5d8146230f3da6c1a8de5e4ec8c8",
"packages/shared/src/utils.test.ts": "d021afcc5e0fb52ada2e65889cb29473818562dc40417f4e22fb2a9e92fb474a",
"packages/shared/src/logger.ts": "dd6dcdace53ab520ff36622a9d380f5ad4eec3146e5dd9f7306e72cd99b52ed3",
@@ -141,17 +173,31 @@
"packages/runtime-node/src/sdd.ts": "3ca889e898be3892b8378964fb89f1dbe3c115e59b82779e832279516eb61519",
"packages/runtime-node/src/sampling-llm.ts": "6f944584929891a01ad35b496b355af12beb8426ca3bf59fa57310003901550e",
"packages/runtime-node/src/sampling-llm.test.ts": "e7f2e157d27c86a538e2742f8a719b9e1c7bddcda3fdc010323497fc64cc41fd",
- "packages/runtime-node/src/run.ts": "3d2804e374e4a72537d2242df8104ad052f18e2af13aefe487f5cc631293a3bc",
+ "packages/runtime-node/src/run.ts": "0ab32d15971fbe57bfc7762238d997c5bffa60cc4b8ff3b9249f6f3cc12a3df2",
+ "packages/runtime-node/src/run.test.ts": "1b991e2476bde4a084f1aab388182cc2f3889f6e3fc92d2a71fac8fde6b38610",
"packages/runtime-node/src/run-logger.ts": "988a2193777b1196f3b10e05fa33ef729fea03efa210e322ce4b21dca237631e",
"packages/runtime-node/src/run-logger.test.ts": "6507657dccf2d543934bbc8870922dc1c12795b83ede436a15cd16f9f4016280",
"packages/runtime-node/src/mcp-server.ts": "4b8b09687546df2689f31c75d1d4a46507ad7dce85d9baab340bc1e6f1c7a720",
"packages/runtime-node/src/mcp-server.test.ts": "a893b49b3d12d1171936b6dc16b09ac33163d9e5321f3cd801c90c45f0e52e41",
- "packages/runtime-node/src/mcp-clients.ts": "9089cb23d21ebda6c1b8e3cb306cba096f3f67a9a0a968fdb30e13437e80fc79",
+ "packages/runtime-node/src/mcp-clients.ts": "e632c290522e3f3635ea9b35cca3f6071992404cd41624401d015d8ffa7ba686",
+ "packages/runtime-node/src/mcp-clients.test.ts": "63527526b41b2f49dd45014e0cacc71dc85109b586936cc8c651b0a53ac0029f",
"packages/runtime-node/src/index.ts": "5c183ab246921ee2c3b3253135fdcbca31f57d110d2688c313e1af5bda3e80d8",
"packages/runtime-node/src/hooks.ts": "81fb19f6dfe4c698fc8c0e4982ad1e1aeb77695ce4264ebbd67be32e2f7d7032",
- "packages/runtime-node/src/hooks.test.ts": "11209a5e48af2ce7c948d7b28f195822bf80946ee17e3689ce05c8e521b06642",
+ "packages/runtime-node/src/hooks.test.ts": "1d2b374b5e432a0924b91ac5a7db5b6dfc48a7161efaa0e1bf95b103d1bdfe9a",
"packages/runtime-node/src/config.ts": "da46e647792e1b8cbc02dacd5f190aee2175ad28a5cef51ec8e60e1de96502df",
"packages/runtime-node/src/config.test.ts": "47f290bba87c19b5b4cac3428e69391d607121d882f8f40c43b67e187bbaf467",
+ "packages/mcp-web-fetch/src/url-safety.ts": "ba11ec3ded9a8286be47bb375ff41817354c8c0c398aa60b3825696c743500a8",
+ "packages/mcp-web-fetch/src/url-safety.test.ts": "774c63fcd5b82545499d12f1dccb92c134b77965d26e526cd9edf78e41d1ee75",
+ "packages/mcp-web-fetch/src/types.ts": "2592bcf6f201c910296e6b7d85e07d0a7b5d7242ffb0963d6af48fdfa6fdb193",
+ "packages/mcp-web-fetch/src/tools.ts": "53c64a38b793048b66e1ba6776a3a8e09d99c4687f57c114063554a467985985",
+ "packages/mcp-web-fetch/src/tools.security.test.ts": "06bda79cb7c6a2f0f065fabf26a8f097d9459ddcac804532bbf5f2f1939b1b0b",
+ "packages/mcp-web-fetch/src/limits.test.ts": "5d2a2d317f05124f2cd1e76f59c97d0575015760699ba47d1808615fc67657a7",
+ "packages/mcp-web-fetch/src/index.ts": "bb89e653a22cf4f6778f28674ca664c2fb17e31fbee830e236d37eb56435a293",
+ "packages/mcp-web-fetch/src/html-to-text.ts": "9ae4c23754c29b68fac312f859edefd7a5ee7cbcf3a274a746d2798004434672",
+ "packages/mcp-web-fetch/src/html-to-text.test.ts": "537ced004700d5c860c69c939f6524ab6c39976bbd444bfc9e3807e258f3c504",
+ "packages/mcp-web-fetch/src/engine.ts": "6c7687faf56ad410a9334b52f4848ee841e46d08bf4f15ad1db75c979f242dcc",
+ "packages/mcp-web-fetch/src/engine.test.ts": "7e88181d2af4b7776002e560bca787dbdf30ea6525ff62a750222ab56893be90",
+ "packages/mcp-web-fetch/src/engine.lookup.test.ts": "3bf01dbbed0a9e242befa6b34bcd8250115bb31674ff6f0d74969502680d0cdc",
"packages/mcp-web/src/url-safety.ts": "e2c0e96b2ce1ba756fc758c464587c99946c5762b47b638fbc97540ea72e2c3a",
"packages/mcp-web/src/url-safety.test.ts": "c336e3e5404451277e90c79f24c4af228046259c5bb04eb3fb00418de2d9f3fd",
"packages/mcp-web/src/server.ts": "72572ce5c3d25cb77d4051709c3aa6a376e70e4b9a257adab7511fd677d38f9d",
@@ -193,9 +239,9 @@
"packages/core/src/workflow-integration.ts": "66b8ee8f5e580ddf3a27d8a8a748ae0f223233f4d632497e1b567a791be14574",
"packages/core/src/types.ts": "b65ac88501152fdf1a56db5dc40400f46bb4c6d7c7fc06babc9ca6ad2cdb14c4",
"packages/core/src/security.ts": "6fe1a0a064aaeb8141482a374170c1b7e9f158389cb25c80653442b8846fd546",
- "packages/core/src/security.test.ts": "59281e8ede199f098fb9912deebd8c4516be51ebc212c429cca43bc0b39b756d",
- "packages/core/src/planner.ts": "ebfa94c4253e12e32dff800dfcb447018c35c8cb0e8b6584418173c3c8ca5f50",
- "packages/core/src/planner.test.ts": "4337c21dce5dfcb18346b25c58efff929edb2b4b95a1502b246ae39c5ee77796",
+ "packages/core/src/security.test.ts": "9f68c4b5c51bbdbc578febfc71211ad8ddc76ea8b222deb9b21da971384398a9",
+ "packages/core/src/planner.ts": "54918438dc7f08663a4de935194e157c13cc3882c2d8d9dcf208b72e34cc4f05",
+ "packages/core/src/planner.test.ts": "437d480e41ce6ff3606d1fc1d00194e0110b9c0418fa0fda6134361d594b167c",
"packages/core/src/planner-phase-helpers.ts": "9cf7dcaf4faa6c2a6ef3351ce4ff24eb8f84a5d056ba80c1526355cb50eb3a39",
"packages/core/src/planner-phase-helpers.test.ts": "62d59ffdff4f01e8bfd1ba20e8660223bf9c37d98f924bc2a21252b205c42cb6",
"packages/core/src/llm.ts": "a65bcc07b3ee168db391929352cffd719384d7e080713ff1e153cce4896f889d",
@@ -206,20 +252,12 @@
"packages/core/src/context-filesense.test.ts": "185e08bc36963359fd7d2e2457da5059d47f5094a4713add2af2f3e0b6e17ef1",
"packages/core/src/a2a.ts": "80764ec469da695ea3025bf4b1e265abb60ba5d592734f96af7e0e8009557a0d",
"packages/core/src/a2a.test.ts": "e64d44430cd2a80f3a7fd3d5850da6cd06dfab439dfab8897717aafa8c4fe29c",
- "models/frontagent-planner/test/05-10.py": "7641412379b14a6118fa9692d85ef0d01818d6fc31beb5ca77d0744d73e8047a",
- "models/frontagent-planner/prompts/schema.json": "4d2734ebc225963ff770dc1cd8e255bbb94c2c340e539a5d33aba03c64486689",
- "models/frontagent-planner/prompts/planner-prompt.md": "2059bc8238f85ca74c2af0ed305fd0289f59b1ce0a69cfebbc4278043d4204ca",
- "models/frontagent-planner/prompts/error-recovery-prompt.md": "a7d547bb87277a0aa4af404960449eb4888d7d22b57ff7b597b0f527cbbfac98",
- "models/frontagent-planner/hf-release-14b/adapter_config.json": "538e2560e452ecfddb184b51c03e6a9745cd79a10ab210c4233070d6962232cb",
- "models/frontagent-planner/hf-release-14b/README.md": "34effd563d8f79ad356883e877c779b25d665e9c0da7d2544c6746388eb5d178",
- "models/frontagent-planner/hf-release-14b/EVAL_RESULTS.md": "9795f9df99cb5aa51a2bcb1d3174078cecdc661093660190ccf5ff4d95bd7b13",
- "models/frontagent-planner/hf-release/tokenizer_config.json": "f38df2b424046acfd6bca1a712900bffa2a8a5e1690d10b1566da92eb2dc0bc3",
- "models/frontagent-planner/hf-release/chat_template.jinja": "3e3e4ccd01b95ae100e861475e34dd42d044d15858f876bb73fe2934fe1603db",
- "models/frontagent-planner/hf-release/adapter_config.json": "52098a437e9746f43e18e54a7aaa610e3f5953640937fc9d9abffd9fb46fca4b",
- "models/frontagent-planner/hf-release/README.md": "5d23189b40ee100941e0ab2adf37fc81effe8a73ebf18d7d3bf4d91cdfabc941",
- "models/frontagent-planner/hf-release/EVAL_RESULTS.md": "e05d09d123972ef6da8aa96e6af2ed39f8aa79ef7c27c792e5c6931d58c7d957",
- "models/frontagent-planner/data/generate_data.py": "e38c6d8b8081200dc93e3ca1efdb728cbd872c25aef1efbadc82b587f46a25dc",
- "models/frontagent-planner/data/eval_v2.json": "d1a0d6d1ce8dfea26e3fca620fe784fa4948916804c74f5dde5c70e738e373ae",
+ "benchmarks/eval/out-smoke/full.jsonl": "e9aecc6ebf189bbe5c5f327a47ff2c86bf15f377f3e18dd695cc76799d45657d",
+ "benchmarks/eval/out-smoke/ablation.jsonl": "82b56ee1138667369da1cac5b4c8e9c3d482902f56c54cdaff07bee7150bb72e",
+ "benchmarks/eval/fixture/tsconfig.json": "3f8e83433971f199d6ec3f029db97b4d832ff483f11a223131aee0ed12e3b241",
+ "benchmarks/eval/fixture/sdd.yaml": "e7e31eae2b88b87eead36b7230463e18baaf0e45185feb756ce21cece0e71372",
+ "benchmarks/eval/fixture/package.json": "e89af11d460bde5fc240e65426495785d39ad6a2bae8ca02d3d90cf6875483cc",
+ "benchmarks/eval/fixture/README.md": "51d92a0a381d6fa2e981a24f0442ce08dbf59f2f09b88b2d8dc6a8802491bf09",
"docs/superpowers/specs/2026-06-11-gitguardian-ci-design.md": "292229a60ccb6c15c00bd1ecb0f2f052e3df7ef308ba4c717623b55cfd016c72",
"docs/superpowers/specs/2026-06-05-frontagent-oss-harness-design.md": "f0948f03e6d21128229df42d46be1008454ff0df3ee2cb7f5f551f18306a6161",
"docs/superpowers/specs/2026-05-20-frontagent-repo-guard-design.md": "924705c8c507e21079d63e838942706fc43e7a191ae7680ce7d943b73239805b",
@@ -285,13 +323,13 @@
"apps/cli/src/run-logger.ts": "439d3f0d7db3cb5aa7259e3c3754dbc8a676995b252b524d9639a358728284c3",
"apps/cli/src/run-logger.test.ts": "98cf812a1251be78f384ccff62709b1a99997c8c9b40fb6879ce46a0b2d5b7f3",
"apps/cli/src/mcp-client.ts": "c4b41745c77d7806850e21ab385e0339a305796bcfcf550de1ae983b4f7e3e13",
- "apps/cli/src/index.ts": "360e75a14c42fecb1c22df1e04be40847d4b689f0d95f2a20fc5ddb01c5b3315",
+ "apps/cli/src/index.ts": "3f07f97bf0f7c27e129e2c28cc3b41245ed3625bfea746cbc94f8958f1cc89a9",
"apps/cli/src/index.test.ts": "ef81661c2e89dc3586afcc4788d2d2191bd2053aeee39d1209b45851d1cfbe8b",
"apps/cli/src/bootstrap.ts": "30faec23379af02d64337f24cc743b62f2b720eaf6b0b8b1ba7c3ae2fabfdc8e",
"apps/cli/src/bootstrap.test.ts": "0257c4822f3ebd3aa29914f302438158ad5f5d14d072a1ba85f510b047a76d8d",
"skills/frontend-design/assets/templates/visual-brief.md": "2e7e116227d0489e5cb886cc8e1f0d5e303bd35166d6e4a3f598cbfef795e897",
"packages/shared/src/types/validation.ts": "d80143b224dbc1dd26186c523ee8d64788df88629c23546a79e6afa5b83a9e76",
- "packages/shared/src/types/task.ts": "3935a80cb3ddf91259b9d4218e76c29a6df15bfe7bc052c7503ef622eb06c36f",
+ "packages/shared/src/types/task.ts": "182a6f407db6f72b31b48f67ed9ad0713ccb4844c313a8c0ee681749385270c6",
"packages/shared/src/types/sdd.ts": "51fa604aec9961284ffa198dabc82d21b34211c8ddcf57c0bcf25c8c7cdf6691",
"packages/shared/src/types/page.ts": "53562720a980625a8743b06c87ecbf9ee0dfd36cd0780305972accbc46e459aa",
"packages/shared/src/types/mcp.ts": "4d5f536029543329cb1d131442b1c38e0897f4b5aaa7ce3f0ee733979fe7742d",
@@ -341,8 +379,8 @@
"packages/mcp-memory/src/rag/index.ts": "8140815159eaec7792ffea54261acacee07c3bb5c28247c7421282e2be986a2d",
"packages/mcp-memory/src/rag/embedding.ts": "9d34925a6e1cea0d14d98a4c5b72db4c94b36541b537680002780dff2c306865",
"packages/mcp-memory/src/rag/config.ts": "42df1919561d9a1eb792cc25a8c2d87c920fa16683fe62fa326dfa8f4431f587",
- "packages/mcp-memory/src/rag/chunking.ts": "98aafd8bc85c2b55c3c7345ddc67eaf550298a559c3ebc1097690819181cd155",
- "packages/mcp-memory/src/rag/chunking.test.ts": "14e18f45e14ab275ac360bf3d2857679c8c455d2ee18b4d163df98c71a147cdb",
+ "packages/mcp-memory/src/rag/chunking.ts": "cd542c66be4abfe8b41dfcca9c36b178990c6e3b3e8e46806e9877cef7b90236",
+ "packages/mcp-memory/src/rag/chunking.test.ts": "8faa0aaa3c56f68d21a1403c63ce10eaaf62a769f42b32034ef4c951ef166546",
"packages/mcp-memory/src/rag/bm25.ts": "d62cc31c992b648e4edeacdacc26fca248b629d5bdd8639f2c001e256e819f8d",
"packages/mcp-memory/src/rag/bm25.test.ts": "04cfe2532ba68fb3edfc55bc74c627a7c9d11402f8414490c983152718260a80",
"packages/mcp-file/src/tools/search-code.ts": "03bd8a4feb391ed2b70de513d07ef0f6d9105d3ff6ac9bc9dd75d971cb660283",
@@ -352,6 +390,7 @@
"packages/mcp-file/src/tools/list-directory.ts": "d66b7c71b16758797f04785a870fa83b78c98f6dcb529d10448cf48fb3e9e8a9",
"packages/mcp-file/src/tools/list-directory.test.ts": "3b9b13a03dd09b54c806e3b23376425c593b4d1acd0d36e7e4083b58bb8206f6",
"packages/mcp-file/src/tools/get-ast.ts": "6d71c80ca67f9e7d4acec9d24b5583f439a93168e50f3e2942bed31410c32ab9",
+ "packages/mcp-file/src/tools/get-ast.test.ts": "60780528c3ad2d441d7e926a7599ef6ba618108f2ec5dbee4d83dc3d5b9c7df9",
"packages/mcp-file/src/tools/create-file.ts": "65106c198b77ed1d0188eed4972d612ce92c9527892d41c8265226e18236448d",
"packages/mcp-file/src/tools/apply-patch.ts": "a3f36f90a9795ff2d98b3d365dc58909e50bf89681fd63372b67e85d7839571a",
"packages/mcp-file/src/tools/apply-patch.test.ts": "a69b407be8406ef7104a6408a9f468bf9cdeb52f002c281bc4cee4e0b70b0edf",
@@ -370,15 +409,13 @@
"packages/core/src/sub-agents/index.ts": "5e418464ce940767df6d6532e156595d23b879d7357f23b3e204253e68b362e2",
"packages/core/src/sub-agents/code-quality-subagent.ts": "1c224562414843daf0569781ac30904b5617a7e478549d24c4717b76c04792da",
"packages/core/src/sub-agents/code-quality-subagent-worker.ts": "e9bb56c7dddc6801434ec07b9cab73c1db469fa9f85f9e8df8cd7e54c9ee2b97",
- "packages/core/src/sub-agents/code-quality-prompt.ts": "5f10b7b48d51839bea1783edb6da08171270b35717e35aebe87aa916c154cb70",
- "packages/core/src/sub-agents/code-quality-prompt.test.ts": "07123ac26bc72a0ddd944851e8673a65ad962db377b7debdc18b2d1227d5d9e7",
+ "packages/core/src/sub-agents/code-quality-prompt.ts": "c9f2319f9339b31ae7412ece235533227c66285028c99dac9a01a370b9d7a657",
+ "packages/core/src/sub-agents/code-quality-prompt.test.ts": "6d6e787aa91e742dff455f18f914d9167488bc283c6c868e01724fa2d39cb9f7",
"packages/core/src/skills/types.ts": "8531586e4271c389ff519757c31be29c666801948036eaeb637f247c6b3b06df",
"packages/core/src/skills/planner-skills.ts": "4baa53855f73554639eed73bdc4bc2d8e84fe517f6b6c72d8b50b1d19e419160",
"packages/core/src/skills/index.ts": "e9ec8b593e7239d3c9a5918302c983dac20ed4f967a62c0f8d3edd1d99de6536",
- "packages/core/src/skills/executor-skills.ts": "06d7096eae0e07f85c08724314b0af2e1d7e0b84df06ad8cf1af66b521a93bf0",
- "packages/core/src/skill-content/types.ts": "4f04bc41f0b2138f761ee0e12d951e6194eaa98a35d4295b1283a287ec03df05",
- "packages/core/src/skill-content/resolver.ts": "43352803efb6de138a7cd2ffb5f6e50d3adc7edb0d4536ac2ea977fa7388214b",
- "packages/core/src/skill-content/loader.ts": "4d9af6e5427ee4e46e8356f8ada39a3ba53eedf162e365dfee49683d85e7ebc5",
+ "packages/core/src/skills/executor-skills.ts": "c397ebc881185c77e1867a06d04b922f29e16e2d2c9e3dd60f3d50ed948226ea",
+ "packages/core/src/skills/executor-skills.test.ts": "ac70181ff4a47922a6b508c1611f4040d0146fdea7b3d08babdb6101ab52506b",
"packages/core/src/skill-lab/utils.ts": "b1492635e04603cc0890888dcb6bf084d9a840d3e217218b040739e1c8fc9f54",
"packages/core/src/skill-lab/utils.test.ts": "07eeee6577a820b666219f6e23566abf6f837d203793463a526af786676756a9",
"packages/core/src/skill-lab/types.ts": "7148f36c4610fb2da8f4247ab236884082d66599b410fd3315c959ac7cafe96d",
@@ -391,6 +428,9 @@
"packages/core/src/skill-lab/improve.ts": "29ea61dadbbb0652a5d72ff6cf41c383450d256636ae853431f591271b8fa702",
"packages/core/src/skill-lab/benchmark.ts": "8c6f45755bc2b96808be370e1cafd6b979602cbe7bd92af18fb653b19424a2c8",
"packages/core/src/skill-lab/behavior-benchmark.ts": "35f10cfdd6d08801129ddd389763faf182d0e1508a9149ef6ac2b5bdc9ea3fb7",
+ "packages/core/src/skill-content/types.ts": "4f04bc41f0b2138f761ee0e12d951e6194eaa98a35d4295b1283a287ec03df05",
+ "packages/core/src/skill-content/resolver.ts": "43352803efb6de138a7cd2ffb5f6e50d3adc7edb0d4536ac2ea977fa7388214b",
+ "packages/core/src/skill-content/loader.ts": "4d9af6e5427ee4e46e8356f8ada39a3ba53eedf162e365dfee49683d85e7ebc5",
"packages/core/src/memory/types.ts": "97fb8897e147fdc1ba7084153a8b2e1fdc737e83882105ae36b54ddc81745344",
"packages/core/src/memory/store.ts": "40d1b0697b92211954baeb96b577e42665180ff50ad8f2052b67bb5a06ee529c",
"packages/core/src/memory/store.test.ts": "1731709002ca2e3edc219ae994b175591f4bdaf8590026834d5473e981606675",
@@ -400,20 +440,35 @@
"packages/core/src/memory/open-memory-gateway.ts": "fd818b67d607bf97d083d7e509378ac2fff9ff714b983a4eebaadb0fc35aefaf",
"packages/core/src/memory/open-memory-gateway.test.ts": "8dc2624b47aca5b3b649fa96bb0aaf7ebad872eefbd695c3c24020d1f3830931",
"packages/core/src/memory/index.ts": "f3a37d193cfffe4bff863972ea4a488f3300abf06f56516fd669a1ace4dbf1b6",
- "packages/core/src/llm/schemas.ts": "5495272d665299e00a17c61b275e0fdd0527ac7afdf53588101825de832e5584",
- "packages/core/src/llm/prompts.ts": "97d9522bf05e592d934f9df118d8d2e64c6348b1f595256b751cf9992fc15702",
- "packages/core/src/llm/plan-generation.ts": "a49bab4c9a2c39d91cb25069c5d1e94b37cabcbec853ed500cde8d3ef8cb4635",
- "packages/core/src/llm/plan-generation.test.ts": "15c8cc571b8f9fae37f39855852d88270822b11682709f34401519698e2d579a",
+ "packages/core/src/llm/schemas.ts": "4d98d139412e68c740fd969fb0f9827a91da57030eb926bf2d3f9472030833a3",
+ "packages/core/src/llm/prompts.ts": "e68f9b311d7fe94d725fe715d7685f3116271b1798e02831a0e6f56a16aa0bc7",
+ "packages/core/src/llm/plan-generation.ts": "4429730839dd7bc66b645387473ab28ecc5b00f0dafea184c12c7a89af0ca643",
+ "packages/core/src/llm/plan-generation.test.ts": "defae704ddee029a79cee91dc9b2f3b1fb3e7768c268df64b298e100cdb2800a",
"packages/core/src/llm/object-repair.ts": "ac93064b3e4157f9246160a6ef39d719a0464921567b33f3ee653f360950870e",
"packages/core/src/llm/object-repair.test.ts": "ee9a9669f3d350eb42c54076899f0f55fac70c734d6ea23524e560e7cd07093f",
- "packages/core/src/llm/llm-service.ts": "9d1b78d14d2c9c8101ab0bc3f5666e45f95ba812daf3718376ae36c8108a60e5",
- "packages/core/src/llm/llm-service.test.ts": "d1f4f25dfb18197c4b4d16cc01b05c98f16f4777e1dfd0f575a540122d977b36",
+ "packages/core/src/llm/llm-service.ts": "1065b3ddcdfaa299650425795f339aa129fa49699fea452769eb7e03d3a97d95",
+ "packages/core/src/llm/llm-service.test.ts": "e78c99cdcb52a3c8844e879d7dcf04006e2d95987ecd1f1cc8f716329b63d266",
"packages/core/src/llm/index.ts": "9099ae980c974075574497195af7ee167da67c002f061599570077407a421c71",
"packages/core/src/llm/factory.ts": "84439c057c0027efbfa9d4873c855c51845f7dae985cac685a122c016b8c0ca5",
- "packages/core/src/llm/code-generation.ts": "cf55a99d48918070120c9be9ccb09e69c95b089087088c864575c5de857f223a",
- "packages/core/src/llm/code-generation.test.ts": "15f23109fa11c93030db8a4c08f78481e2158e6263d59bb6e45e4868b4c5f495",
+ "packages/core/src/llm/code-generation.ts": "f44594e983718ff05630c3d2108b39aa869165430a8339a21ae79ec67ab5f98b",
+ "packages/core/src/llm/code-generation.test.ts": "bc12ed05116eded21359e5c0af698a3eba5cc74b788ec8567d530a7d77737359",
"packages/core/src/filesense/trigger-policy.ts": "becfb5ac97f431b88236597d096f0e8d64a72befcd22e82c0b3305dc9ce1f4fa",
"packages/core/src/filesense/trigger-policy.test.ts": "0d0098cb511c6d6f574833fd3c9ea0b2b62252fe5fdfe0fa5367c6fa522fed89",
+ "packages/core/src/context/project-instructions.ts": "5b4f2e64d6965ff972bbb76038db0f353f12bde872e677fbc1b2d6dd3617bc94",
+ "packages/core/src/context/project-instructions.test.ts": "380f404c8824d9e92af06dc7808e702a59678d835c6885f7566633395fe764b5",
+ "packages/core/src/context/module-dependency-graph.ts": "8cae095707cef46249cb5141f2e570420cabfd23b0efc7742896c626097809d5",
+ "packages/core/src/context/module-dependency-graph.test.ts": "3b86ca71329444b84f6bb1940f128a462a69f2b99591923fd76de6a390f5bbbc",
+ "packages/core/src/context/index.ts": "3f2545c79b7c63f75bf5461810c1f43c32cf6766ca29a57f626ab6087cdccd0a",
+ "packages/core/src/context/helpers.ts": "a6463181a4cdc8d9ea7e2145b36ac7d5a6124e7be8d6318a1a2b021f523b1be2",
+ "packages/core/src/context/helpers.test.ts": "ca2cae1f6d3addc97bd1f9920e106256e6af390e22b4c7eeaa3d694cc44df669",
+ "packages/core/src/context/filesystem-facts-update.ts": "4439f47b4854083e151f993df53cb969f26fd6fcdb27c4fa26ba805f9108f97a",
+ "packages/core/src/context/facts-merge-helpers.ts": "c300c9368dbdb9561ea005f0d3d78e65f0d0b4759c8633cd9a25c3013a5b18c7",
+ "packages/core/src/context/fact-serializer.ts": "25e3773276512aa52be43092f6339e5600f71406bd221972764ddc1242f2595f",
+ "packages/core/src/context/fact-serializer.test.ts": "72c82961e7c6c5ad07ab8e952e179fa8df4a97ce5fd27bdc63e82cd6a58dee44",
+ "packages/core/src/context/context-manager.ts": "f5ba69b1d1ec7d04968d326bd38e463076cec05065f17a9fb499e549830004e5",
+ "packages/core/src/context/context-manager.test.ts": "7620dba14a25845b8f2883581d4a2a03a3fa2b3bd8b2afa24fe611fcf65c4025",
+ "packages/core/src/context/budget.ts": "0530402b7bfa3a2da5601f5b15a923278f8acdc2e9334814616ba1c5d335dcaa",
+ "packages/core/src/context/budget.test.ts": "d7f11aab8fc4859a61d1d0c88ae5839ebc4eb1060901d6c8f4719ee031eb5b78",
"packages/core/src/executor/types.ts": "1b5d42eb6abe73c13fc317c98fc95e0bc6b199c0ee3b660a54abc6cee910d987",
"packages/core/src/executor/trace.ts": "294032d09c18a549db371474cfe6387c369d6ca4f5493d0c2b79339c5b5d87f4",
"packages/core/src/executor/trace.test.ts": "cd9340cef2ed972be6bc64de3979b25053352ac37f47176c09bcf44427a086fc",
@@ -431,24 +486,10 @@
"packages/core/src/executor/index.ts": "ae4ff32e0e696a01a6f66f2bc963d45d08ced83361be39e32f58018ec6ed38e8",
"packages/core/src/executor/executor.ts": "002d61ca4b93f5e42c7fba9b526444e8f142e58361c3fa970b910fc75417540c",
"packages/core/src/executor/executor.test.ts": "ec0c491de48ce27a138289ac6ac05b5b0429b017b0f4c5a9947329d1ff957edd",
- "packages/core/src/context/project-instructions.ts": "5b4f2e64d6965ff972bbb76038db0f353f12bde872e677fbc1b2d6dd3617bc94",
- "packages/core/src/context/project-instructions.test.ts": "380f404c8824d9e92af06dc7808e702a59678d835c6885f7566633395fe764b5",
- "packages/core/src/context/module-dependency-graph.ts": "8cae095707cef46249cb5141f2e570420cabfd23b0efc7742896c626097809d5",
- "packages/core/src/context/module-dependency-graph.test.ts": "3b86ca71329444b84f6bb1940f128a462a69f2b99591923fd76de6a390f5bbbc",
- "packages/core/src/context/index.ts": "3f2545c79b7c63f75bf5461810c1f43c32cf6766ca29a57f626ab6087cdccd0a",
- "packages/core/src/context/helpers.ts": "a6463181a4cdc8d9ea7e2145b36ac7d5a6124e7be8d6318a1a2b021f523b1be2",
- "packages/core/src/context/helpers.test.ts": "ca2cae1f6d3addc97bd1f9920e106256e6af390e22b4c7eeaa3d694cc44df669",
- "packages/core/src/context/filesystem-facts-update.ts": "4439f47b4854083e151f993df53cb969f26fd6fcdb27c4fa26ba805f9108f97a",
- "packages/core/src/context/facts-merge-helpers.ts": "c300c9368dbdb9561ea005f0d3d78e65f0d0b4759c8633cd9a25c3013a5b18c7",
- "packages/core/src/context/fact-serializer.ts": "25e3773276512aa52be43092f6339e5600f71406bd221972764ddc1242f2595f",
- "packages/core/src/context/fact-serializer.test.ts": "72c82961e7c6c5ad07ab8e952e179fa8df4a97ce5fd27bdc63e82cd6a58dee44",
- "packages/core/src/context/context-manager.ts": "f5ba69b1d1ec7d04968d326bd38e463076cec05065f17a9fb499e549830004e5",
- "packages/core/src/context/context-manager.test.ts": "7620dba14a25845b8f2883581d4a2a03a3fa2b3bd8b2afa24fe611fcf65c4025",
- "packages/core/src/context/budget.ts": "0530402b7bfa3a2da5601f5b15a923278f8acdc2e9334814616ba1c5d335dcaa",
- "packages/core/src/context/budget.test.ts": "d7f11aab8fc4859a61d1d0c88ae5839ebc4eb1060901d6c8f4719ee031eb5b78",
"packages/core/src/agent/task-execution-setup.ts": "f46a6d58bb9b11931bb5ef78f96e63e87309d03f116487fd5247e58f7b54019b",
"packages/core/src/agent/task-execution-setup.test.ts": "ef7d803ae494446c6099fff6628c9f15d5604fd9ad9237a50b40da0e692c67e0",
- "packages/core/src/agent/step-callbacks.ts": "c74dcaba76e1bc189c485d27fc91801f1fe3f431c9c7eb9b4fab367d1cae9179",
+ "packages/core/src/agent/step-callbacks.ts": "39638ccf6570507a05ce8ca52cd00dbe1ca9be09849c237abdb0873fad226d66",
+ "packages/core/src/agent/step-callbacks.test.ts": "b9d1b47675161b5f7b26495bf78b72b077ef949fb30c3a76887b1923cdd18c42",
"packages/core/src/agent/rag-retrieval.ts": "f19c654d82704d7ed61a32fc2cd11689e4561d4a0187f2c2a51b3505983bffb2",
"packages/core/src/agent/project-prescan-preparation.ts": "424f383a917da902ec2bd4e0b561b3961aa639706453aa54b993f76e121a9ea1",
"packages/core/src/agent/project-prescan-preparation.test.ts": "459a030f607d1bc5584754d49f4f63451037b7f9e7e4877b346cad160c3e5976",
@@ -467,10 +508,35 @@
"packages/core/src/agent/context-gathering.ts": "dce973327ffb3611cc1365ca28466b38555201ac9b709ee484de7ff4f99a5f05",
"packages/core/src/agent/context-gathering.test.ts": "0e91333250b59e6561eb36b14162aa67a7e566ce8fee4332e9895f127f88a42a",
"packages/core/src/agent/answer-generation.ts": "0f727f88ff5914ae26e3b9c22750ece0929fa5312ead958bc3e648d1b7e39644",
- "packages/core/src/agent/agent.ts": "1c8a391df82010660ed372a4d653a39f45c1d04697670ea0acba8c544165132a",
- "packages/core/src/agent/agent.test.ts": "0c3545da0c7fc0b010c4b4b14965cd78e267410bd314bb224dd3c91e8e13621b",
+ "packages/core/src/agent/agent.ts": "d5f3271fe4de4ed9ebd15e42a3791afdd02573a8cf8dfc607428794192357c00",
+ "packages/core/src/agent/agent.test.ts": "1416f694bfa99a597a8d8c3bf7cfd56de56324c1d31a5e5abff5eb1bebe592b8",
+ "benchmarks/eval/fixture/src/App.tsx": "d4bea307ccedeffc80ade36baadf8792f6d14b0bf13f38ae695904f613fd514c",
"apps/vscode/src/test/vscode-stub.ts": "a43f4fb5b3333b3007229013f6ec8374bac986e1ae2f816aa2da1a3e3aef99d8",
"apps/vscode/src/test/view-provider.test.ts": "a1af5b19cd0f666f80f64be75e83ac6fd627c679b3b7b8e39d8c2b030f8aa71b",
+ "apps/desktop/src/state/executionReducer.ts": "24e0090887dfb26272e02106313dc8cf613da2ad54a2a4f83d8e8b5b3feeff69",
+ "apps/desktop/src/state/executionReducer.test.ts": "1c607c6d61ea69e7b338b2b08f7faf9051f639387513b456cd704dfca0f8635b",
+ "apps/desktop/src/preload/preload.ts": "77fe49259e6d0fb8dc9611f7878f23aa18c9e5a61fa05f030c257159dc826cc9",
+ "apps/desktop/src/preload/install.ts": "670af61d45e8e54f46714a3849ed7bc35899b75b26fb3e83859ca05cf93ab7da",
+ "apps/desktop/src/preload/install.test.ts": "d57018724377b811884103c49253c90c8d924ded0249a88922ba10100de00ec8",
+ "apps/desktop/src/preload/bridge.ts": "f053b465d5eef0061722d511711d994e2cfc9af2177a5330a4ff8df11d1c4c02",
+ "apps/desktop/src/preload/bridge.test.ts": "a86dedfe04c2ed8efd3eb155bf256297ecfd71530d87ce5f19babc1f847c787e",
+ "apps/desktop/src/renderer/theme.css": "4631f5dc6626b375b7b51ca041d76e8bf9ca165a4f6e42a20ab7294d8ceb76c0",
+ "apps/desktop/src/renderer/selectBridge.ts": "752400cae9611427c8120a41a3d598e452b163706ec942280c0a789b1de2ae41",
+ "apps/desktop/src/renderer/selectBridge.test.ts": "3e73690337d931bddfad0686fec03f6935018fa76bdcd10127efec1a0cd171d1",
+ "apps/desktop/src/renderer/main.tsx": "15a0329e72706d02354b9b08d57619de4e3724cb62a54cb7c571dd3e93ff6628",
+ "apps/desktop/src/renderer/App.tsx": "5f512dcb824fd6ad180da74807d2b8eccc3b070e9a324f47942663bac64c8e60",
+ "apps/desktop/src/main/smokeProbe.ts": "945f855472ddb0121a4cdbff9888fa5815d2091e54c289de4d7bd597f0483479",
+ "apps/desktop/src/main/smokeProbe.test.ts": "bdb9c6cdca1f00d325c74aadf83e84f70789cdb8f5ffd744aaa9a7d3e5c549c2",
+ "apps/desktop/src/main/settingsStore.ts": "b0c0400e205222a142076d206c6582d7ffbd16b96b4045041dd4c44aa61d5fcd",
+ "apps/desktop/src/main/settingsStore.test.ts": "0e61fc7f66c4b1e9002a26302494db466092bcb3a9fcd6335e473cf98c8a1236",
+ "apps/desktop/src/main/runtimeIO.ts": "8c1a8c8c5bc8b0236c87cde79766ac1d2bfd47a077f777e375a50a3efe2a5b49",
+ "apps/desktop/src/main/runtimeIO.test.ts": "c53f766a7646ab4ede0571487ad8bcd06d08ef5ca3d7c5fe1182dd094ba5571c",
+ "apps/desktop/src/main/runtimeBridge.ts": "b52a42503fb3a5ceee263ee89d90e640f7bb543eb8706e58a477c1bbe4d69200",
+ "apps/desktop/src/main/runtimeBridge.test.ts": "a689ce8a9dbbc341544a54c2e6f474e4cd7439a94449e1e4d79d1090f240d4e8",
+ "apps/desktop/src/main/main.ts": "50b848626f309780190506453a0c322a09245b1f2b7fea5a6caf822e3053489a",
+ "apps/desktop/src/main/ipcHandlers.ts": "1f2cac26e38c2e8084c5de85b36a40218ac7d8c5bb0a8cb680e96b7a1a1f0bdb",
+ "apps/desktop/src/main/ipcHandlers.test.ts": "a12fcc84c307e2609a6e7716481af99e4bc850c3ce509271424a034d65fb50bb",
+ "apps/desktop/src/ipc/contract.ts": "069f94e8ab1782ca933a9572315e8d517e4c9f1806ca0f017626ccaadb54e332",
"apps/cli/src/ui/store.ts": "4f8221870061f581d25c52e15827e6cc0fb0960d64ed5c54df375a8ba57f2a0e",
"apps/cli/src/ui/store.test.ts": "93c4a61c0637806f86d9fddad9adc3d18693521948ff4b580b8b9d2bc28cd20e",
"apps/cli/src/ui/index.ts": "ca9e3a5b4986b07685586dad2df1fd12904d91a813b9e7c483421b6b55d11269",
@@ -478,7 +544,7 @@
"apps/cli/src/ui/bridge.ts": "00d529d4bc2637f7e3708c8f61dd798c241bedd90c185a7766d4afccf8cddfe3",
"apps/cli/src/commands/validate.ts": "73f3c9e931c17ecee63487b486866b8531d43a699ee83b93fdbc049ce8aeea5f",
"apps/cli/src/commands/skill.ts": "de5f58e9e06d0eca43e4cdb52b3ed245290ac7c0400802abde1b63682eeb2c6c",
- "apps/cli/src/commands/run.tsx": "781c9e3a3f012990041a1a6849f601b8565a25e46cb66947f96caaff2ed883f0",
+ "apps/cli/src/commands/run.tsx": "bb314afbdcf00cfba16c016fe0931417274c0b54b840865ca3f8198d15f75c9b",
"apps/cli/src/commands/rag.ts": "bd0f6994a36ce02ebf8b2ddaa3bfd192c202d10cc1cca43f68098a6562d51ca0",
"apps/cli/src/commands/prompt.ts": "41c570dbe98042bfca9c90b9f0f183063c28e341c24064e24150306429abaeeb",
"apps/cli/src/commands/init.ts": "b30d6db0091ba7cf488fca3750de86a72f80d194c1b00506c0165d52930a1aef",
@@ -494,6 +560,33 @@
"packages/sdd/src/workflow/checklist/validator.test.ts": "ac4662439c3c332a85b7d671ea696a43ebc230965548a08a9c82c2f79d6e6162",
"packages/sdd/src/workflow/checklist/types.ts": "82d2ae676e3d25d590ead701601188b9833d0a0773e720ebea653e915a16604a",
"packages/sdd/src/workflow/checklist/built-in.ts": "061ddaeec91bd19470f81e27def1ad1745e462d76e87f7dabe575a8b36513919",
+ "benchmarks/eval/fixture/src/hooks/useToggle.ts": "043d5853e956288120d906d43eaaf5703ecc6a98e6ede114d849247f13161487",
+ "benchmarks/eval/fixture/src/utils/truncate.ts": "6e1da7866b40ab5e3876bd0f91f91c51a6d872191c2cd5a9be83a713b74b0b92",
+ "benchmarks/eval/fixture/src/utils/truncate.test.ts": "efa0cacfdb81f0aa87ca538fdb9e783121bf51d6cac7b776db4cfb08443cd20e",
+ "benchmarks/eval/fixture/src/utils/pluralize.ts": "b8cce9384c7ed887bf45c66d59e595255a97e91197a3c4990dd1f270a2f7cd01",
+ "benchmarks/eval/fixture/src/utils/pluralize.test.ts": "42b84d9235d1c6128e47362e731c64062b4bac62ed2dba4cef770f08011b2a14",
+ "benchmarks/eval/fixture/src/utils/parseQuery.ts": "4d518009a3d0056c435a05381df563be4839358ccee9a597bb2330d8f8608648",
+ "benchmarks/eval/fixture/src/utils/parseQuery.test.ts": "18ac549e3be40be9ef55ffe6468b8db6d7524c28caa2fd1afc516f4190ea01a3",
+ "benchmarks/eval/fixture/src/utils/formatDate.ts": "f19a2beb1ea3db2f252496e1e4d3d77ff88bbaa75e4aabd0cbdde9d7e2518f78",
+ "benchmarks/eval/fixture/src/utils/formatDate.test.ts": "db7f07391c5b26b002fb69639b210ed6e46301601b1eb580e2c15d283637e4a5",
+ "benchmarks/eval/fixture/src/utils/clamp.ts": "d2d94d7531e2947bc6d0df52c4d8803384b79a1c6c36fc03e3cafaa679830a5a",
+ "benchmarks/eval/fixture/src/utils/clamp.test.ts": "c2a287cc86ac5c5154e040f5e19b54c0c4b7b93eebb887dd885307979a021576",
+ "benchmarks/eval/fixture/src/components/TodoList.tsx": "2088ca87d00e73b3b6ae9a61e1877c11673d31f92a20f3e6744eb75511326c4b",
+ "benchmarks/eval/fixture/src/components/Button.tsx": "c1ca7aebd1bd65be6ef3c52f791a386a957a3fdc840e4471fd161b05410d0d3d",
+ "apps/desktop/src/renderer/mock/mockBridge.ts": "487f0ba9eeda19322e0c0456d1d4597be523b0011258c2140e518d424c074082",
+ "apps/desktop/src/renderer/mock/mockBridge.test.ts": "401c06a4fb2b193b75aaab8130d45493fe44566fa021ea88c7972c2e2b531ba3",
+ "apps/desktop/src/renderer/store/useSettings.ts": "909dc8c915cf3df75c1cce9a47ef79398ab4afc01830b283cbd90cfcb4702a03",
+ "apps/desktop/src/renderer/store/useConsoleState.ts": "d8c87166fa0b6e63ddeff64df53bc4d7d8601b4bc868de76292fe0b8ec9e2ac9",
+ "apps/desktop/src/renderer/store/settingsController.ts": "052704df2acfb595921a6be18d8d0285a86ab808324cf1421e15ddd69c218e0d",
+ "apps/desktop/src/renderer/store/settingsController.test.ts": "6702d4b5b7f9c4454f808843a7ec4c5a4d21e8b757b4446796c6ab19f7f0e320",
+ "apps/desktop/src/renderer/store/consoleStore.ts": "486d10d56bbfa00c5592f536ea7c57f8a200678cbda8dd9bd8ca1a6309005875",
+ "apps/desktop/src/renderer/store/consoleStore.test.ts": "0d62b476bf0ff38e82911d7bfe1348829f79ec9e184e0990510f5a2fa706a394",
+ "apps/desktop/src/renderer/components/TaskComposer.tsx": "6909be319466a05a519569bab3b38cfda62598a10a5a8efb321f903f043cce15",
+ "apps/desktop/src/renderer/components/StatusPill.tsx": "687d4a4ff3492d1b4487fcc067d7e99b312a7acbc1dc3cdb5ac1e51d4e0c0ef6",
+ "apps/desktop/src/renderer/components/SettingsPanel.tsx": "9a0403419286990b7de1bbc35ef25fd4ce6c37c8e9a9f6f1446c77a02810b46a",
+ "apps/desktop/src/renderer/components/ExecutionTimeline.tsx": "329f4d3296dc0c55d9c974c77a9563e0d3e2a52c5a8ba49410d5b44caed734f9",
+ "apps/desktop/src/renderer/components/EventStream.tsx": "fa1785033082f6b8eec68d7ea87daae6601b71ff83b513c16b6c755f49591e65",
+ "apps/desktop/src/renderer/components/ApprovalDrawer.tsx": "9b8c05dc6cd0f8be9f5ef27bd40760044fa2229184a1700861ddf95de48a1154",
"apps/cli/src/ui/components/StreamView.tsx": "ee731bd505d280503553f96af3edb05a7333df0f521a54a7cc13614080983c59",
"apps/cli/src/ui/components/ResultSummary.tsx": "865fdca08c4102c19c805e58c3e0a872642f3d43d0709101023cf857d99f420d",
"apps/cli/src/ui/components/RagInfo.tsx": "068d4c6b396e50770c9b947edb53b3d8e89c15b3b8329ace8a4cc8daf04b1783",
diff --git a/README.md b/README.md
index faa6c2a6..ce5992c5 100644
--- a/README.md
+++ b/README.md
@@ -1297,6 +1297,19 @@ pnpm clean
- [RedBox](https://github.com/Jamailar/RedBox) - Local AI creation workspace for Xiaohongshu creators.
- [1flowbase](https://github.com/taichuy/1flowbase) - Virtual model gateway for publishing multi-model workflows as OpenAI/Claude-compatible endpoints, with trace, token, latency, and cost visibility.
+## Ablation Benchmark (reproducible)
+
+A frozen 30-task benchmark measures whether SDD constraints and the hallucination guard actually improve first-pass success. It runs on an isolated fixture project with machine-checkable acceptance (`tsc --noEmit`, `vitest`, file assertions), two arms, and resume-on-interrupt.
+
+```bash
+pnpm build
+node benchmarks/eval/run-eval.mjs --arm full --tasks all # SDD on
+node benchmarks/eval/run-eval.mjs --arm ablation --tasks all # SDD off
+node benchmarks/eval/report.mjs benchmarks/eval/out
+```
+
+Latest results: [`benchmarks/results/`](benchmarks/results/). **The current findings are negative and actionable**: SDD showed no measurable effect on first-pass rate, and the hallucination guard recorded zero interceptions while syntactically invalid files still landed on disk. Three root causes are documented in the report and tracked as issues.
+
## Contributing
Welcome to contribute! Submit issues, bugs, or suggestions:
diff --git a/benchmarks/eval/checks.mjs b/benchmarks/eval/checks.mjs
new file mode 100644
index 00000000..bddb823d
--- /dev/null
+++ b/benchmarks/eval/checks.mjs
@@ -0,0 +1,40 @@
+import { existsSync, readFileSync } from 'node:fs';
+import { join } from 'node:path';
+import { spawnSync } from 'node:child_process';
+
+/** 逐条执行任务 checks;返回 [{kind, ok, detail}],全 ok 即任务 pass */
+export function runChecks(checks, { workspace, resultText }) {
+ return checks.map((check) => {
+ try {
+ switch (check.kind) {
+ case 'file_exists': {
+ const ok = existsSync(join(workspace, check.path));
+ return { kind: check.kind, ok, detail: check.path };
+ }
+ case 'file_contains': {
+ const p = join(workspace, check.path);
+ if (!existsSync(p)) return { kind: check.kind, ok: false, detail: `missing ${check.path}` };
+ const ok = new RegExp(check.pattern).test(readFileSync(p, 'utf8'));
+ return { kind: check.kind, ok, detail: check.pattern };
+ }
+ case 'result_contains': {
+ const ok = new RegExp(check.pattern, 'i').test(resultText ?? '');
+ return { kind: check.kind, ok, detail: check.pattern };
+ }
+ case 'typecheck': {
+ const r = spawnSync('npx', ['tsc', '--noEmit'], { cwd: workspace, timeout: 120000 });
+ return { kind: check.kind, ok: r.status === 0, detail: r.status === 0 ? '' : String(r.stdout).slice(0, 300) };
+ }
+ case 'cmd': {
+ const [bin, ...rest] = check.argv;
+ const r = spawnSync(bin, rest, { cwd: workspace, timeout: 180000 });
+ return { kind: check.kind, ok: r.status === 0, detail: check.argv.join(' ') };
+ }
+ default:
+ return { kind: check.kind, ok: false, detail: 'unknown check kind' };
+ }
+ } catch (error) {
+ return { kind: check.kind, ok: false, detail: String(error).slice(0, 200) };
+ }
+ });
+}
diff --git a/benchmarks/eval/claude-cli-backend.mjs b/benchmarks/eval/claude-cli-backend.mjs
new file mode 100644
index 00000000..8636dcf9
--- /dev/null
+++ b/benchmarks/eval/claude-cli-backend.mjs
@@ -0,0 +1,126 @@
+import { spawn } from 'node:child_process';
+import { mkdirSync } from 'node:fs';
+
+// 空目录作为 CLI 工作目录:阻断 Claude Code 对宿主仓库 CLAUDE.md/项目上下文的注入
+const CLI_CWD = '/tmp/frontagent-eval/claude-cli-cwd';
+mkdirSync(CLI_CWD, { recursive: true });
+
+const MODEL = process.env.EVAL_MODEL ?? 'claude-haiku-4-5';
+const CALL_TIMEOUT_MS = Number(process.env.EVAL_LLM_TIMEOUT_MS ?? 180000);
+
+const tally = { calls: 0, failures: 0, inputTokens: 0, outputTokens: 0 };
+export function getUsageTally() {
+ return { ...tally };
+}
+
+function recordFailure(error) {
+ tally.failures += 1;
+ console.error(`[claude-cli-backend] call failed (#${tally.failures}): ${String(error?.message ?? error).slice(0, 200)}`);
+}
+
+function renderPrompt(messages, system) {
+ const parts = [];
+ if (system) parts.push(`[System]\n${system}`);
+ for (const m of messages ?? []) {
+ parts.push(`[${m.role}]\n${typeof m.content === 'string' ? m.content : JSON.stringify(m.content)}`);
+ }
+ return parts.join('\n\n');
+}
+
+function callClaude(prompt) {
+ return new Promise((resolvePromise, reject) => {
+ // 纯文本生成后端:禁用全部工具,否则「列目录」类 prompt 会诱发 tool_use
+ // 并在 --max-turns 1 下报 error_max_turns
+ const args = [
+ '-p',
+ '--model',
+ MODEL,
+ '--output-format',
+ 'json',
+ '--max-turns',
+ '1',
+ '--disallowedTools',
+ '*',
+ '--system-prompt',
+ '你是一次性文本生成后端:只依据提示词中给出的信息直接作答,没有任何工具可用,不要尝试读取文件或执行命令。',
+ ];
+ const child = spawn('claude', args, { stdio: ['pipe', 'pipe', 'pipe'], cwd: CLI_CWD });
+ let stdout = '';
+ let stderr = '';
+ const timer = setTimeout(() => {
+ child.kill('SIGKILL');
+ const err = new Error('claude CLI timeout');
+ recordFailure(err);
+ reject(err);
+ }, CALL_TIMEOUT_MS);
+ child.stdout.on('data', (d) => {
+ stdout += d;
+ });
+ child.stderr.on('data', (d) => {
+ stderr += d;
+ });
+ child.on('error', (e) => {
+ clearTimeout(timer);
+ recordFailure(e);
+ reject(e);
+ });
+ child.on('close', (code) => {
+ clearTimeout(timer);
+ if (code !== 0) {
+ const err = new Error(
+ `claude exit ${code}: stderr=${stderr.slice(0, 300)} stdoutHead=${stdout.slice(0, 200)} promptChars=${prompt.length}`,
+ );
+ recordFailure(err);
+ return reject(err);
+ }
+ try {
+ const parsed = JSON.parse(stdout);
+ tally.calls += 1;
+ tally.inputTokens += parsed.usage?.input_tokens ?? 0;
+ tally.outputTokens += parsed.usage?.output_tokens ?? 0;
+ if (parsed.is_error) {
+ const err = new Error(`claude error result: ${String(parsed.result).slice(0, 300)}`);
+ recordFailure(err);
+ return reject(err);
+ }
+ resolvePromise(String(parsed.result ?? ''));
+ } catch (e) {
+ const err = new Error(`bad CLI JSON: ${String(e)}; head=${stdout.slice(0, 200)}`);
+ recordFailure(err);
+ reject(err);
+ }
+ });
+ child.stdin.end(prompt);
+ });
+}
+
+function extractJson(text) {
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/);
+ const body = fenced ? fenced[1] : text;
+ const start = body.indexOf('{');
+ const end = body.lastIndexOf('}');
+ if (start === -1 || end <= start) throw new Error('no JSON object in output');
+ return body.slice(start, end + 1);
+}
+
+export function createClaudeCliBackend() {
+ return {
+ name: `claude-cli:${MODEL}`,
+ async generateText({ messages, system }) {
+ return callClaude(renderPrompt(messages, system));
+ },
+ async generateObject({ messages, system, schema, maxRetries = 2 }) {
+ let lastError = '';
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
+ const suffix = `\n\n只输出一个 JSON 对象:不要 markdown 代码围栏、不要解释文字。${lastError ? `上次输出未通过 schema 校验(${lastError}),请修正。` : ''}`;
+ const text = await callClaude(renderPrompt(messages, system) + suffix);
+ try {
+ return schema.parse(JSON.parse(extractJson(text)));
+ } catch (error) {
+ lastError = String(error).slice(0, 400);
+ }
+ }
+ throw new Error(`generateObject retries exhausted: ${lastError}`);
+ },
+ };
+}
diff --git a/benchmarks/eval/fixture/.gitignore b/benchmarks/eval/fixture/.gitignore
new file mode 100644
index 00000000..c2658d7d
--- /dev/null
+++ b/benchmarks/eval/fixture/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/benchmarks/eval/fixture/README.md b/benchmarks/eval/fixture/README.md
new file mode 100644
index 00000000..b80fccc9
--- /dev/null
+++ b/benchmarks/eval/fixture/README.md
@@ -0,0 +1,10 @@
+# Eval Fixture
+
+架构消融评测的冻结夹具:一个最小 React + TypeScript 工程。
+
+- `src/components/` —— UI 组件(PascalCase 命名导出)
+- `src/hooks/` —— 自定义 hooks(`use*` 前缀)
+- `src/utils/` —— 纯函数工具与对应测试
+- `npm run typecheck` / `npm run test` 为验收门禁
+
+组件与函数的具体接口以源码为准,本 README 不重复文档。
diff --git a/benchmarks/eval/fixture/package.json b/benchmarks/eval/fixture/package.json
new file mode 100644
index 00000000..ebde8ad1
--- /dev/null
+++ b/benchmarks/eval/fixture/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "eval-fixture",
+ "private": true,
+ "type": "module",
+ "scripts": { "typecheck": "tsc --noEmit", "test": "vitest run" },
+ "devDependencies": {
+ "@types/react": "^18.3.0",
+ "react": "^18.3.0",
+ "react-dom": "^18.3.0",
+ "typescript": "^5.6.0",
+ "vitest": "^2.0.0"
+ }
+}
diff --git a/benchmarks/eval/fixture/pnpm-lock.yaml b/benchmarks/eval/fixture/pnpm-lock.yaml
new file mode 100644
index 00000000..d756818b
--- /dev/null
+++ b/benchmarks/eval/fixture/pnpm-lock.yaml
@@ -0,0 +1,950 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ devDependencies:
+ '@types/react':
+ specifier: ^18.3.0
+ version: 18.3.31
+ react:
+ specifier: ^18.3.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.0
+ version: 18.3.1(react@18.3.1)
+ typescript:
+ specifier: ^5.6.0
+ version: 5.9.3
+ vitest:
+ specifier: ^2.0.0
+ version: 2.1.9
+
+packages:
+
+ '@esbuild/aix-ppc64@0.21.5':
+ resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.21.5':
+ resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.21.5':
+ resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.21.5':
+ resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.21.5':
+ resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.21.5':
+ resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.21.5':
+ resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.21.5':
+ resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.21.5':
+ resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.21.5':
+ resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.21.5':
+ resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.21.5':
+ resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.21.5':
+ resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.21.5':
+ resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.21.5':
+ resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.21.5':
+ resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.21.5':
+ resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-x64@0.21.5':
+ resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-x64@0.21.5':
+ resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/sunos-x64@0.21.5':
+ resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.21.5':
+ resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.21.5':
+ resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.21.5':
+ resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@rollup/rollup-android-arm-eabi@4.62.2':
+ resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.62.2':
+ resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.62.2':
+ resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.62.2':
+ resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.62.2':
+ resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.62.2':
+ resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.62.2':
+ resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.62.2':
+ resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.62.2':
+ resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.62.2':
+ resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-gnu@4.62.2':
+ resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-musl@4.62.2':
+ resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.62.2':
+ resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-musl@4.62.2':
+ resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.62.2':
+ resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.62.2':
+ resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.62.2':
+ resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.62.2':
+ resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.62.2':
+ resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-openbsd-x64@4.62.2':
+ resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@rollup/rollup-openharmony-arm64@4.62.2':
+ resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.62.2':
+ resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.62.2':
+ resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.62.2':
+ resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.62.2':
+ resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==}
+ cpu: [x64]
+ os: [win32]
+
+ '@types/estree@1.0.9':
+ resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+
+ '@types/prop-types@15.7.15':
+ resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
+
+ '@types/react@18.3.31':
+ resolution: {integrity: sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==}
+
+ '@vitest/expect@2.1.9':
+ resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==}
+
+ '@vitest/mocker@2.1.9':
+ resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^5.0.0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
+ '@vitest/pretty-format@2.1.9':
+ resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==}
+
+ '@vitest/runner@2.1.9':
+ resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==}
+
+ '@vitest/snapshot@2.1.9':
+ resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==}
+
+ '@vitest/spy@2.1.9':
+ resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==}
+
+ '@vitest/utils@2.1.9':
+ resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==}
+
+ assertion-error@2.0.1:
+ resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
+ engines: {node: '>=12'}
+
+ cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+
+ chai@5.3.3:
+ resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
+ engines: {node: '>=18'}
+
+ check-error@2.1.3:
+ resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==}
+ engines: {node: '>= 16'}
+
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ deep-eql@5.0.2:
+ resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
+ engines: {node: '>=6'}
+
+ es-module-lexer@1.7.0:
+ resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
+
+ esbuild@0.21.5:
+ resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ expect-type@1.4.0:
+ resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==}
+ engines: {node: '>=12.0.0'}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ loupe@3.2.1:
+ resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
+
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ nanoid@3.3.15:
+ resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ pathe@1.1.2:
+ resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
+
+ pathval@2.0.1:
+ resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
+ engines: {node: '>= 14.16'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ postcss@8.5.16:
+ resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ react-dom@18.3.1:
+ resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
+ peerDependencies:
+ react: ^18.3.1
+
+ react@18.3.1:
+ resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+ engines: {node: '>=0.10.0'}
+
+ rollup@4.62.2:
+ resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ scheduler@0.23.2:
+ resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+
+ siginfo@2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ stackback@0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+
+ std-env@3.10.0:
+ resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+
+ tinybench@2.9.0:
+ resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+
+ tinyexec@0.3.2:
+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+
+ tinypool@1.1.1:
+ resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+
+ tinyrainbow@1.2.0:
+ resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
+ engines: {node: '>=14.0.0'}
+
+ tinyspy@3.0.2:
+ resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
+ engines: {node: '>=14.0.0'}
+
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ vite-node@2.1.9:
+ resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+
+ vite@5.4.21:
+ resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+
+ vitest@2.1.9:
+ resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/node': ^18.0.0 || >=20.0.0
+ '@vitest/browser': 2.1.9
+ '@vitest/ui': 2.1.9
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ why-is-node-running@2.3.0:
+ resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
+ engines: {node: '>=8'}
+ hasBin: true
+
+snapshots:
+
+ '@esbuild/aix-ppc64@0.21.5':
+ optional: true
+
+ '@esbuild/android-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/android-arm@0.21.5':
+ optional: true
+
+ '@esbuild/android-x64@0.21.5':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/darwin-x64@0.21.5':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-arm@0.21.5':
+ optional: true
+
+ '@esbuild/linux-ia32@0.21.5':
+ optional: true
+
+ '@esbuild/linux-loong64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.21.5':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.21.5':
+ optional: true
+
+ '@esbuild/linux-s390x@0.21.5':
+ optional: true
+
+ '@esbuild/linux-x64@0.21.5':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.21.5':
+ optional: true
+
+ '@esbuild/sunos-x64@0.21.5':
+ optional: true
+
+ '@esbuild/win32-arm64@0.21.5':
+ optional: true
+
+ '@esbuild/win32-ia32@0.21.5':
+ optional: true
+
+ '@esbuild/win32-x64@0.21.5':
+ optional: true
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@rollup/rollup-android-arm-eabi@4.62.2':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.62.2':
+ optional: true
+
+ '@rollup/rollup-openbsd-x64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.62.2':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.62.2':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.62.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.62.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.62.2':
+ optional: true
+
+ '@types/estree@1.0.9': {}
+
+ '@types/prop-types@15.7.15': {}
+
+ '@types/react@18.3.31':
+ dependencies:
+ '@types/prop-types': 15.7.15
+ csstype: 3.2.3
+
+ '@vitest/expect@2.1.9':
+ dependencies:
+ '@vitest/spy': 2.1.9
+ '@vitest/utils': 2.1.9
+ chai: 5.3.3
+ tinyrainbow: 1.2.0
+
+ '@vitest/mocker@2.1.9(vite@5.4.21)':
+ dependencies:
+ '@vitest/spy': 2.1.9
+ estree-walker: 3.0.3
+ magic-string: 0.30.21
+ optionalDependencies:
+ vite: 5.4.21
+
+ '@vitest/pretty-format@2.1.9':
+ dependencies:
+ tinyrainbow: 1.2.0
+
+ '@vitest/runner@2.1.9':
+ dependencies:
+ '@vitest/utils': 2.1.9
+ pathe: 1.1.2
+
+ '@vitest/snapshot@2.1.9':
+ dependencies:
+ '@vitest/pretty-format': 2.1.9
+ magic-string: 0.30.21
+ pathe: 1.1.2
+
+ '@vitest/spy@2.1.9':
+ dependencies:
+ tinyspy: 3.0.2
+
+ '@vitest/utils@2.1.9':
+ dependencies:
+ '@vitest/pretty-format': 2.1.9
+ loupe: 3.2.1
+ tinyrainbow: 1.2.0
+
+ assertion-error@2.0.1: {}
+
+ cac@6.7.14: {}
+
+ chai@5.3.3:
+ dependencies:
+ assertion-error: 2.0.1
+ check-error: 2.1.3
+ deep-eql: 5.0.2
+ loupe: 3.2.1
+ pathval: 2.0.1
+
+ check-error@2.1.3: {}
+
+ csstype@3.2.3: {}
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ deep-eql@5.0.2: {}
+
+ es-module-lexer@1.7.0: {}
+
+ esbuild@0.21.5:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.21.5
+ '@esbuild/android-arm': 0.21.5
+ '@esbuild/android-arm64': 0.21.5
+ '@esbuild/android-x64': 0.21.5
+ '@esbuild/darwin-arm64': 0.21.5
+ '@esbuild/darwin-x64': 0.21.5
+ '@esbuild/freebsd-arm64': 0.21.5
+ '@esbuild/freebsd-x64': 0.21.5
+ '@esbuild/linux-arm': 0.21.5
+ '@esbuild/linux-arm64': 0.21.5
+ '@esbuild/linux-ia32': 0.21.5
+ '@esbuild/linux-loong64': 0.21.5
+ '@esbuild/linux-mips64el': 0.21.5
+ '@esbuild/linux-ppc64': 0.21.5
+ '@esbuild/linux-riscv64': 0.21.5
+ '@esbuild/linux-s390x': 0.21.5
+ '@esbuild/linux-x64': 0.21.5
+ '@esbuild/netbsd-x64': 0.21.5
+ '@esbuild/openbsd-x64': 0.21.5
+ '@esbuild/sunos-x64': 0.21.5
+ '@esbuild/win32-arm64': 0.21.5
+ '@esbuild/win32-ia32': 0.21.5
+ '@esbuild/win32-x64': 0.21.5
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.9
+
+ expect-type@1.4.0: {}
+
+ fsevents@2.3.3:
+ optional: true
+
+ js-tokens@4.0.0: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ loupe@3.2.1: {}
+
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ ms@2.1.3: {}
+
+ nanoid@3.3.15: {}
+
+ pathe@1.1.2: {}
+
+ pathval@2.0.1: {}
+
+ picocolors@1.1.1: {}
+
+ postcss@8.5.16:
+ dependencies:
+ nanoid: 3.3.15
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ react-dom@18.3.1(react@18.3.1):
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.3.1
+ scheduler: 0.23.2
+
+ react@18.3.1:
+ dependencies:
+ loose-envify: 1.4.0
+
+ rollup@4.62.2:
+ dependencies:
+ '@types/estree': 1.0.9
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.62.2
+ '@rollup/rollup-android-arm64': 4.62.2
+ '@rollup/rollup-darwin-arm64': 4.62.2
+ '@rollup/rollup-darwin-x64': 4.62.2
+ '@rollup/rollup-freebsd-arm64': 4.62.2
+ '@rollup/rollup-freebsd-x64': 4.62.2
+ '@rollup/rollup-linux-arm-gnueabihf': 4.62.2
+ '@rollup/rollup-linux-arm-musleabihf': 4.62.2
+ '@rollup/rollup-linux-arm64-gnu': 4.62.2
+ '@rollup/rollup-linux-arm64-musl': 4.62.2
+ '@rollup/rollup-linux-loong64-gnu': 4.62.2
+ '@rollup/rollup-linux-loong64-musl': 4.62.2
+ '@rollup/rollup-linux-ppc64-gnu': 4.62.2
+ '@rollup/rollup-linux-ppc64-musl': 4.62.2
+ '@rollup/rollup-linux-riscv64-gnu': 4.62.2
+ '@rollup/rollup-linux-riscv64-musl': 4.62.2
+ '@rollup/rollup-linux-s390x-gnu': 4.62.2
+ '@rollup/rollup-linux-x64-gnu': 4.62.2
+ '@rollup/rollup-linux-x64-musl': 4.62.2
+ '@rollup/rollup-openbsd-x64': 4.62.2
+ '@rollup/rollup-openharmony-arm64': 4.62.2
+ '@rollup/rollup-win32-arm64-msvc': 4.62.2
+ '@rollup/rollup-win32-ia32-msvc': 4.62.2
+ '@rollup/rollup-win32-x64-gnu': 4.62.2
+ '@rollup/rollup-win32-x64-msvc': 4.62.2
+ fsevents: 2.3.3
+
+ scheduler@0.23.2:
+ dependencies:
+ loose-envify: 1.4.0
+
+ siginfo@2.0.0: {}
+
+ source-map-js@1.2.1: {}
+
+ stackback@0.0.2: {}
+
+ std-env@3.10.0: {}
+
+ tinybench@2.9.0: {}
+
+ tinyexec@0.3.2: {}
+
+ tinypool@1.1.1: {}
+
+ tinyrainbow@1.2.0: {}
+
+ tinyspy@3.0.2: {}
+
+ typescript@5.9.3: {}
+
+ vite-node@2.1.9:
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.3
+ es-module-lexer: 1.7.0
+ pathe: 1.1.2
+ vite: 5.4.21
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
+ vite@5.4.21:
+ dependencies:
+ esbuild: 0.21.5
+ postcss: 8.5.16
+ rollup: 4.62.2
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ vitest@2.1.9:
+ dependencies:
+ '@vitest/expect': 2.1.9
+ '@vitest/mocker': 2.1.9(vite@5.4.21)
+ '@vitest/pretty-format': 2.1.9
+ '@vitest/runner': 2.1.9
+ '@vitest/snapshot': 2.1.9
+ '@vitest/spy': 2.1.9
+ '@vitest/utils': 2.1.9
+ chai: 5.3.3
+ debug: 4.4.3
+ expect-type: 1.4.0
+ magic-string: 0.30.21
+ pathe: 1.1.2
+ std-env: 3.10.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinypool: 1.1.1
+ tinyrainbow: 1.2.0
+ vite: 5.4.21
+ vite-node: 2.1.9
+ why-is-node-running: 2.3.0
+ transitivePeerDependencies:
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
+ why-is-node-running@2.3.0:
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
diff --git a/benchmarks/eval/fixture/sdd.yaml b/benchmarks/eval/fixture/sdd.yaml
new file mode 100644
index 00000000..9e8f5b44
--- /dev/null
+++ b/benchmarks/eval/fixture/sdd.yaml
@@ -0,0 +1,65 @@
+# FrontAgent SDD 配置文件(评测夹具冻结版)
+# 规格驱动开发 - Agent 行为约束
+
+version: "1.0"
+
+project:
+ name: "eval-fixture"
+ type: "react-spa"
+ description: "架构消融评测的冻结夹具工程"
+
+# 技术栈约束
+tech_stack:
+ framework: "react"
+ version: "^18.0.0"
+ language: "typescript"
+ styling: "css"
+ state_management: "none"
+ forbidden_packages:
+ - "jquery"
+ - "moment"
+
+# 目录结构约束
+directory_structure:
+ src/components:
+ pattern: "PascalCase"
+ max_lines: 300
+ src/hooks:
+ pattern: "use*.ts"
+ src/utils:
+ pattern: "camelCase"
+ must_be_pure: true
+
+# 模块边界约束
+module_boundaries:
+ - from: "src/components/*"
+ can_import:
+ - "src/hooks/*"
+ - "src/utils/*"
+ cannot_import:
+ - "src/api/*"
+
+# 命名规范
+naming_conventions:
+ components: "PascalCase"
+ hooks: "camelCase with 'use' prefix"
+ utils: "camelCase"
+ constants: "SCREAMING_SNAKE_CASE"
+
+# 代码质量约束
+code_quality:
+ max_function_lines: 50
+ max_file_lines: 300
+ max_parameters: 4
+ forbidden_patterns:
+ - "any"
+ - "// @ts-ignore"
+ - "console.log"
+
+# 修改安全边界
+modification_rules:
+ protected_files:
+ - "package.json"
+ - "tsconfig.json"
+ protected_directories:
+ - "node_modules"
diff --git a/benchmarks/eval/fixture/src/App.tsx b/benchmarks/eval/fixture/src/App.tsx
new file mode 100644
index 00000000..955fb8ad
--- /dev/null
+++ b/benchmarks/eval/fixture/src/App.tsx
@@ -0,0 +1,12 @@
+import { Button } from "./components/Button";
+import { TodoList } from "./components/TodoList";
+
+export default function App() {
+ return (
+
+ Eval Fixture
+
+ );
+}
diff --git a/benchmarks/eval/fixture/src/components/Button.tsx b/benchmarks/eval/fixture/src/components/Button.tsx
new file mode 100644
index 00000000..ccfd627e
--- /dev/null
+++ b/benchmarks/eval/fixture/src/components/Button.tsx
@@ -0,0 +1,12 @@
+interface ButtonProps {
+ label: string;
+ onClick: () => void;
+}
+
+export function Button({ label, onClick }: ButtonProps) {
+ return (
+
+ );
+}
diff --git a/benchmarks/eval/fixture/src/components/TodoList.tsx b/benchmarks/eval/fixture/src/components/TodoList.tsx
new file mode 100644
index 00000000..413bffbf
--- /dev/null
+++ b/benchmarks/eval/fixture/src/components/TodoList.tsx
@@ -0,0 +1,13 @@
+interface TodoListProps {
+ items: string[];
+}
+
+export function TodoList({ items }: TodoListProps) {
+ return (
+
+ {items.map((item) => (
+ - {item}
+ ))}
+
+ );
+}
diff --git a/benchmarks/eval/fixture/src/hooks/useToggle.ts b/benchmarks/eval/fixture/src/hooks/useToggle.ts
new file mode 100644
index 00000000..69996e59
--- /dev/null
+++ b/benchmarks/eval/fixture/src/hooks/useToggle.ts
@@ -0,0 +1,7 @@
+import { useState } from "react";
+
+export function useToggle(initial = false): [boolean, () => void] {
+ const [on, setOn] = useState(initial);
+ const toggle = () => setOn((v) => !v);
+ return [on, toggle];
+}
diff --git a/benchmarks/eval/fixture/src/utils/clamp.test.ts b/benchmarks/eval/fixture/src/utils/clamp.test.ts
new file mode 100644
index 00000000..6de3d222
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/clamp.test.ts
@@ -0,0 +1,14 @@
+import { describe, expect, it } from "vitest";
+import { clamp } from "./clamp";
+
+describe("clamp", () => {
+ it("小于下界取下界", () => {
+ expect(clamp(-1, 0, 10)).toBe(0);
+ });
+ it("大于上界取上界", () => {
+ expect(clamp(11, 0, 10)).toBe(10);
+ });
+ it("区间内原样返回", () => {
+ expect(clamp(5, 0, 10)).toBe(5);
+ });
+});
diff --git a/benchmarks/eval/fixture/src/utils/clamp.ts b/benchmarks/eval/fixture/src/utils/clamp.ts
new file mode 100644
index 00000000..2e041e39
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/clamp.ts
@@ -0,0 +1,5 @@
+export function clamp(value: number, min: number, max: number): number {
+ if (value < min) return min;
+ if (value > max) return min;
+ return value;
+}
diff --git a/benchmarks/eval/fixture/src/utils/formatDate.test.ts b/benchmarks/eval/fixture/src/utils/formatDate.test.ts
new file mode 100644
index 00000000..d75a99cd
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/formatDate.test.ts
@@ -0,0 +1,8 @@
+import { describe, expect, it } from "vitest";
+import { formatDate } from "./formatDate";
+
+describe("formatDate", () => {
+ it("格式化为 YYYY-MM-DD", () => {
+ expect(formatDate(new Date(2026, 6, 11))).toBe("2026-07-11");
+ });
+});
diff --git a/benchmarks/eval/fixture/src/utils/formatDate.ts b/benchmarks/eval/fixture/src/utils/formatDate.ts
new file mode 100644
index 00000000..0c5aeae1
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/formatDate.ts
@@ -0,0 +1,6 @@
+export function formatDate(d: Date): string {
+ const y = d.getFullYear();
+ const m = String(d.getMonth()).padStart(2, "0");
+ const day = String(d.getDate()).padStart(2, "0");
+ return `${y}-${m}-${day}`;
+}
diff --git a/benchmarks/eval/fixture/src/utils/parseQuery.test.ts b/benchmarks/eval/fixture/src/utils/parseQuery.test.ts
new file mode 100644
index 00000000..20327945
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/parseQuery.test.ts
@@ -0,0 +1,14 @@
+import { describe, expect, it } from "vitest";
+import { parseQuery } from "./parseQuery";
+
+describe("parseQuery", () => {
+ it("解析问号前缀查询串", () => {
+ expect(parseQuery("?a=1&b=2")).toEqual({ a: "1", b: "2" });
+ });
+ it("URL 编码的值要解码", () => {
+ expect(parseQuery("q=hello%20world")).toEqual({ q: "hello world" });
+ });
+ it("空串返回空对象", () => {
+ expect(parseQuery("")).toEqual({});
+ });
+});
diff --git a/benchmarks/eval/fixture/src/utils/parseQuery.ts b/benchmarks/eval/fixture/src/utils/parseQuery.ts
new file mode 100644
index 00000000..56c25ef1
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/parseQuery.ts
@@ -0,0 +1,10 @@
+export function parseQuery(query: string): Record {
+ const result: Record = {};
+ const trimmed = query.startsWith("?") ? query.slice(1) : query;
+ if (!trimmed) return result;
+ for (const pair of trimmed.split("&")) {
+ const [key, value] = pair.split("=");
+ if (key) result[key] = value ?? "";
+ }
+ return result;
+}
diff --git a/benchmarks/eval/fixture/src/utils/pluralize.test.ts b/benchmarks/eval/fixture/src/utils/pluralize.test.ts
new file mode 100644
index 00000000..3615c7d6
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/pluralize.test.ts
@@ -0,0 +1,11 @@
+import { describe, expect, it } from "vitest";
+import { pluralize } from "./pluralize";
+
+describe("pluralize", () => {
+ it("单数不加 s", () => {
+ expect(pluralize("item", 1)).toBe("1 item");
+ });
+ it("复数加 s", () => {
+ expect(pluralize("item", 2)).toBe("2 items");
+ });
+});
diff --git a/benchmarks/eval/fixture/src/utils/pluralize.ts b/benchmarks/eval/fixture/src/utils/pluralize.ts
new file mode 100644
index 00000000..9a508037
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/pluralize.ts
@@ -0,0 +1,3 @@
+export function pluralize(word: string, count: number): string {
+ return `${count} ${word}s`;
+}
diff --git a/benchmarks/eval/fixture/src/utils/truncate.test.ts b/benchmarks/eval/fixture/src/utils/truncate.test.ts
new file mode 100644
index 00000000..d7899466
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/truncate.test.ts
@@ -0,0 +1,11 @@
+import { describe, expect, it } from "vitest";
+import { truncate } from "./truncate";
+
+describe("truncate", () => {
+ it("不超长原样返回", () => {
+ expect(truncate("abc", 5)).toBe("abc");
+ });
+ it("超长截到 maxLength 并加省略号", () => {
+ expect(truncate("abcdefg", 3)).toBe("abc…");
+ });
+});
diff --git a/benchmarks/eval/fixture/src/utils/truncate.ts b/benchmarks/eval/fixture/src/utils/truncate.ts
new file mode 100644
index 00000000..fd40a93c
--- /dev/null
+++ b/benchmarks/eval/fixture/src/utils/truncate.ts
@@ -0,0 +1,4 @@
+export function truncate(text: string, maxLength: number): string {
+ if (text.length <= maxLength) return text;
+ return `${text.slice(0, maxLength + 1)}…`;
+}
diff --git a/benchmarks/eval/fixture/tsconfig.json b/benchmarks/eval/fixture/tsconfig.json
new file mode 100644
index 00000000..9714625a
--- /dev/null
+++ b/benchmarks/eval/fixture/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "jsx": "react-jsx",
+ "strict": true,
+ "skipLibCheck": true,
+ "noEmit": true
+ },
+ "include": ["src"]
+}
diff --git a/benchmarks/eval/out-smoke/ablation.jsonl b/benchmarks/eval/out-smoke/ablation.jsonl
new file mode 100644
index 00000000..d1f42090
--- /dev/null
+++ b/benchmarks/eval/out-smoke/ablation.jsonl
@@ -0,0 +1,5 @@
+{"taskId":"query-button-props","category":"query","arm":"ablation","pass":false,"agentSuccess":true,"validationCount":1,"runError":null,"checks":[{"kind":"result_contains","ok":false,"detail":"label"},{"kind":"result_contains","ok":true,"detail":"onClick"}],"events":{"task_started":1,"status_update":15,"security_decision":4,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":150729,"llmCalls":1,"llmFailures":0,"inputTokens":10,"outputTokens":952}
+{"taskId":"create-usedebounce","category":"create","arm":"ablation","pass":false,"agentSuccess":false,"validationCount":3,"runError":null,"checks":[{"kind":"file_exists","ok":false,"detail":"src/hooks/useDebounce.ts"},{"kind":"file_contains","ok":false,"detail":"missing src/hooks/useDebounce.ts"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":5,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":2,"phase_completed":2,"step_failed":1,"task_completed":1},"elapsedMs":465285,"llmCalls":12,"llmFailures":1,"inputTokens":120,"outputTokens":29639}
+{"taskId":"create-checkbox","category":"create","arm":"ablation","pass":true,"agentSuccess":true,"validationCount":3,"runError":null,"checks":[{"kind":"file_exists","ok":true,"detail":"src/components/Checkbox.tsx"},{"kind":"file_contains","ok":true,"detail":"onChange"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":7,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":323016,"llmCalls":7,"llmFailures":0,"inputTokens":70,"outputTokens":18788}
+{"taskId":"bugfix-formatdate","category":"bugfix","arm":"ablation","pass":true,"agentSuccess":true,"validationCount":2,"runError":null,"checks":[{"kind":"cmd","ok":true,"detail":"npx vitest run src/utils/formatDate.test.ts"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":8,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":253827,"llmCalls":7,"llmFailures":0,"inputTokens":70,"outputTokens":11270}
+{"taskId":"refactor-todolist-empty","category":"refactor","arm":"ablation","pass":false,"agentSuccess":true,"validationCount":2,"runError":null,"checks":[{"kind":"file_contains","ok":false,"detail":"暂无待办"},{"kind":"typecheck","ok":false,"detail":"src/components/TodoList.tsx(1,1): error TS1434: Unexpected keyword or identifier.\nsrc/components/TodoList.tsx(1,16): error TS1005: ';' expected.\nsrc/components/TodoList.tsx(1,31): error TS1127: Invalid character.\nsrc/components/TodoList.tsx(1,42): error TS1127: Invalid character.\nsrc/components/Todo"}],"events":{"task_started":1,"status_update":21,"security_decision":8,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":322254,"llmCalls":7,"llmFailures":0,"inputTokens":70,"outputTokens":16738}
diff --git a/benchmarks/eval/out-smoke/full.jsonl b/benchmarks/eval/out-smoke/full.jsonl
new file mode 100644
index 00000000..a79e2c65
--- /dev/null
+++ b/benchmarks/eval/out-smoke/full.jsonl
@@ -0,0 +1,5 @@
+{"taskId":"query-button-props","category":"query","arm":"full","pass":false,"agentSuccess":true,"validationCount":1,"runError":null,"checks":[{"kind":"result_contains","ok":false,"detail":"label"},{"kind":"result_contains","ok":false,"detail":"onClick"}],"events":{"task_started":1,"status_update":15,"security_decision":4,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":140240,"llmCalls":1,"llmFailures":0,"inputTokens":10,"outputTokens":577}
+{"taskId":"create-usedebounce","category":"create","arm":"full","pass":false,"agentSuccess":false,"validationCount":3,"runError":null,"checks":[{"kind":"file_exists","ok":false,"detail":"src/hooks/useDebounce.ts"},{"kind":"file_contains","ok":false,"detail":"missing src/hooks/useDebounce.ts"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":5,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":2,"phase_completed":2,"step_failed":1,"task_completed":1},"elapsedMs":393303,"llmCalls":9,"llmFailures":1,"inputTokens":90,"outputTokens":23821}
+{"taskId":"create-checkbox","category":"create","arm":"full","pass":false,"agentSuccess":false,"validationCount":3,"runError":null,"checks":[{"kind":"file_exists","ok":false,"detail":"src/components/Checkbox.tsx"},{"kind":"file_contains","ok":false,"detail":"missing src/components/Checkbox.tsx"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":5,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":2,"phase_completed":2,"step_failed":1,"task_completed":1},"elapsedMs":478316,"llmCalls":12,"llmFailures":1,"inputTokens":120,"outputTokens":33917}
+{"taskId":"bugfix-formatdate","category":"bugfix","arm":"full","pass":true,"agentSuccess":true,"validationCount":2,"runError":null,"checks":[{"kind":"cmd","ok":true,"detail":"npx vitest run src/utils/formatDate.test.ts"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":8,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":256759,"llmCalls":7,"llmFailures":0,"inputTokens":70,"outputTokens":10789}
+{"taskId":"refactor-todolist-empty","category":"refactor","arm":"full","pass":false,"agentSuccess":true,"validationCount":2,"runError":null,"checks":[{"kind":"file_contains","ok":false,"detail":"暂无待办"},{"kind":"typecheck","ok":false,"detail":"src/components/TodoList.tsx(1,13): error TS1127: Invalid character.\nsrc/components/TodoList.tsx(1,14): error TS1434: Unexpected keyword or identifier.\nsrc/components/TodoList.tsx(1,57): error TS1127: Invalid character.\nsrc/components/TodoList.tsx(1,69): error TS1127: Invalid character.\nsrc/component"}],"events":{"task_started":1,"status_update":21,"security_decision":8,"rag_retrieved":1,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":275785,"llmCalls":7,"llmFailures":0,"inputTokens":70,"outputTokens":13672}
diff --git a/benchmarks/eval/out/ablation.jsonl b/benchmarks/eval/out/ablation.jsonl
new file mode 100644
index 00000000..b69addb7
--- /dev/null
+++ b/benchmarks/eval/out/ablation.jsonl
@@ -0,0 +1,27 @@
+{"taskId":"query-button-props","category":"query","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"# Button 组件 Props 说明\n\n根据当前工作区文件 `src/components/Button.tsx`,Button 组件接受以下 props:\n\n| Prop | 类型 | 用途 |\n|------|------|------|\n| **label** | `string` | 按钮显示的文本内容 |\n| **onClick** | `() => void` | 按钮点击时的回调","checks":[{"kind":"result_contains","ok":true,"detail":"label"},{"kind":"result_contains","ok":true,"detail":"onClick"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":7483,"llmCalls":1,"llmFailures":0,"inputTokens":991,"outputTokens":440}
+{"taskId":"query-structure","category":"query","arm":"ablation","pass":false,"agentSuccess":true,"agentError":null,"validationCount":2,"runError":null,"resultHead":"我无法直接列出 src 下的目录结构及其职责。\n\n**原因是**:提供的证据中没有包含关于 src 目录结构的信息。既没有知识库条目描述项目结构,也没有当前工作区文件的内容。\n\n**建议**:\n- 如果你需要我分析项目结构,需要先提供 src 目录的实际内容或文件清单\n- 或者提供项目的架构文档、README 等说明性文件作为参考\n\n我是 FrontAgent,具备分析和解释前端项目结构的能力,一","checks":[{"kind":"result_contains","ok":false,"detail":"components"},{"kind":"result_contains","ok":false,"detail":"hooks"},{"kind":"result_contains","ok":false,"detail":"utils"}],"events":{"task_started":1,"status_update":16,"security_decision":4,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":2,"step_completed":2,"phase_completed":2,"filesense_navigated":1,"task_completed":1},"elapsedMs":7870,"llmCalls":1,"llmFailures":0,"inputTokens":907,"outputTokens":506}
+{"taskId":"query-todolist-render","category":"query","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"## 答案\n\nTodoList 组件使用 **`.map()` 遍历列表项数组**,并将每个项渲染为 `` 元素;**列表项的 key 使用的是 `item` 本身(字符串值)**。\n\n## 说明\n\n根据当前工作区文件 `src/components/TodoList.tsx` 的实现:\n\n```tsx\n{items.map((item) => (\n {it","checks":[{"kind":"result_contains","ok":true,"detail":"key"},{"kind":"result_contains","ok":true,"detail":"item"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":8904,"llmCalls":1,"llmFailures":0,"inputTokens":1005,"outputTokens":625}
+{"taskId":"query-usetoggle-behavior","category":"query","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"# useToggle Hook 返回值和状态切换说明\n\n## 返回值\n\n根据当前工作区文件 `src/hooks/useToggle.ts`,**useToggle 返回一个元组 `[boolean, () => void]`**:\n\n1. **第一项**:当前的布尔状态值(on/off)\n2. **第二项**:触发切换的函数\n\n```typescript\n[on, toggle]\n```\n\n#","checks":[{"kind":"result_contains","ok":true,"detail":"toggle"},{"kind":"result_contains","ok":true,"detail":"useState"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":8740,"llmCalls":1,"llmFailures":0,"inputTokens":994,"outputTokens":629}
+{"taskId":"query-app-components","category":"query","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"# 回答\n\n根据当前工作区文件 `src/App.tsx`,**App 组件直接使用了 2 个子组件**:\n\n1. **Button** —— 来自 `./components/Button`,在 JSX 中调用时传入了 `label` 和 `onClick` 属性\n2. **TodoList** —— 来自 `./components/TodoList`,在 JSX 中调用时传入了 `items","checks":[{"kind":"result_contains","ok":true,"detail":"Button"},{"kind":"result_contains","ok":true,"detail":"TodoList"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":8061,"llmCalls":1,"llmFailures":0,"inputTokens":1009,"outputTokens":493}
+{"taskId":"query-formatdate-io","category":"query","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"# 答案\n\n根据当前工作区文件 `src/utils/formatDate.ts` 的定义:\n\n**输入类型**:`Date` 对象\n\n**输出类型和格式**:`string` 类型,格式为 `YYYY-MM-DD`(例如 `2026-07-12`)\n\n## 原理说明\n\n该函数接收一个 JavaScript 的 `Date` 对象,通过以下步骤生成格式化字符串:\n- 提取年份(`getFullYe","checks":[{"kind":"result_contains","ok":true,"detail":"Date"},{"kind":"result_contains","ok":true,"detail":"string|字符串"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":9440,"llmCalls":1,"llmFailures":0,"inputTokens":1004,"outputTokens":681}
+{"taskId":"query-tsconfig-strict","category":"query","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"# 答案\n\n**strict 已开启**。\n\n根据当前工作区文件 `tsconfig.json`,该项目开启了以下编译选项:\n\n| 选项 | 值 |\n|------|------|\n| `target` | ES2022 |\n| `module` | ESNext |\n| `moduleResolution` | bundler |\n| `jsx` | react-jsx |\n| **`stric","checks":[{"kind":"result_contains","ok":true,"detail":"strict"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":8116,"llmCalls":1,"llmFailures":0,"inputTokens":1013,"outputTokens":519}
+{"taskId":"query-clamp-purpose","category":"query","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"# clamp 函数说明\n\n**结论:** `clamp` 函数用于将一个数值限制在指定的最小值和最大值范围内。\n\n## 三个参数含义\n\n根据当前工作区文件 `src/utils/clamp.ts` 的实现:\n\n| 参数 | 类型 | 含义 |\n|------|------|------|\n| `value` | number | 要被限制的原始值 |\n| `min` | number | 允许的","checks":[{"kind":"result_contains","ok":true,"detail":"min"},{"kind":"result_contains","ok":true,"detail":"max"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":10896,"llmCalls":1,"llmFailures":0,"inputTokens":975,"outputTokens":791}
+{"taskId":"query-test-files","category":"query","arm":"ablation","pass":false,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"我无法直接回答这个问题。\n\n**原因**:当前的可用证据中,除了我的智能体身份定义外,**没有提供任何关于项目测试文件的知识库条目或当前工作区文件信息**。\n\n要回答\"项目里有哪些测试文件?分别测试什么?\"这样的问题,我需要:\n- 当前工作区的实际文件访问权限(特别是 `test/`、`__tests__/`、`.spec.js` 等测试文件)\n- 或相关的项目文档/知识库条目\n\n**建议**:\n","checks":[{"kind":"result_contains","ok":false,"detail":"formatDate"},{"kind":"result_contains","ok":false,"detail":"clamp"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":9798,"llmCalls":1,"llmFailures":0,"inputTokens":904,"outputTokens":588}
+{"taskId":"query-button-export","category":"query","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":2,"runError":null,"resultHead":"## 结论\n\n- **Button 组件**是**命名导出**\n- **App 组件**是**默认导出**\n\n## 证据\n\n来自当前工作区文件:\n\n1. **Button.tsx** 使用 `export function Button`:\n ```typescript\n export function Button({ label, onClick }: ButtonProps) { .","checks":[{"kind":"result_contains","ok":true,"detail":"命名|named"},{"kind":"result_contains","ok":true,"detail":"默认|default"}],"events":{"task_started":1,"status_update":15,"security_decision":4,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":8161,"llmCalls":1,"llmFailures":0,"inputTokens":1089,"outputTokens":504}
+{"taskId":"create-usedebounce","category":"create","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":3,"runError":null,"resultHead":"执行完成 (3/3 步骤成功)\n\n✅ 按需构建目录导航上下文:create task benefits from nearby placement conventions\n✅ 检查目标路径 src/hooks/useDebounce.ts 是否已存在\n✅ 创建文件 src/hooks/useDebounce.ts","checks":[{"kind":"file_exists","ok":true,"detail":"src/hooks/useDebounce.ts"},{"kind":"file_contains","ok":true,"detail":"export function useDebounce"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":6,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":322182,"llmCalls":9,"llmFailures":0,"inputTokens":18548,"outputTokens":37610}
+{"taskId":"create-card","category":"create","arm":"ablation","pass":false,"agentSuccess":true,"agentError":null,"validationCount":3,"runError":null,"resultHead":"执行完成 (3/3 步骤成功)\n\n✅ 按需构建目录导航上下文:create task benefits from nearby placement conventions\n✅ 检查目标路径 src/components/Card.tsx 是否已存在\n✅ 创建文件 src/components/Card.tsx","checks":[{"kind":"file_exists","ok":true,"detail":"src/components/Card.tsx"},{"kind":"file_contains","ok":false,"detail":"export function Card"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":6,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":374622,"llmCalls":9,"llmFailures":0,"inputTokens":18285,"outputTokens":40257}
+{"taskId":"create-capitalize","category":"create","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":3,"runError":null,"resultHead":"执行完成 (3/3 步骤成功)\n\n✅ 按需构建目录导航上下文:create task benefits from nearby placement conventions\n✅ 检查目标路径 src/utils/capitalize.ts 是否已存在\n✅ 创建文件 src/utils/capitalize.ts","checks":[{"kind":"file_exists","ok":true,"detail":"src/utils/capitalize.ts"},{"kind":"file_contains","ok":true,"detail":"export function capitalize"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":6,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":313715,"llmCalls":8,"llmFailures":0,"inputTokens":15648,"outputTokens":33029}
+{"taskId":"create-uselocalstorage","category":"create","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":3,"runError":null,"resultHead":"执行完成 (3/3 步骤成功)\n\n✅ 按需构建目录导航上下文:create task benefits from nearby placement conventions\n✅ 检查目标路径 src/hooks/useLocalStorage.ts 是否已存在\n✅ 创建文件 src/hooks/useLocalStorage.ts","checks":[{"kind":"file_exists","ok":true,"detail":"src/hooks/useLocalStorage.ts"},{"kind":"file_contains","ok":true,"detail":"export function useLocalStorage"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":6,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":349031,"llmCalls":9,"llmFailures":0,"inputTokens":18493,"outputTokens":37339}
+{"taskId":"create-badge","category":"create","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":3,"runError":null,"resultHead":"执行完成 (3/3 步骤成功)\n\n✅ 按需构建目录导航上下文:create task benefits from nearby placement conventions\n✅ 检查目标路径 src/components/Badge.tsx 是否已存在\n✅ 创建文件 src/components/Badge.tsx","checks":[{"kind":"file_exists","ok":true,"detail":"src/components/Badge.tsx"},{"kind":"file_contains","ok":true,"detail":"variant"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":6,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":301683,"llmCalls":4,"llmFailures":2,"inputTokens":7855,"outputTokens":14848}
+{"taskId":"create-formatcurrency","category":"create","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":3,"runError":null,"resultHead":"执行完成 (3/3 步骤成功)\n\n✅ 按需构建目录导航上下文:create task benefits from nearby placement conventions\n✅ 检查目标路径 src/utils/formatCurrency.ts 是否已存在\n✅ 创建文件 src/utils/formatCurrency.ts","checks":[{"kind":"file_exists","ok":true,"detail":"src/utils/formatCurrency.ts"},{"kind":"file_contains","ok":true,"detail":"export function formatCurrency"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":6,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":435109,"llmCalls":9,"llmFailures":0,"inputTokens":18113,"outputTokens":48064}
+{"taskId":"create-spinner","category":"create","arm":"ablation","pass":false,"agentSuccess":false,"agentError":"Syntax errors found in src/components/Spinner.tsx","validationCount":3,"runError":null,"resultHead":"","checks":[{"kind":"file_exists","ok":true,"detail":"src/components/Spinner.tsx"},{"kind":"file_contains","ok":false,"detail":"export function Spinner"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":5,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":2,"phase_completed":2,"step_failed":1,"task_completed":1},"elapsedMs":630159,"llmCalls":12,"llmFailures":0,"inputTokens":23991,"outputTokens":61670}
+{"taskId":"create-useinterval","category":"create","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":3,"runError":null,"resultHead":"执行完成 (3/3 步骤成功)\n\n✅ 按需构建目录导航上下文:create task benefits from nearby placement conventions\n✅ 检查目标路径 src/hooks/useInterval.ts 是否已存在\n✅ 创建文件 src/hooks/useInterval.ts","checks":[{"kind":"file_exists","ok":true,"detail":"src/hooks/useInterval.ts"},{"kind":"file_contains","ok":true,"detail":"useEffect"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":6,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":457924,"llmCalls":9,"llmFailures":0,"inputTokens":18206,"outputTokens":40463}
+{"taskId":"create-slugify","category":"create","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":3,"runError":null,"resultHead":"执行完成 (3/3 步骤成功)\n\n✅ 按需构建目录导航上下文:create task benefits from nearby placement conventions\n✅ 检查目标路径 src/utils/slugify.ts 是否已存在\n✅ 创建文件 src/utils/slugify.ts","checks":[{"kind":"file_exists","ok":true,"detail":"src/utils/slugify.ts"},{"kind":"file_contains","ok":true,"detail":"export function slugify"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":6,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":314668,"llmCalls":8,"llmFailures":0,"inputTokens":15472,"outputTokens":30378}
+{"taskId":"create-checkbox","category":"create","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":3,"runError":null,"resultHead":"执行完成 (3/3 步骤成功)\n\n✅ 按需构建目录导航上下文:create task benefits from nearby placement conventions\n✅ 检查目标路径 src/components/Checkbox.tsx 是否已存在\n✅ 创建文件 src/components/Checkbox.tsx","checks":[{"kind":"file_exists","ok":true,"detail":"src/components/Checkbox.tsx"},{"kind":"file_contains","ok":true,"detail":"onChange"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":20,"security_decision":6,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":3,"filesense_navigated":1,"step_completed":3,"phase_completed":2,"task_completed":1},"elapsedMs":391073,"llmCalls":10,"llmFailures":0,"inputTokens":21029,"outputTokens":42355}
+{"taskId":"bugfix-formatdate","category":"bugfix","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":2,"runError":null,"resultHead":"执行完成 (2/2 步骤成功)\n\n✅ 分析文件结构 src/utils/formatDate.ts\n✅ 修改文件 src/utils/formatDate.ts","checks":[{"kind":"cmd","ok":true,"detail":"npx vitest run src/utils/formatDate.test.ts"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":7,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":298582,"llmCalls":8,"llmFailures":0,"inputTokens":14576,"outputTokens":28712}
+{"taskId":"bugfix-clamp","category":"bugfix","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":2,"runError":null,"resultHead":"执行完成 (2/2 步骤成功)\n\n✅ 分析文件结构 src/utils/clamp.ts\n✅ 修改文件 src/utils/clamp.ts","checks":[{"kind":"cmd","ok":true,"detail":"npx vitest run src/utils/clamp.test.ts"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":7,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":331327,"llmCalls":9,"llmFailures":0,"inputTokens":16884,"outputTokens":32491}
+{"taskId":"bugfix-pluralize","category":"bugfix","arm":"ablation","pass":false,"agentSuccess":true,"agentError":null,"validationCount":2,"runError":null,"resultHead":"执行完成 (2/2 步骤成功)\n\n✅ 分析文件结构 src/utils/pluralize.ts\n✅ 修改文件 src/utils/pluralize.ts","checks":[{"kind":"cmd","ok":false,"detail":"npx vitest run src/utils/pluralize.test.ts"},{"kind":"typecheck","ok":false,"detail":"src/utils/pluralize.ts(1,13): error TS1127: Invalid character.\nsrc/utils/pluralize.ts(3,1): error TS1434: Unexpected keyword or identifier.\nsrc/utils/pluralize.ts(3,11): error TS1005: ';' expected.\nsrc/utils/pluralize.ts(3,44): error TS1127: Invalid character.\nsrc/utils/pluralize.ts(3,59): error TS1"}],"events":{"task_started":1,"status_update":21,"security_decision":7,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":298556,"llmCalls":9,"llmFailures":0,"inputTokens":16921,"outputTokens":28980}
+{"taskId":"bugfix-truncate","category":"bugfix","arm":"ablation","pass":false,"agentSuccess":true,"agentError":null,"validationCount":2,"runError":null,"resultHead":"执行完成 (2/2 步骤成功)\n\n✅ 分析文件结构 src/utils/truncate.ts\n✅ 修改文件 src/utils/truncate.ts","checks":[{"kind":"cmd","ok":false,"detail":"npx vitest run src/utils/truncate.test.ts"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":7,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":338711,"llmCalls":9,"llmFailures":0,"inputTokens":16723,"outputTokens":28584}
+{"taskId":"bugfix-parsequery","category":"bugfix","arm":"ablation","pass":true,"agentSuccess":true,"agentError":null,"validationCount":2,"runError":null,"resultHead":"执行完成 (2/2 步骤成功)\n\n✅ 分析文件结构 src/utils/parseQuery.ts\n✅ 修改文件 src/utils/parseQuery.ts","checks":[{"kind":"cmd","ok":true,"detail":"npx vitest run src/utils/parseQuery.test.ts"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":21,"security_decision":7,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":394377,"llmCalls":8,"llmFailures":0,"inputTokens":14583,"outputTokens":40862}
+{"taskId":"refactor-todolist-empty","category":"refactor","arm":"ablation","pass":false,"agentSuccess":false,"agentError":"claude CLI timeout","validationCount":2,"runError":null,"resultHead":"","checks":[{"kind":"file_contains","ok":false,"detail":"暂无待办"},{"kind":"typecheck","ok":true,"detail":""}],"events":{"task_started":1,"status_update":22,"security_decision":5,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":1,"step_failed":1,"phase_completed":1,"task_completed":1},"elapsedMs":919701,"llmCalls":9,"llmFailures":3,"inputTokens":16383,"outputTokens":28668}
+{"taskId":"refactor-button-disabled","category":"refactor","arm":"ablation","pass":false,"agentSuccess":true,"agentError":null,"validationCount":2,"runError":null,"resultHead":"执行完成 (2/2 步骤成功)\n\n✅ 分析文件结构 src/components/Button.tsx\n✅ 修改文件 src/components/Button.tsx","checks":[{"kind":"file_contains","ok":true,"detail":"disabled"},{"kind":"typecheck","ok":false,"detail":"src/components/Button.tsx(1,3): error TS1127: Invalid character.\nsrc/components/Button.tsx(1,29): error TS1127: Invalid character.\nsrc/components/Button.tsx(1,30): error TS1127: Invalid character.\nsrc/components/Button.tsx(1,43): error TS1443: Module declaration names may only use ' or \" quoted stri"}],"events":{"task_started":1,"status_update":21,"security_decision":7,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":2,"step_completed":2,"phase_completed":1,"task_completed":1},"elapsedMs":376167,"llmCalls":4,"llmFailures":3,"inputTokens":7293,"outputTokens":7589}
diff --git a/benchmarks/eval/out/full.jsonl b/benchmarks/eval/out/full.jsonl
new file mode 100644
index 00000000..f1d25621
--- /dev/null
+++ b/benchmarks/eval/out/full.jsonl
@@ -0,0 +1,27 @@
+{"taskId":"query-button-props","category":"query","arm":"full","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"# Button 组件 Props 说明\n\n根据当前工作区文件 `src/components/Button.tsx` 的定义,Button 组件接受以下 props:\n\n| Prop | 类型 | 用途 |\n|------|------|------|\n| **label** | `string` | 按钮显示的文本标签 |\n| **onClick** | `() => void` | 点击按钮","checks":[{"kind":"result_contains","ok":true,"detail":"label"},{"kind":"result_contains","ok":true,"detail":"onClick"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":24151,"llmCalls":1,"llmFailures":0,"inputTokens":991,"outputTokens":550}
+{"taskId":"query-structure","category":"query","arm":"full","pass":false,"agentSuccess":true,"agentError":null,"validationCount":2,"runError":null,"resultHead":"我无法列出 src 目录的结构。\n\n**原因:** 提供的证据中不包含当前工作区的任何文件内容。我没有看到关于 src 目录的本地文件信息,也没有相关的知识库条目。\n\n**我需要:**\n1. 访问当前工作区的文件系统(查看 src 目录的实际结构)\n2. 或者你直接提供 src 目录的结构信息\n\n如果你希望我分析和说明 src 目录各子目录的职责,请:\n- 让我读取当前工作区中 src 目录下的文","checks":[{"kind":"result_contains","ok":false,"detail":"components"},{"kind":"result_contains","ok":false,"detail":"hooks"},{"kind":"result_contains","ok":false,"detail":"utils"}],"events":{"task_started":1,"status_update":16,"security_decision":4,"planning_started":1,"planning_completed":1,"phase_started":2,"step_started":2,"step_completed":2,"phase_completed":2,"filesense_navigated":1,"task_completed":1},"elapsedMs":10077,"llmCalls":1,"llmFailures":0,"inputTokens":907,"outputTokens":567}
+{"taskId":"query-todolist-render","category":"query","arm":"full","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"## 答案\n\n根据当前工作区文件 `src/components/TodoList.tsx` 的代码:\n\n**渲染方式:** TodoList 组件使用 `.map()` 方法遍历 `items` 数组,将每个 item 渲染为一个 `` 元素。\n\n**Key 值:** 列表项的 `key` 使用的是 **item 本身**(即字符串值),具体代码为:\n```tsx\nitems.map((","checks":[{"kind":"result_contains","ok":true,"detail":"key"},{"kind":"result_contains","ok":true,"detail":"item"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":9793,"llmCalls":1,"llmFailures":0,"inputTokens":1005,"outputTokens":605}
+{"taskId":"query-usetoggle-behavior","category":"query","arm":"full","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"# useToggle hook 返回和状态切换说明\n\n## 返回值\n根据当前工作区文件 `src/hooks/useToggle.ts`,**useToggle 返回一个二元组 `[boolean, () => void]`**:\n- **第一个元素**:当前的布尔状态值(初始值由参数决定,默认 `false`)\n- **第二个元素**:一个无参函数,调用它可以切换状态\n\n## 内部状态切换原理","checks":[{"kind":"result_contains","ok":true,"detail":"toggle"},{"kind":"result_contains","ok":true,"detail":"useState"}],"events":{"task_started":1,"status_update":15,"security_decision":3,"planning_started":1,"planning_completed":1,"phase_started":1,"step_started":1,"step_completed":1,"phase_completed":1,"task_completed":1},"elapsedMs":7652,"llmCalls":1,"llmFailures":0,"inputTokens":994,"outputTokens":608}
+{"taskId":"query-app-components","category":"query","arm":"full","pass":true,"agentSuccess":true,"agentError":null,"validationCount":1,"runError":null,"resultHead":"# 回答\n\nApp 组件直接使用了 **2 个子组件**:\n\n1. **Button** - 来自 `./components/Button`\n2. **TodoList** - 来自 `./components/TodoList`\n\n---\n\n## 依据\n\n根据当前工作区文件 `src/App.tsx`,App 组件在其 JSX 中直接实例化了这两个组件:\n- `